FLTK tech, HICON to Fl_RGB_Image

      Comments Off on FLTK tech, HICON to Fl_RGB_Image

This is a simple source code for converting Windows HICON to Fl_RGB_Image for my own customized FLTK window.

Before understanding how it works, It must be requires understanding of some Windows API like LoadImage().

API, icon_to_flrgb()

Fl_RGB_Image* icon_to_flrgb(HICON hIcon)
{
    BITMAP bm;
    ICONINFO iconInfo;

    GetIconInfo(hIcon, &iconInfo);
    GetObject(iconInfo.hbmColor, sizeof(BITMAP),&bm);

    int width = bm.bmWidth;
    int height = bm.bmHeight;
    int bytesPerScanLine = (width * 3 + 3) & 0xFFFFFFFC;
    int size = bytesPerScanLine * height;

    BITMAPINFO infoheader = {0};
    infoheader.bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
    infoheader.bmiHeader.biWidth    = width;
    infoheader.bmiHeader.biHeight   = height;
    infoheader.bmiHeader.biPlanes   = 1;
    infoheader.bmiHeader.biBitCount = 24;
    infoheader.bmiHeader.biCompression = BI_RGB;
    infoheader.bmiHeader.biSizeImage = size;

    // allocate Memory for Icon RGB data plus Icon mask plus ARGB buffer for the resulting image
    unsigned char* pixelsIconRGB = new unsigned char[ height * width * 4 ];

    if ( pixelsIconRGB == NULL )
    {
        return NULL;
    }

    unsigned char* alphaPixels   = new unsigned char[ height * width * 4 ];

    if ( alphaPixels == NULL )
    {
        delete[] pixelsIconRGB;

        return NULL;
    }

    unsigned char* imagePixels   = new unsigned char[ height * width * 4 ];

    if ( imagePixels == NULL )
    {
        delete[] pixelsIconRGB;
        delete[] alphaPixels;

        return NULL;
    }

    HDC hDC = CreateCompatibleDC(NULL);

    if ( hDC == NULL )
    {
        delete[] pixelsIconRGB;
        delete[] alphaPixels;

        return NULL;
    }

    HBITMAP hBmpOld = (HBITMAP)SelectObject(hDC, (HGDIOBJ)iconInfo.hbmColor);

    if( GetDIBits(hDC, iconInfo.hbmColor, 0, height, (LPVOID) pixelsIconRGB, &infoheader, DIB_RGB_COLORS) == 0 )
    {
        DeleteDC(hDC);

        delete[] pixelsIconRGB;
        delete[] alphaPixels;
        delete[] imagePixels;

        return NULL;
    }

    SelectObject(hDC, hBmpOld);
   // now get the mask
    if( GetDIBits(hDC, iconInfo.hbmMask, 0,height,(LPVOID)alphaPixels, &infoheader, DIB_RGB_COLORS) == 0 )
    {
        DeleteDC(hDC);

        delete[] pixelsIconRGB;
        delete[] alphaPixels;
        delete[] imagePixels;

        return NULL;
    }

    DeleteDC(hDC);

    int x=0;
    int currentSrcPos=0;
    int currentDestPos=0;
    int linePosSrc = 0;
    int linePosDest = 0;
    int vsDest = height-1;

    for(int y=0; y<height; y++)
    {
        linePosSrc  = ( vsDest - y ) * ( width * 3 );
        linePosDest = y * width * 4;

        for(x=0; x<width; x++)
        {
            currentDestPos = linePosDest + ( x * 4 );
            currentSrcPos  = linePosSrc + ( x * 3);

            imagePixels[ currentDestPos + 0 ] = pixelsIconRGB[ currentSrcPos + 2 ];
            imagePixels[ currentDestPos + 1 ] = pixelsIconRGB[ currentSrcPos + 1 ];
            imagePixels[ currentDestPos + 2 ] = pixelsIconRGB[ currentSrcPos + 0 ];
            imagePixels[ currentDestPos + 3 ] = 0xFF - alphaPixels[ currentSrcPos ];
        }
    }

    Fl_RGB_Image* pImage = new Fl_RGB_Image( imagePixels, width, height, 4 );

    delete[] pixelsIconRGB;
    delete[] alphaPixels;

    return pImage;
}

Plus, to remove Fl_RGB_Image in safe, use this.

remove_fl_rgb_image()

void remove_fl_rgb_image( Fl_RGB_Image** img )
{
    if ( img != NULL )
    {
        Fl_RGB_Image* srci = (Fl_RGB_Image*)*img;

        if ( ( srci->array != NULL ) && ( srci->alloc_array == 0 ) )
        {
            delete[] srci->array;
        }

        delete srci;

        *img = NULL;
    }
}

And, let know understand how it calls :

Sequence to convert image and apply, then discard.

// Load small ICON in size 16x16.
HICON hIconWindowSmall = (HICON)LoadImage( fl_display,MAKEINTRESOURCE( IDC_ICON_A ),IMAGE_ICON,16,16,LR_SHARED );

// Convert HICON to Fl_RGB_Image ..
Fl_RGB_Image* convtitleiconimg = icon_to_flrgb( hIconWindowSmall );
if ( convtitleiconimg != NULL )
{
    window_title_box->image( convtitleiconimg );
}

.... something do .... and now .

remove_fl_rgb_image( &convtitleiconimg );

remove_fl_rgb_image() may called in end of program, when it terminates or class destructor to release memory contains user allocated memory, and it is specification of FLTK 1.3.x.