No announcement yet.

ImageList_GetImageInfo - Color Table Info?

  • Filter
  • Time
  • Show
Clear All
new posts

  • ImageList_GetImageInfo - Color Table Info?

    Playing around with imagelists right now, mainly looking for the means to extract single images from one list and transfer them to another. So in examining the API for something that would do this, I find nothing, except for ImageList_GetImageInfo which seems to come close in that it returns the handle to the bitmap, along with the bounding rectangle of the selected image. Found out through experimentation that the image list's bitmap is stored as a grid, 4 across and N down, depending on how many images are stored in the list. At least with a bitmap imagelist, have not tinkered with icon lists yet.
    LOCAL pImage        AS IMAGEINFO
    LOCAL hImageList    AS DWORD
    LOCAL pBits         AS BITMAP
    LOCAL pSize         AS LONG
    LOCAL hDib, hDC     AS DWORD
    LOCAL filename      AS ASCIIZ * %MAX_PATH      
        CONTROL SEND hDialog, idControl, %LVM_GETIMAGELIST, %LVSIL_SMALL, 0 _
        TO hImageList
        ImageList_GetImageInfo hImageList, 0, pImage
        pSize = SIZEOF(pBits)
        GetObject pImage.hbmImage, pSize, pBits
        #DEBUG PRINT "pBits.bmWidth="& FORMAT$(pBits.bmWidth) _
            &" pBits.bmHeight="& FORMAT$(pBits.bmHeight) _
            &" pBits.bmWidthBytes="& FORMAT$(pBits.bmWidthBytes) _
            &" pBits.bmBitsPixel="& FORMAT$(pBits.bmBitsPixel) _
            &" pBits.bmBits="& FORMAT$(pBits.bmBits)
        #DEBUG PRINT "hbmImage="& FORMAT$(pImage.hbmImage) _
            &" rcImage.nLeft="& FORMAT$(pImage.rcImage.nLeft) _
            &" rcImage.nTop="& FORMAT$(pImage.rcImage.nTop) _
            &" rcImage.nRight="& FORMAT$(pImage.rcImage.nRight) _
            &" rcImage.nBottom="& FORMAT$(pImage.rcImage.nBottom)
    Returns me the information about the imagelist, and "selected" image, sort of arbitrary at this point, was still looking to extract a single image from the imagelist, the code prints the following for an 8 bit imagelist:
    pBits.bmWidth=160 pBits.bmHeight=80 pBits.bmWidthBytes=160 _
        pBits.bmBitsPixel=8 pBits.bmBits=21626880
    hbmImage=2986676997 rcImage.nLeft=0 rcImage.nTop=0 _
        rcImage.nRight=40 rcImage.nBottom=40
    And this from a 32 bit imagelist:
    pBits.bmWidth=160 pBits.bmHeight=80 pBits.bmWidthBytes=640 _
        pBits.bmBitsPixel=32 pBits.bmBits=21626880
    hbmImage=2802127693 rcImage.nLeft=0 rcImage.nTop=0 _
        rcImage.nRight=40 rcImage.nBottom=40
    The "ImageList_Draw=1" is from code a bit further along. Armed with the above information, I executed:
        hDib = FreeImage_ConvertFromRawBits(BYVAL pBits.bmBits, _
                pBits.bmWidth, pBits.bmHeight, pBits.bmWidthBytes, _
                    pBits.bmBitsPixel, 0,0,0, %FALSE)
        filename = EXE.PATH$ &"imagelist.bmp"
        FreeImage_Save %fif_bmp, hDib, filename
        hDib = UnloadDib(hDib)
    ' this is a MACRO wrapper around the unload and returns Zero
    When the imagelist is in 24 or 32 bit mode, the results is the imagelist as I've determined to be setup in memory, 4 across and N down. It also works when the imagelist is in 8 bit mode, however, I only know this because of the size of the resulting image, and when examining the contents of the file itself with frhed, I see the bits of the images in the bitmap, but no color table. Which was expected, more or less. The ImageList_GetImageInfo returns a handle to the bitmap, and a pointer to the BITS of the bitmap, nothing in there about the color table. So the next step, obviously, was to get the color table of the bitmap, and attach it to the hDib from FreeImage.

    Not so fast it seems, the bitmap maintained by the imagelist when in an 8 bit mode seems to be a DDB, not a DIB, hence GetDIBColorTable does not work. When I tried it, it returned a color count of 2, so as far as the DC into which I selected the imagelist's bitmap into was concerned, it was a monochrome bitmap.

    I tried using a GRAPHIC BITMAP to capture the whole image via a bitblt, and just the "selected" image within the imagelist via ImageList_Draw:
        GRAPHIC BITMAP NEW 40, 40 TO hDib ' remember, I released this above
        GRAPHIC ATTACH hDib, 0
        #DEBUG PRINT "ImageList_Draw="& _
            FORMAT$( ImageList_Draw (hImageList, 0, hDC, 0, 0, %ILD_NORMAL ))
        filename = EXE.PATH$ &"image.bmp"
        GRAPHIC SAVE filename
    And according to walking through the results with frehed, at offset 0x1c, the WORD there should be biBitCount and it says it's a 24 bit image. And the resulting image is "visible", that is, it's got color. But this is a 24 bit image and for the destination, I desire an 8 bit image.

    Any ideas on how to get the color table of the imagelist's color table?
    Furcadia, an interesting online MMORPG in which you can create and program your own content.

  • #2
    I found my answer! GetDIBits

    However, you cannot use the function as defined in the Win32API, you have to modify it due to misinterpretation of the parameters required for the operation to be successful. Specifically:
    [in/out] Pointer to a BITMAPINFO structure that specifies the desired format for the DIB data.
    And this really needs to be ANY. And that's because the defination of the BITMAPINFO has a BITMAPINFOHEADER and a single LONG in the place where the palette entries are supposed to go. This works if you allocate a memory block of the required size and then cast the BITMAPINFO to a pointer then point it to the memory block. Something I did not need to do for this operation.

    This works just as fine:
      biSize AS LONG
      biWidth AS LONG
      biHeight AS LONG
      biPlanes AS INTEGER
      biBitCount AS INTEGER
      biCompression AS LONG
      biSizeImage AS LONG
      biXPelsPerMeter AS LONG
      biYPelsPerMeter AS LONG
      biClrUsed AS LONG
      biClrImportant AS LONG
      biColors(255) AS RGBQUAD
        (BYVAL hdc AS DWORD, BYVAL hBitmap AS DWORD, _
            BYVAL nStartScan AS DWORD, BYVAL nNumScans AS DWORD, _
                lpBits AS ANY, lpBI AS BITMAPCOLORS, _
                    BYVAL wUsage AS DWORD) AS LONG
    FYI: This is also the first part of a packed dib format for creating a clipboard object.

    That aside, I set up the header information with the required data, then executed the call, and copied the palette to the hDib created by FreeImage, and it works as expected, I end up with a palettizied image containing all the bitmaps contained in the ImageList.
        hDib = FreeImage_ConvertFromRawBits(BYVAL pBits.bmBits, _
                pBits.bmWidth, pBits.bmHeight, pBits.bmWidthBytes, _
                    pBits.bmBitsPixel, 0,0,0, %FALSE)
        hDC = CreateCompatibleDC(0)
        memBit = SelectObject(hDC, pImage.hbmImage)
        pBitmap.biSize = SIZEOF(BITMAPINFOHEADER)
        pBitmap.biWidth = pBits.bmWidth
        pBitmap.biHeight = pBits.bmHeight
        pBitmap.biPlanes = 1
        pBitmap.biBitCount = pBits.bmBitsPixel
        pBitmap.biCompression = %BI_RGB
        GetDIBColors hDC, pImage.hbmImage, 0, pBits.bmHeight, _
            BYVAL 0, pBitmap, %DIB_RGB_COLORS
        SelectObject hDC, memBit
        DeleteDC hDC
        CopyMemory(BYVAL FreeImage_GetPalette(hDib),pBitmap.biColors(0),1024)
        filename = EXE.PATH$ &"imagelist.bmp"
        FreeImage_Save %fif_bmp, hDib, filename
        hDib = UnloadDib(hDib)
    Attached Files
    Last edited by colin glenn; 18 Mar 2009, 09:47 PM. Reason: Missed something, ...
    Furcadia, an interesting online MMORPG in which you can create and program your own content.