Victor Image Processing Library How-to Tips

Load Images into an ImageList Control

Microsoft defines the ImageList control as "a collection of images of the same size, each of which can be referred to by its index." That is, it's a series of images of all the same width, length, and pixel depth. The image of interest is selected by a handle to the image list and the index number corresponding to the image.

In the first example, we load three TIFF images into an ImageList control. The sequence is

  1. With the Victor tiffinfo function read the header info from the first TIFF file and get the dimensions for the image.
  2. Create the image list with the Windows function ImageList_Create.
  3. Use the Victor allocimage function to allocate a temporary buffer (tempimage) to hold the images as they are loaded.
  4. Load each image from the TIFF file with the Victor loadtif function.
  5. Transfer each image from the temporary buffer into the image list with the Windows function ImageList_Add
  6. Free the temporary buffer by calling the Victor freeimage function.
  7. Return the image list handle to the calling function.

This example assumes that you previously created the three TIFF files ("test1.tif", "test2.tif", and "test3.tif") and they are all of the same dimensions and pixel depth.

Loading Images into an ImageList Control - Example 1

Requires Victor Image Processing Library v 5 or higher.
#include <commctrl.h>   // Must be linked with comctl32.lib
HIMAGELIST Load3tiffs()
{
imgdes tempimage;
TiffData tinfo;
int rcode, imgCount, cFlag;
// Make sure file exists and get its dimensions
rcode = tiffinfo("test1.tif", &tinfo);
if(rcode == NO_ERROR) {
   int width = tinfo.width;
   int length = tinfo.length;
   int bitcount = tinfo.vbitcount;
   HIMAGELIST hIml = 0;
   cFlag = ILC_COLOR24;  // For simplicity always create a 24-bit ImageList 
            // Create an empty image list
   hIml = ImageList_Create(  // Windows function 
      width, // width
      length, // height 
      cFlag, // creation flag
      3, // number of images
      0); // amount this list can grow
            // Allocate space for the image
   rcode = allocimage(&tempimage, width, length, bitcount);
   if(rcode == NO_ERROR) {
      rcode = loadtif("test1.tif", &tempimage);
      if(rcode == NO_ERROR)
         ImageList_Add(hIml, tempimage.hBitmap, NULL); // Add first image
      rcode = loadtif("test2.tif", &tempimage);
      if(rcode == NO_ERROR)
         ImageList_Add(hIml, tempimage.hBitmap, NULL); // Add second image
      rcode = loadtif("test3.tif", &tempimage);
      if(rcode == NO_ERROR)
         ImageList_Add(hIml, tempimage.hBitmap, NULL); // Add third image
      }
   freeimage(&tempimage); 
   return(hIml);
}

This little example is all you need for a simple implementation of a image list if application will run in a 24-bit display mode. When ready to display an image, you can use the Windows ImageList_Draw function and select the image by image_index.

   ImageList_Draw(hIml, image_index, hdc, x_position, y_position, ILD_NORMAL);

If, however, the application will not always display in 24-bit display mode then for best quality display you have to consider the type of image loaded and the display mode.

In the next example, a single image is loaded and processed to change the colors. In this case, we have to check the display mode and perhaps perform some color reduction for the best quality display.

Loading Images into an ImageList Control - Example 2

Requires Victor Image Processing Library v 5 or higher.
#include <commctrl.h>   // Must link with comctl32.lib
HIMAGELIST hIml = 0; // Handle to image list
HPALETTE HPalette;
int displayBits;
// Build image list command selected
void DoBuildImageList(HWND hWnd, 
   char *filnam) // Name of BMP file to add to image list
{
#define NUM_BITMAPS 4
   int rcode, imgCount, cFlag;
   BITMAPINFOHEADER bdat; // Reserve space for struct
   imgdes image, timg8;
   imgdes *iptr;
//   InitCommonControls(); // May need this
            // Make sure file exists and get its dimensions
   rcode = bmpinfo(filnam, &bdat);
   if(rcode == NO_ERROR) {
      int bitcount = bdat.biBitCount;
      int width = (int)bdat.biWidth;
      int length = (int)bdat.biHeight;
      BOOL useStdPal;
      HDC hdc;
      hdc = GetDC(hWnd);
            // Get display bits: 4, 8, 24, or 32
      displayBits = GetDeviceCaps(hdc, BITSPIXEL);
      ReleaseDC(hWnd, hdc);
      if(bitcount >= 16) // Load a 16-, 24-, or 32-bit file into a 24-bit buffer
         bitcount = 24;
            // Set buffwidth to 0 to check for allocation of timg8 later
      image.buffwidth = 0;
      timg8.buffwidth = 0;
            // Create image list with bitcount = 8 or 24
      cFlag = (bitcount <= 8) ? ILC_COLOR8 : ILC_COLOR24;
            // Create an empty image list
      hIml = ImageList_Create(
         width, // width
         length, // height 
         cFlag, // creation flags
         NUM_BITMAPS, // number of images
         0); // amount this list can grow
            // Allocate space for the image
      rcode = allocimage(&image, width, length, bitcount);
            // Set flag to use standard halftone palette
      useStdPal = (bitcount <= 8 && displayBits <= 8);
      if(useStdPal && rcode == NO_ERROR) {
            // Allocate temp 8- or 1-bit image
         rcode = allocimage(&timg8, width, length, bitcount);
            // Use standard halftone palette for timg8
         standard_palette(&timg8);
         }
            // Point iptr at image if we don't need timg8,
            // otherwise point iptr at timg8
      iptr = useStdPal ? &timg8 : ℑ
      if(rcode == NO_ERROR) {
            // Load the image file(s) and add them to the list
         rcode = loadbmp(filnam, &image);
         if(rcode == NO_ERROR) {
            // Add 1st image
            // If display mode is 256 or fewer colors, 
            // match image palette to standard palette
            if(useStdPal)
               rcode = matchcolorimageex(&image, &timg8, CR_TSDDIFF);
            ImageList_Add(hIml, iptr->hBitmap, NULL);
            // Add 2nd image
            negative(&image, &image);
            if(useStdPal)
               rcode = matchcolorimageex(&image, &timg8, CR_TSDDIFF);
            ImageList_Add(hIml, iptr->hBitmap, NULL);
            // Add 3rd image
            flipimage(&image, &image);
            if(useStdPal)
               rcode = matchcolorimageex(&image, &timg8, CR_TSDDIFF);
            ImageList_Add(hIml, iptr->hBitmap, NULL);
            // Get number of images in list (actually don't do anything with it here)
            imgCount = ImageList_GetImageCount(hIml);
            }
         if(image.buffwidth)
            freeimage(&image); // Release image buffers
         if(timg8.buffwidth)
            freeimage(&timg8);
         }
      }
   if(rcode != NO_ERROR)
      error_handler(hWnd, rcode);   // Handle any errors
}
// Repaint a portion or all of the window.
void DoPaint(HWND hWnd)
{
   PAINTSTRUCT ps;   // Holds PAINT info
   HDC hdc;
   int rcode = NO_ERROR;
   hdc = BeginPaint(hWnd, &ps);
   if(hIml != 0) { // If handle to image list exists...
            // Get number of images in list
      int imgno, imgCount = ImageList_GetImageCount(hIml);
      IMAGEINFO info;
      int cx, cy, width, length, bitcount;
      BOOL nRc;
      BITMAPINFOHEADER far *bmHdr;
      DIBSECTION dib;
      BOOL useStdPal;
            // Get size of an image in the image list
      ImageList_GetImageInfo(hIml, 0, &info);
      width = info.rcImage.right - info.rcImage.left;
      length = info.rcImage.bottom - info.rcImage.top;
      if(GetObject(info.hbmImage, sizeof(DIBSECTION), &dib) == sizeof(DIBSECTION)) {
         bmHdr = &dib.dsBmih;
         bitcount = bmHdr->biBitCount;
         }
              
            // Set flag to use standard halftone palette
      useStdPal = (bitcount <= 8 && displayBits <= 8);
      if(useStdPal == TRUE) {   // Only necessary with 8-bit display mode
         if(HPalette)   // Delete previous palette object
            DeletePalette(HPalette);
            // Retrieve the Windows halftone standard palette
         HPalette = CreateHalftonePalette(hdc);
            // Select and realize the palette
         SelectPalette(hdc, HPalette, 0);
         RealizePalette(hdc);
         }
      cx = 0;
      cy = 0;
      for(imgno=0; imgno<imgCount; imgno++) {
         nRc = ImageList_Draw(hIml, imgno, hdc, cx, cy, ILD_NORMAL);
         cx += width;
         }
      }
   EndPaint(hWnd, &ps);
            // Handle any errors
   if(rcode != NO_ERROR)
      error_handler(hWnd, rcode);
}
// Add 256-color standard halftone Window's palette to image->palette and fill in 
//   image->colors. Returns number of colors added to image->palette, 0 or 256.
//
int standard_palette(imgdes far *image)
{
   PALETTEENTRY pe[256];
   HPALETTE hPal;
   RGBQUAD far *palptr = image->palette;
   HDC hdc = 0;
   int j, colorsMax, nColors;
   if(image->bmh->biBitCount != 8 || image->palette == 0) 
      return(0); // Guard against a non 8-bit image
   hdc = GetDC(NULL);
   hPal = CreateHalftonePalette(hdc); // Get Windows halftone standard palette (256)
            // Retrieve up to 256 colors
   colorsMax = GetPaletteEntries(hPal, 0, 256, pe);
            // Convert from the PALETTEENTRY format to RGBQUAD format
   for(j=0, nColors=0; j<colorsMax; j++, nColors++) {
      palptr->rgbRed   = pe[j].peRed;
      palptr->rgbGreen = pe[j].peGreen;
      palptr->rgbBlue  = pe[j].peBlue;
      palptr++; // Update RGB quad pointer
      }
   if(hdc)
      ReleaseDC(NULL, hdc);
            // Fill in and return the number of palette colors
   return(image->colors = nColors);
}
Victor Image Processing Library

Victor Image Processing Library homepage | Victor Product Summary | more source code




Copyright © 2000 Catenary Systems Inc. All rights reserved. Victor Image Processing Library is a trademark of Catenary Systems.