previous section

Using Victor Functions in a Windows Application

When working with images, a general procedure to follow is

Allocate memory for the image
Load the image
Set the image area to be modified
Modify the image area
Display/save/print the image
Free the image


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
BMPloadbmp
loadbmpfrombuffer
savebmp
loads 1-, 4-, 8-, 16-, 24-, and 32-bit

saves 1-, 8-, and 24-bit
TIFFloadtif
loadtiffrombuffer
loadtifpage
loadtifpagebyindex
loadtifwithalpha
savetif
savetifpage
savetiftobuffer
loads 1-, 4-, 8-, 16-, 24-, and 32-bit




saves 1-, 8-, and 24-bit
EPS saveepssaves 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 process 
To 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:

stx = 0,
sty = 0,
endx = bmh.biWidth - 1, and
endy = bmh.biHeight - 1


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:

endx >= bmh->biWidth,
endx >= XLIMIT, defined in VICDEFS.H,
endy >= bmh->biHeight, or
endy >= 32768
ibuff == 0, or
bmh == 0
bmh->biWidth * bmh->biBitCount / 8 > buffwidth


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.




Color Palettes

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.




DIBs, Bitmaps, and Images

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 DIB Functions

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.




Using the Windows Clipboard

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);
}





Scanning Images

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.




Victor Functions by Category

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