When working with images, a general procedure to follow is
Allocating Memory for an Image
To allocate an image buffer and assign the elements of an image descriptor, use the allocimage function. Allocimage allocates space for the image, including the header, palette, and image data.
Allocimage enters the correct values into the image descriptor and DIB header and the image buffer is ready to receive an image.
For example, to allocate space for a 8-bit image the following code can be used:
imgdes image1; // Define an image descriptor int width=640, length=480; // Desired image buffer size (pixels) int bppixel=8; // 8 bits per pixel // Allocate space for the image rcode = allocimage(&image1, width, length, bppixel); // If allocimage() returns an error, handle it . . . // Ready to load an image
Loading and Saving an Image
After an image buffer has been allocated, a Victor loadfile function can be called to place the image in the buffer. For example, to load an 8-bit TIFF image into the previously allocated image buffer:
rcode = loadtif("CAR.TIF", &image1);
The Victor Library supports all the popular image file formats to load and save bilevel, grayscale, and color images. Table 1 lists the supported file formats and the corresponding Victor functions.
Table 1. Image File Formats Supported by Victor | ||
Format | Function | Description |
BMP | loadbmp loadbmpfrombuffer savebmp |
loads 1-, 4-, 8-, 16-, 24-, and 32-bit saves 1-, 8-, and 24-bit |
TIFF | loadtif
loadtiffrombuffer loadtifpage loadtifpagebyindex loadtifwithalpha savetif savetifpage savetiftobuffer |
loads 1-, 4-, 8-, 16-, 24-, and 32-bit
saves 1-, 8-, and 24-bit |
EPS | saveeps | saves 8-bit |
JPEG | loadjpg
loadjpgex loadjpgfrombuffer loadjpgfrombufferex loadjpgthumbnail loadjpgthumbnailfrombuffer savejpg savejpgex savejpgtobuffer savejpgtobufferex |
loads 8- and 24-bit
saves 8- and 24-bit |
GIF | loadgif
loadgifframe loadgifframefrombuffer loadgiffrombuffer savegif savegifex savegifframe savegifframetobuffer savegiftobufferex |
loads 1- through 8-bit
saves 1- and 8-bit saves 1- through 8-bit |
PCX | loadpcx
savepcx |
loads 1-, 4-, 8-, and 24-bit
saves 1- and 8-bit |
PNG | loadpng
loadpngfrombuffer savepng savepngtobuffer |
loads 1-, 4-, 8-, 16-, 24-, and 32-bit
saves 1-, 8-, and 24-bit |
BIF | loadbif
savebif |
loads 8-bit
saves 8-bit |
TGA | loadtga
loadtgawithalpha savetga |
loads 8-, 16-, 24-, and 32-bit
saves 24-bit |
To determine the size of the image before loading and to allocate exactly the correct amount of space to hold the image use one of the fileinfo functions. For example for the TIFF image:
imgdes image1; // Define an image descriptor TiffData tdat; // TIFF info data structure int width, length; // Desired image size (pixels) int bppixel ; // 8 bits per pixel int rcode; // Get image info on the file we're to load rcode = tiffinfo(fname, &tdat); if(rcode != NO_ERROR) { MessageBox(hWnd,"Error in reading file", 0, MB_OK); return(rcode); } width = tdat.width; length = tdat.length; bppixel = tdat.vbitcount; // Allocate space for the image allocimage(&image1, width, length, bppixel); rcode = loadtif("CAR.TIF", &image1); If (rcode == NO_ERROR) // Image is in memory ready to display or processTo save an 8-bit TIFF image after processing:
rcode = savetif("NEWCAR.TIF", &image1, compression=0);
The Victor file functions automatically load and save any palette data along
with the image data.
Setting an Image Area
The coordinate system describing the image buffer places the origin, (0,0), at the upper left of the image as displayed on the computer screen. Victor functions require valid starting and ending coordinates that define the image area. The image area is defined by the image descriptor elements stx, sty, endx, and endy. All coordinates are in pixels.
Operations can be performed on any rectangular area within the image buffer. When an image buffer is allocated with allocimage, the allocation function sets the image area to include the entire image, that is:
A smaller image area can be set with the setimagearea or recttoimagearea functions. For example, to define an image area 100 x 200 within the image image1 starting at (0,0) use:
setimagearea(&image1, 0, 0, 99, 199);
To set an area based on values contained in a RECT structure:
SetRect(&rect, 0, 0, 99, 199); recttoimagearea(&rect, &image1);
Alternatively, the image area coordinates can be set with individual assignment statements:
image1.stx = 0; image1.sty = 0; image1.endx = 99; image1.endy = 199;
Modifying an Image with Victor Functions
Images may be modified using Victor image processing or manipulation functions. These functions require that source and result image descriptors be specified. The data of the source image is used to create the result image. Functions that combine two images to produce the result, like wtaverage, require an operator image descriptor as well. It is always the address of the image descriptor that is used as the argument to Victor functions.
Image data is read from the specified image area in the source buffer and written to the image area in the result buffer. If the same image descriptor can be used for both source and result, the source data will be replaced by the result data. For example, to sharpen an image and increase its brightness by 10 use:
sharpen(&image1, &image1); changebright(10, &image1, &image1);
If the source and result image areas overlap in memory (but are not identical), the source data
may be corrupted during an image processing operation by the result data. In this case, first copy
the source image area to the result image area with the copyimage function. The copyimage
function will work correctly, even if the source and result areas overlap. Then process the result
image area.
Displaying an Image
A Victor image can be displayed easily with the viewimageex function.
For example, to view the
image loaded from the TIFF file above:
HDC hDC; PAINTSTRUCT ps; HPALETTE hpal; hDC = BeginPaint(hWnd, &ps); /* Display the image beginning at (0,0) */ viewimageex(hWnd, hDC, &hpal, 0, 0, &image1,0,0,VIEWDITHER); EndPaint(hWnd, &ps);
The viewimageex function displays the image in the window and automatically uses color reduction if necessary. You can also specify the starting position for the image and the scroll positions.
Your program can also use viewimage or the Windows functions SetDIBitstoDevice, StretchDIBits, or CreateDIBitmap to display an image.
The viewimageex function automatically uses color reduction to display a 24-bit image on in a
display mode limited to 256 or fewer colors. The color reduction method will be one of the
following defined constants:
VIEWOPTPAL | creates an optimized palette | |
VIEWDITHER | a fast ordered dither using a standard palette | |
VIEWSCATTER | a diffusion scatter pattern using a standard palette |
Freeing an Image
Call freeimage to release memory associated with an image after the image is no longer needed. Failure to release memory may cause memory shortages. To release the memory associated with the image image1, use:
freeimage(&image1);
Range Checking
All functions that access an image buffer call the function checkrange_ to perform range checking. The source code for checkrange_ is included with the library in the module VICCORE.C. (All functions and variables that are used internally by Victor contain a trailing underscore as part of the name.)
If a range error occurs, the function returns BAD_RANGE (defined in VICDEFS.H). This indicates that one of the following conditions exists:
If necessary, checkrange_ also reorders x and y coordinate data so that the starting position of an area is at upper left, and the ending position is at lower right.
Range checking also includes pointer validation to make sure the image buffer address passed to Victor functions is valid. That is, that the image buffer can be read and written. This should help catch uninitialized or corrupted image descriptors before they cause General Protection Faults or access violations. If checkrange_ determines that the image buffer address is invalid, a BAD_IBUF error code will be returned.
What is a Color Palette?
In a 1- or 8-bit image, each pixel value is an index into a color lookup table -- the palette. The palette is arranged as an array of RGBQUADs, in which four bytes (blue, green, red, and reserved) represent each palette color. The byte values represent the relative intensities of blue, green, and red, and can range from 0 to 255.
For example, to access the components of an individual color, use the image descriptor element palette which points to the palette table.
red = image.palette[color_number].rgbRed; green = image.palette[color_number].rgbGreen; blue = image.palette[color_number].rgbBlue;
A 24-bit RGB image does not have a color palette since each pixel consists of blue, green, and red bytes that represent the color intensities.
Changing a Palette
Each red, green, or blue value can range from 0 (no intensity) to 255 (maximum intensity). To increase the red, green, or blue contribution of a color, add a quantity to the rgbRed, rgbGreen, or rgbBlue element of the corresponding RGBQUAD. For example, to increase by 20 the red contribution to color number 43:
red = image.palette[43].rgbRed; red = red + 20; if(red > 255) red = 255; image.palette[43].rgbRed = red;
With color palette images a quick method of brightening an image is to increase the intensity of the entire palette. To brighten an individual color add the same amount to the red, green, and blue components. To brighten an entire image add the same amount to the red, green, and blue components of every color in the palette.
For example, to brighten an image by 30:
void altermypalette(imgdes *image) { int j, red, green, blue; for(j = 0; j < 256; j++) { red = image->palette[j].rgbRed; red = red + 30; if(red > 255) red = 255; image->palette[j].rgbRed = red; green = image->palette[j].rgbGreen; green = green + 30; if(green > 255) green = 255; image->palette[j].rgbGreen = green; blue = image->palette[j].rgbBlue; blue = blue + 30; if(blue > 255) blue = 255; image->palette[j].rgbBlue = blue; } }
Displaying an Altered Palette
To redisplay the image with the altered palette, use victowinpal to create a Windows logical palette. Then select the palette into the device context and realize the palette. A palette has to be "realized" for its color entries to be added to the system palette.
HPALETTE hpal; hDC = GetDC(hWnd); // Convert palette associated with image to a Windows palette victowinpal(&image, &hpal); // Select the palette into the DC and realize the palette holdpal = SelectPalette(hDC, hpal, 0); RealizePalette(hDC); // Deselect the palette before releasing DC SelectPalette(hDC, holdpal, 0); DeleteObject(hpal); ReleaseDC(hWnd, hDC);
Color Reduction: Creating a Palette Color Image from an RGB Image
A 24-bit RGB image can be converted to an 8-bit palette color image by several Victor functions. The main reason to use color reduction is to reduce the image storage requirements. Converting an image from 24-bit to 8-bit automatically reduces the image size to one-third of the original.
The choice of color reduction function depends upon your requirements for speed of execution, image quality, and ability to display multiple images at the same time. The Victor color reduction functions and performance estimates are listed in Table 2.
Table 2. Color Reduction Functions | |||
Function | Speed | Quality | Description |
colordither(16)1 | very fast | fair | 16 standard colors |
colordither(256)1 | very fast | good | 256 standard colors |
colorscatter(16)1 | fast | fair | 16 standard colors |
colorscatter(256)1 | fast | very good | 256 standard colors |
matchcolorimage | good | varies based on palette specified | programmer specifies palette, uses error diffusion |
matchcolorimageex 2 | good | varies based on palette specified | programmer specifies palette, error diffusion is optional |
convertrgbtopal | good | excellent | creates optimum palette |
convertrgbtopalex 2 | good | excellent | creates optimum palette, diffusion is optional |
colortogray | fast | excellent | 256 shades of gray |
1 The numbers in parentheses refer to the size of the standard palette. Refer to individual function
descriptions in the Victor Library Reference for additional information.
2 These functions allow you to specify the color matching method and whether or not error diffusion scatter is used. |
To convert an RGB image into a palette color image with optimized palette and
save it as a TIFF file, use the following sequence:
// Allocate an 8-bit image allocimage(&image8, (int)rgbimage.bmh->biWidth, (int)rgbimage.bmh->biHeight, 8); // Convert RGB to 8-bit image convertrgbtopal(256, &rgbimage, &image8); savetif("ANY.TIF", &image8, compression = 0); // Save the image freeimage(&image8);
Where rgbimage is a 24-bit RGB color image and image8 is an 8-bit palette color image.
To convert an RGB image into a palette color image with an existing palette and save it as a TIFF file, use the following sequence:
// Allocate an 8-bit image allocimage(&image8, (int)rgbimage.bmh->biWidth, (int)rgbimage.bmh->biHeight, 8); // Copy an existing palette to the new image copyimagepalette(&anotherimage, &image8); // Convert RGB to 8-bit image matchcolorimage(&rgbimage, &image8); savetif("NEW.TIF", &image8, compression); // Save the image freeimage(&image8);
Where rgbimage is a 24-bit RGB color image, anotherimage is an existing image with the palette of interest, and image8 is an 8-bit palette color image.
Converting an Existing DIB to an Image
A device independent bitmap can be operated on by Victor functions if the DIB is Victor compatible and is described by an image descriptor. A Victor-compatible DIB is a DIB that is 1-, 8-, or 24-bits per pixel, uncompressed, and contains explicit RGB palette values.
To make a DIB Victor-compatible, select the function based on the type of DIB.
DIB Description | Victor Library Function | |
Victor-compatible packed DIB
1-, 8-, or 24-bits per pixel uncompressed RGB palette | setupimgdes | |
Any packed DIB | dibtoimage | |
DIB section | dibsecttoimage |
Converting a Victor-compatible packed DIB
The setupimgdes function provides an easy way to enter the correct values into an image descriptor for a Victor-compatible DIB. For example, to save an existing DIB as a TIFF image directly from the clipboard, the following code can be used:
int SaveClippingasTiff(HWND hwnd, char *fname) { unsigned char huge *dib; int rcode=NO_ERROR; HGLOBAL hMem; imgdes image; OpenClipboard(hwnd); // Open clipboard // Get DIB from clipboard hMem = GetClipboardData(CF_DIB); // Get address of DIB dib = (unsigned char huge *)GlobalLock(hMem); // Fill in an image descriptor for the Victor-compatible DIB rcode = setupimgdes(dib, &image); if(rcode == NO_ERROR) rcode = savetif(fname, &image, 0); if(hMem) // Unlock memory before closing the clipboard GlobalUnlock(hMem); CloseClipboard(); // Close the clipboard return(rcode); }
Converting any packed DIB
If a DIB is not Victor compatible (i.e., it is 4-bits per pixel or compressed), a Victor image has to be created from the DIB for Victor functions to operate on it. The dibtoimage function creates a Victor image based on any packed DIB.
In the following example, a new image is created and saved as a BMP file from a DIB on the clipboard.
int SaveClippingasBMP(HWND hwnd, char *fname) { unsigned char huge *dib; imgdes image; int rcode=NO_ERROR; HGLOBAL hMem; // Open clipboard OpenClipboard(hwnd); // Get DIB from clipboard if(hMem = GetClipboardData(CF_DIB)) { // Get address of DIB dib = (unsigned char huge *)GlobalLock(hMem); // Create a new image from the DIB rcode = dibtoimage(dib, &image); if(rcode == NO_ERROR) { savebmp(fname, &image, 0); // Free memory allocated by dibtoimage freeimage(&image); } GlobalUnlock(hMem); } CloseClipboard(); return(rcode); }
Converting a DIB Section
A DIB section is a Win 32 system object with an HBITMAP handle. To convert a DIB section into a Victor image use the dibsecttoimage function. For example, to save an existing DIB section as a TIFF file use the following:
int SaveDIBSectToTiffFile(HBITMAP hBitmap) { int rcode; imgdes timage; char *fname = "bitmap.tif"; rcode = dibsecttoimage(hBitmap, &timage); if(rcode == NO_ERROR) { // Save captured image rcode = savetif(fname, &timage, 0); freeimage(&timage); } return(rcode); }
Converting a Device Dependent Bitmap to an Image
A device dependent bitmap is a Windows system object represented by a bitmap handle. Victor functions can operate on a device dependent bitmap only if it is first converted into a Victor image. Use the ddbtoimage function to create a Victor image. For example, to save a bitmap as a TIFF file use the following:
int SaveHBitmaptoTiffFile(HBITMAP hBitmap) { int rcode; imgdes timage; char *fname = "bitmap.tif"; HPALETTE hPal = 0; rcode = ddbtoimage(hBitmap, hPal, &timage); if(rcode == NO_ERROR) { // Save captured image rcode = savetif(fname, &timage, 0); freeimage(&timage); } return(rcode); }
In the above example, a palette handle is one of the arguments to ddbtoimage. By specifying zero for the palette handle the Windows system palette is used.
Converting an Image to a Device Dependent Bitmap
In the 32-bit Victor Library an image allocated with the allocimage function has a DIB handle, that is, the hBitmap element of the image descriptor is non-zero. This hBitmap can be used wherever a device dependent bitmap handle is requested, thus eliminating the need to convert to a device dependent bitmap (DDB).
But if the hBitmap element is zero and a device dependent bitmap is required then it is necessary to convert a Victor image to a DDB. The following function creates a device dependent bitmap from a Victor image:
int ConvertImageToBitmap(HDC hDC, imgdes *image, HBITMAP *hBitmap) { int rcode; HPALETTE hPal; // Create a logical palette from Victor palette rcode = victowinpal(image, &hPal); if(rcode == NO_ERROR) { if(image->bmh->biBitCount <= 8) { // Select and realize the palette hPal = SelectPalette(hDC, hPal, 0); RealizePalette(hDC); } // Convert the DIB into a DDB // and return the DDB handle in hBitmap rcode = dibtobitmap(hDC, (UCHAR huge *)image->bmh, hBitmap); if(image->bmh->biBitCount <= 8) // Remove logpalette before releasing DC SelectPalette(hDC, hPal, 0); } return(rcode); }
The bits per pixel of the resulting bitmap is dependent upon the display mode, i.e., a 256-color
display mode produces an 8-bit DDB, and a 16-color display mode produces a 4-bit DDB. This is
independent of the bits per pixel of the source image.
Adding Graphic Elements to an Image
Graphics elements such as text, lines, rectangles, and ellipses can be added to an image using the Windows GDI functions See the Example below.
Example, Using the GDI Functions
To add graphic elements to an image use the Windows GDI functions. This is possible because the image descriptor contains a bitmap handle, hBitmap.
The function AddCaptionToImage32 uses the GDI function DrawText to add a caption to an image.
/* Add a centered caption to an image at the bottom of the image. */ int AddCaptionToImage32(HWND hWnd, imgdes *image, // Image to modify, 1-, 8-, or 24-bit char *caption) // Caption to add (null terminated) { #define FONT_SIZE 10 static LOGFONT lf = { // Use font described by LOGFONT struct 0, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Helv" }; HFONT hFont, hOldFont; HBITMAP hOldBitmap; HDC hDC, hMemDC; RECT rc; int rcode = NO_ERROR, cols, rows, captionHt, txtStartY; /* Function creates a new image large enough to hold the image and the caption text. The current image is copied into the new image and the text is added. Then the current image is deleted and replaced by the new image. */ cols = image->endx - image->stx + 1; rows = image->endy - image->sty + 1; /* Call DrawText() to determine the rectangle we need for the caption */ SetRect(&rc, 0, 0, cols - 1, 1); // Get a memory DC hDC = GetDC(hWnd); hMemDC = CreateCompatibleDC(hDC); // Set the font point size lf.lfHeight= - MulDiv(FONT_SIZE, GetDeviceCaps(hDC, LOGPIXELSY), 72); hFont = CreateFontIndirect(&lf); // Create our font hOldFont = SelectObject(hMemDC, hFont); // Select font into DC // Select bitmap into the memory DC hOldBitmap = SelectObject(hMemDC, image->hBitmap); // Don't write any text, just expand rc to hold the text DrawText(hMemDC, caption, -1, &rc, DT_CALCRECT); // Calculate the rows needed to hold the text captionHt = rc.bottom - rc.top + 1; // Set starting Y for text placement at bottom of image txtStartY = image->endy + 1 - captionHt; // Set the rect for adding caption SetRect(&rc, image->stx, txtStartY, image->stx + cols - 1, txtStartY + captionHt - 1); // This time write the text DrawText(hMemDC, caption, -1, &rc, DT_CENTER); // Restore the original bitmap and font and delete the new font SelectObject(hMemDC, hOldBitmap); DeleteObject(SelectObject(hMemDC, hOldFont)); DeleteDC(hMemDC); // Delete memory DC ReleaseDC(hWnd, hDC); return(rcode); }
Windows provides the functions SetDIBitsToDevice, StretchDIBits, CreateDIBitmap, SetDIBits,
and GetDIBits for working with device independent bitmaps. These functions can be used
directly with Victor images. The use of image descriptor elements as arguments to the Windows
functions is illustrated below.
SetDIBitsToDevice
SetDIBitsToDevice sets the bits from a DIB directly on a device context. This function copies a rectangle of image data from the DIB to a device context. To display the image beginning at (8,8) on a device context:
SetDIBitsToDevice(hdc, 8, 8, // x,y position on device context (unsigned)image.bmh->biWidth, // Image width (unsigned)image.bmh->biHeight, // Image height 0, 0, // Starting x,y in image 0U, // Starting scanline (unsigned)image.bmh->biHeight, // Number of lines to display image.ibuff, // Address of image buffer (BITMAPINFO far *)image.bmh, // Address of BITMAPINFO DIB_RGB_COLORS); // Color usage constant
StretchDIBits
StretchDIBits moves a source rectangle from a DIB into a rectangle on a device context, stretching or compressing the image data to fit the dimensions of the destination rectangle.
When using this function to stretch an image area, remember that the parameters describing the DIB's starting x and y coordinates are in an upside down system. This function assumes y = 0 is at the bottom of the image.
To resize an image area to fit a 640 x 480 area beginning at (8,8) on a device context:
StretchDIBits(hdc, 8, 8, // x,y position on device context 640, 480, // Width, height of DC rect image.stx, // Starting x in image image.bmh->biHeight - 1 - image.endy, // Starting y pos in DIB image.endx - image.stx + 1, // Image area width image.endy - image.sty + 1, // Image area height image.ibuff, // Address of image buffer (BITMAPINFO far *)image.bmh, // Address of BITMAPINFO DIB_RGB_COLORS, // Color usage constant SRCCOPY); // Raster op
CreateDIBitmap
CreateDIBitmap creates a device dependent bitmap from a DIB.
To create a device dependent bitmap from an entire image:
CreateDIBitmap(hdc, // Device context (BITMAPINFOHEADER far *)image.bmh, // BITMAPINFOHEADER CBM_INIT, // Initialize bitmap image.ibuff, // Address of image buffer (BITMAPINFO far *)image.bmh, // Address of BITMAPINFO DIB_RGB_COLORS); // Color usage constant
SetDIBits
SetDIBits sets the bits of a bitmap to the values given in a DIB. That is, this function copies a
specified number of rows of image data from a DIB to a device dependent bitmap.
GetDIBits
GetDIBits converts the bits in a device dependent bitmap into device independent format, and stores the values in a specified number of rows in a DIB. See Converting a Device Dependent Bitmap to an Image above for an example.
If GetDiBits is called with the lpBits parameter set to NULL, no image data is returned, only the biSizeImage field and color table of a BITMAPINFO structure are filled in.
The Windows clipboard is a common area for exchanging data between applications. The clipboard supports passing image data as DIB, bitmap, and palette objects.
When working with the clipboard, it is very important to remember that the clipboard maintains ownership of all objects passed to it. When passing an image to the clipboard, always pass a copy of the image. And when receiving an image from the clipboard, make a copy of the image owned by the clipboard.
Copying an Image to the Clipboard as a DIB
In the following code imagetodib allocates space for a new DIB and copies the image area into the new DIB for passing to the clipboard.
void CopyDIBToClipboard(HWND hWnd, imgdes *image) { unsigned char huge *dib; int rcode; HGLOBAL hMem; if(OpenClipboard(hWnd)) { EmptyClipboard(); // Clean clipboard of contents // Create a new DIB to pass to the clipboard rcode = imagetodib(image, &dib); if(rcode == NO_ERROR) { // Get a handle to the new DIB hMem = (HGLOBAL)GlobalHandle(dib); // Unlock the handle to the DIB // Handle passed to clipboard must be unlocked! GlobalUnlock(hMem); // Copy the DIB to the clipboard SetClipboardData(CF_DIB, hMem); CloseClipboard(); } } else MessageBox(hWnd,"Could not open clipboard", 0, MB_OK); }
Copying an Image to the Clipboard as a Bitmap
The above routine can be modified to create a device dependent bitmap. In the code that follows, the bitmap handle to be passed to the clipboard is returned in the variable hBitmap.
HBITMAP hBitmap; . . . hdc = GetDC(hWnd); // Convert image to a bitmap rcode = ConvertImageToBitmap(hdc, image, &hBitmap); if(rcode == NO_ERROR) // Copy the bitmap to the clipboard SetClipboardData(CF_BITMAP, hBitmap); ReleaseDC(hWnd, hdc);
The ConvertImageToBitmap function was presented in the earlier section, see Converting an Image
to a Device Dependent Bitmap.
Copying a Palette to the Clipboard
The victowinpal function converts the palette associated with an image into a logical palette object and enters the logical palette handle in the hPal variable. The logical palette is then copied to the clipboard.
void CopyPaletteToClipboard(HWND hWnd, imgdes *image) { HPALETTE hPal; if(OpenClipboard(hWnd)) { EmptyClipboard(); // Clean clipboard of contents // Create a PALETTE object from the image victowinpal(image, &hPal); if(hPal) { // Copy the palette to the clipboard SetClipboardData(CF_PALETTE, hPal); CloseClipboard(); } } else MessageBox(hWnd,"Could not open clipboard", 0, MB_OK); }
Pasting a DIB from the Clipboard
The dibtoimage function is used to allocate space for a new image and copy the DIB from the clipboard into the new image buffer.
// Get clipping from clipboard void PasteDIBfromClipboard(HWND hWnd, imgdes *image) { unsigned char huge *dib; int rcode=NO_ERROR; HGLOBAL hMem; if(OpenClipboard(hWnd)) { // Get DIB from clipboard if((hMem = GetClipboardData(CF_DIB)) != 0) { // Get address of DIB dib = (unsigned char huge *)GlobalLock(hMem); // Create a new image from the DIB dibtoimage(dib, image); // Unlock memory before closing GlobalUnlock(hMem); } else MessageBox(hWnd, "No DIB on clipboard", 0, MB_OK); CloseClipboard(); // Close the clipboard } else MessageBox(hWnd, "Could not open clipboard", 0, MB_OK); }
TWAIN Support
Victor TWAIN functions allow you to easily create an application to import images from any device that has a TWAIN data source (a broad range of scanners and video capture devices). An added benefit is that an optimal user interface is provided so you don't have to design a new interface for each device.
TWAIN Architecture
There are four components in the TWAIN architecture:
This relationship can be depicted as follows:
Application | | Victor TWAIN module | | TWAIN Source Manager / \ / \ Data Source 1 Data Source 2
Additional files necessary to acquire an image from a TWAIN data source are listed below.
Filename | Description |
TWAIN.DLL | TWAIN 16-bit source manager |
TWAIN_32.DLL | TWAIN 32-bit source manager |
TWUNK_32.EXE | Thunking module |
TWUNK_16.EXE | Thunking module |
MSVCRT20.DLL | Runtime library used by the source manager |
xxx.DS | TWAIN 16- or 32-bit data source for device xxx |
The thunking modules allow a 16- or 32-bit application to use a 16- or 32-bit data source. Data sources are available from the device manufacturers.
The first four files listed above should be installed in the \Windows directory. MSVCRT20.DLL should be installed in the \Windows\System directory (Windows 9x) or in the \Windows\System32 directory (Windows NT). Data source files xxx.DS should be in the \Windows\Twain or \Windows\Twain_32 directory.
Using the Victor TWAIN functions
The most common method of using the Victor TWAIN functions is to add two menu items to an application under the File menu: Select Source, which will call TWselectsource or TWselectsourcebyname and Acquire, which will call one of the Victor scan functions. You may also want to use TWdetecttwain to enable or disable these menu items.
The Victor scan functions are
TWscanimage | Capture one image |
TWscanimageex | Capture one image without displaying the acquire dialog box |
TWscancountimages | Capture one or more images without displaying the acquire dialog box |
TWscanmultipleimages | Capture one or more images |
TWscanmultipleimagesex | Capture one or more images without displaying the acquire dialog box |
The get-parameter functions (TWgetbrightness, TWgetcontrast, TWgetmeasurementunit, TWgetpixeltype, TWgetxresolution, TWgetyresolution) are used to get the valid range of parameter values before calling the set-parameter functions. The get functions may not be able to verify a parameter change made by a set function because the new value to set is not sent to the device until a scan image function is called.
It is important to recognize that using a set-parameter function (TWsetbrightness, TWsetcontrast, TWsetmeasurementunit, TWsetpixeltype, TWsetxresolution, TWsetyresolution) does not guarantee a change in that parameter. A TWAIN device is under no obligation to allow a parameter to be modified. This is especially true if an acquire dialog box is displayed, since the user may change the selected parameter anyway. To learn more about TWAIN, the TWAIN toolkit may be downloaded from ftp://caere.com/pub/twain.
A TWAIN Example
Here is an example of a simple implementation to acquire an image from a TWAIN device.
// Select source command selected void DoMenuSelectSource(HWND hWnd) { int rcode; // Call the TWAIN source manager to select a source // for image acquisition rcode = TWselectsource(hWnd); if(rcode != NO_ERROR) // Handle any errors here } // Acquire command selected void DoMenuAcquire(HWND hWnd, imgdes far *simage) // Store captured image in simage { int rcode; // Use App name to display in Source dialog box. TWsetproductname("MyApp"); // Display the device user interface dialog box and // capture an image rcode = TWscanimage(hWnd, simage); if(rcode != NO_ERROR) // Handle any errors here }For additional examples see the individual scan functions in the Library Reference section.
Memory Management
These functions allocate or free global memory for image storage.
allocDIB allocate space for an image in memory allocimage allocate space for an image in global memory freeimage free an allocated image SetGlobalCompactFlag disables release of discardable memory (vic.dll, Windows 3.x only)
File Handling
The save and load operations transfer image data between an image area and the disk. The info
routines provide information about a file before loading. Binary, BMP, GIF, JPEG, PCX, TGA
and TIFF file formats are supported.
loadbif load binary image data file loadbmp load BMP or DIB file loadbmpfrombuffer load BMP or DIB file from memory loadbmppalette load BMP palette loadbmppalettefrombuffer load BMP palette from memory loadgif load GIF image loadgifframe load GIF image from multiframe file loadgifframefrombuffer load GIF image from multiframe file in memory loadgiffrombuffer load GIF file from memory loadgifpalette load GIF palette loadgifpalettefrombuffer load GIF palette from memory loadgifglobalpalette load GIF global palette loadgifglobalpalettefrombuffer load GIF global palette from memory loadgifframepalette load GIF frame palette loadgifframepalettefrombuffer load GIF frame palette from memory loadjpg load JPEG file loadjpgex load JPEG file without converting from ycc to rgb loadjpgfrombuffer load JPEG file from memory buffer loadjpgthumbnail load a thumbnail image from a JPEG file loadjpgthumbnailfrombuffer load a thumbnail image from a JPEG file in memory loadpcx load PCX file loadpcxpalette load PCX palette loadpng load PNG file loadpngfrombuffer load PNG file from memory loadpngpalette load PNG palette loadpngpalettefrombuffer load PNG palette from memory loadtga load TGA file loadtgapalette load TGA palette loadtgawithalpha load TGA image and alpha channel loadtif load TIFF file loadtiffrombuffer load image from TIFF file in memory loadtifpage load image from TIFF multipage file loadtifpagebyindex load image from TIFF multipage file loadtifpalette load palette from TIFF file loadtifpalettefrombuffer load palette from TIFF file from memory loadtifpalettepage load palette from TIFF multipage file loadtifpalettepagebyindex load palette from TIFF multipage file loadtifwithalpha load TIFF image and alpha channel savebif save image as binary data file savebmp save image as BMP file savebmptobuffer save image as BMP file in memory saveeps save image as EPS file savegif save image as GIF file savegifex save image as GIF file with transparency and interlace options savegiftobufferex save image as GIF file with transparency, interlace, and compression options to memory savegifframe save image as a frame in a multiframe GIF file savegifframetobuffer save image as a frame in a multiframe GIF file in memory savejpg save image as JPEG file savejpgex save image as JPEG file with mode option savejpgtobuffer save image as JPEG file in memory savejpgtobufferex save image as JPEG file with mode option in memory savepcx save image as PCX file savepng save image as PNG file savepngtobuffer save image as PNG file to memory savetga save image as TGA file savetif save image as TIFF file savetiftobuffer save image as TIFF file to memory savetifpage save image in a multipage TIFF file getgifcomment read comment from a GIF file getpngcomment read comment from a PNG file setgifcomment set comment and version for saving a GIF file bmpinfo BMP file information bmpinfofrombuffer BMP file information from memory gifframecount get number of frames in GIF file gifframecountfrombuffer get number of frames in GIF file in memory gifinfo GIF file information gifinfoallframes get image info about all frames in GIF file gifinfoallframesfrombuffer get image info about all frames in GIF file in memory gifinfoframe get image info about one frame in GIF file gifinfoframefrombuffer get image info about one frame in GIF file in memory gifinfofrombuffer GIF file information from memory jpeginfo JPEG file information jpeginfoex JPEG file information jpeginfofrombuffer JPEG file information from memory buffer jpeginfofrombufferex JPEG file information from memory buffer jpegsetxyresolution set resolution dta for saving JPEG files jpegsetthumbnailsize set JPEG thumbnail size pnggetxyresolution get resolution data from a PNG file pcxinfo PCX file information pnginfo PNG file information pnginfofrombuffer PNG file information from memory pngsetxyresolution set resolution data for saving PNG files tgainfo TGA file information tiffinfo TIFF file information tiffinfofrombuffer TIFF file information from memory tiffinfopage TIFF information about a single page in a multipage TIFF file tiffinfopagebyindex TIFF information about a single page in a multipage TIFF file tiffgetpageinfo TIFF file information about all pages tiffgetxyresolution get resolution data from a TIFF file tiffgetxyresolutionpagebyindex get resolution data about a single page from a TIFF file tiffsetxyresolution set resolution data for saving a TIFF file jpeggeterror report last JPEG error pnggeterror report last PNG error tiffgeterror report last TIFF error unlockLZW enable LZW compression/decompression (requires license agreement with Unisys)
Image Processing
Image processing functions alter the brightness level values of 8- or 24-bit images. Functions marked with "+1" also operate on 1-bit images. Image processing functions can operate on the entire image or any rectangular area within the image.
blur smoothing filter blurthresh smoothing filter with threshold brightenmidrange raise brightness of intermediate levels changebright increase or decrease brightness dilate darken by enlarging dark areas (+1) divide divide by factor erode brighten by enlarging bright areas (+1) exchangelevel change range of levels to new value expandcontrast increase contrast gammabrighten apply a gamma brightness correction histobrighten histogram brightening histoequalize histogram equalization kodalith create high contrast image limitlevel set maximum brightness level matrixconv matrix convolution multiply multiply by factor negative negative image (+1) outline edge detection filter pixellize pixellation removenoise median filter sharpen sharpening filter sharpengentle gentle sharpening filter threshold set minimum brightness level usetable set pixel values based on table zeroimage set all pixels to the same value (+1) addimage add two images andimage AND two images (+1) cover overlay two images coverclear overlay two images, transparent color multiplyimage multiply two images orimage OR two images (+1) subimage subtract operator from source wtaverage weighted average of two images xorimage XOR two images (+1)
Image Manipulation
These operations alter an image area's shape, dimensions, position, or orientation. Image data is read from a source image area, modified, and written to a result area.
copyimage copy image and palette (+1) copyimagebits copy image data only (+1) flipimage flip image top to bottom (+1) mirrorimage reverse image left to right (+1) resize resize image (+1) resizeex resize image with interpolation rotate rotate image any angle (+1) rotate90 rotate image 90 degrees (+1)
Image Descriptor Modification
The image descriptor is a data structure that contains information that describes an image. These functions simplify the entry of data into an image descriptor.
copyimgdes copy all image descriptor elements imageareatorect set RECT coordinates from an image area recttoimagearea set an image area from a RECT data structure setimagearea set the image area of interest setupimgdes assign image descriptor fields based on the BITMAPINFOHEADER of a packed DIB zeroimgdes set all image descriptor elements to zero
Color Reduction and Image Conversion
Images and color palettes are converted between formats.
clienttoimage capture window client area to image colordither color image to 8-bit dither image colorscatter color image to 8-bit scatter image colortogray color image to grayscale convert1bitto8bit 1-bit image to 8-bit palette color image convert1bitto8bitsmooth 1-bit image to 8-bit with smoothing convert8bitto1bit 8-bit palette color image to 1-bit image convertgray8to16 8-bit grayscale to 16-bit grayscale image convertgray16to8 16-bit grayscale to 8-bit grayscale image convertpaltorgb 8-bit palette color image to RGB image convertrgbtopal RGB image to 8-bit palette color image convertrgbtopalex RGB image to 8-bit palette color image with scatter and color matching options ddbtoimage device dependent bitmap to image dibtobitmap DIB to a device dependent bitmap dibtoimage DIB to a Victor-compatible image dibsecttoimage DIB section to a Victor-compatible image imagetodib image area to a DIB matchcolorimage match image to new palette matchcolorimageex match image to new palette with scatter and color matching options reduceimagecolors reduce colors used in an 8-bit image windowtoimage capture window to image
Color Palette Operations
copyimagepalette copy image palette data only defaultpalette establish a 16-color palette consisting of the default Windows colors hsv2rgb convert hue, saturation, value table to red, green, blue palette rainbowpalette create a 256-color rainbow palette rgb2hsv convert red, green, blue palette to hue, saturation, value table updatebitmapcolortable update internal color info (32-bit only) victowinpal convert image palette to Windows logical palette wintovicpal convert Windows logical palette to image palette
Display Functions
drawhisto display histogram on a device context viewimage display image on a device context viewimageex display image at specified position with automatic color reduction
Printer Functions
The printer functions print an image area at any size and position on a printer device context.
printimage print image printimageenddoc end print-document and eject page printimagenoeject print image without ejecting the page printimagestartdoc begin print-document
Image Analysis
calcavglevel calculate average brightness level calchisto calculate histogram calchistorgb calculate histogram treating palette color image as an RGB image getpixelcolor read pixel value at buffer (x,y) isgrayscaleimage determine if image is grayscale pixelcount count pixels within a brightness level range setpixelcolor set pixel at buffer (x,y) to value
System Information
Victorversion return Victor Library version number Victorversionex get Victor Library version information VicStaticLibStart initialize static library VicStaticLibTerm terminate static library
TWAIN Device Control Functions
Control a TWAIN-compliant scanner and Automatic Document Feeder (ADF), set parameters, get parameters, and capture images.
TWclose close TWAIN data source and data source manager TWdetecttwain detect TWAIN source manager TWgetbrightness set scanner brightness Twgetcontrast set scanner contrast TWgeterror get extended error information TWgetfeeder get document feeder status TWgetmeasureunit get valid measurement units TWgetpixeltype restrict pixel type TWgetphysicalsize get maximum image size TWgetsourcenames get names of available data sources TWgetxresolution set scanner horizontal resolution TWgetyresolution set scanner vertical resolution TWopen open TWAIN data source and data source manager TWscancountimages acquire specified number of images TWscanimage acquire image from TWAIN data source TWscanimageex acquire image from TWAIN data source without displaying Acquire dialog box TWscanmultipleimages acquire multiple images TWscanmultipleimagesex acquire multiple images without displaying Acquire dialog box TWselectsource select a new data source TWselectsourcebyname select a data source by name TWsetbrightness set scanner brightness TWsetcontrast set scanner contrast TWsetduplex set duplex operation TWsetfeeder set document feeder TWsetmeasureunit set measurement unit type TWsetpagesize set maximum image size TWsetpixeltype restrict pixel type TWsetproductname inform data source of application name TWsetxresolution set scanner horizontal resolution TWsetyresolution set scanner vertical resolution TWStaticLibStart initialize static library TWStaticLibTerm terminate static library TWvicversion return Victor Library TWAIN support module version number