Menu

PNG to hBitmap with libpng

2003-08-18
2012-09-26
  • Nobody/Anonymous

    Hey guys,

    This is sort of a cross between a libpng group and win32 API. Basically I am writing a method in my class to load a png file and convert it into an HBITMAP so I can use it easily in my win32 program. I have managed to get the hardest part done so far, its simply a matter of calling the right win32 functions, I am guessing. Or perhaps I am wrong? Here is what I have so far. Many thanks to anyone who can help =)

    // Load a PNG from resource or from disk....
    HBITMAP CWinApp::loadPNG(char *pszImage, bool bDisk)
    {
        // Variables...
        FILE           *hFile               = NULL;
        png_byte       *ppngByte            = NULL;
        png_byte      **pppngRow            = NULL;
        long            lFileSize           = 0;
        HANDLE          hResource           = NULL;
        png_structp     pngRead             = NULL;
        png_infop       pngInfo             = NULL;
        png_infop       pngInfoEnd          = NULL;
        char            szBuffer[1024]      = {0};
        png_uint_32     unWidth             = 0;
        png_uint_32     unHeight            = 0;
        int             nBitDepth           = 0;
        int             nColorType          = 0;
        unsigned long   ulRowBytes          = 0;
        unsigned long   ulChannels          = 0;
        int             i                   = 0;

        // Prepare to load image...

            // From disk...
            if(bDisk)
            {
                // Open...
                hFile = fopen(pszImage, "rb");

                    // Failed...
                    if(!hFile)
                        return NULL;

                // Verify file size...

                    // Calculate file size...
                    fseek(hFile, 0, SEEK_END);
                    lFileSize = ftell(hFile);
                    fseek(hFile, 0, SEEK_SET);
       
                    // File too small...
                    if(lFileSize < 8)
                    {
                        // Cleanup and abort...
                        fclose(hFile);
                        return NULL;
                    }

                // Verify image header...

                    // Allocate storage space for image header...
                    ppngByte = (png_byte *) malloc(8);
                   
                        // Failed...
                        if(!ppngByte)
                        {
                            // Cleanup and abort...
                            fclose(hFile);
                            return NULL;
                        }
                   
                    // Initialize, store image header and check for error...
                    memset(ppngByte, '\x0', 8);
                    if((ULONG) 8 != fread(ppngByte, 1, 8, hFile))
                    {
                        // Cleanup, then abort...
                        fclose(hFile);
                        free(ppngByte);
                        return NULL;
                    }
                   
                    // Verify image header...
                    if(png_sig_cmp(ppngByte, 0, 8) != 0)
                    {
                        // Cleanup, then abort...
                        fclose(hFile);
                        free(ppngByte);
                        return NULL;
                    }
                   
                    // Done...
                    free(ppngByte);
                    fclose(hFile);
            }

            // From resource...
            else
            {
                // Find it...
                hResource = FindResource(NULL, pszImage, "PNG");

                    // Error...
                    if(!hResource)
                        return NULL;

                // Calculate size...
                lFileSize = SizeofResource(GetModuleHandle(NULL), (HRSRC) hResource);

                    // Invalid file size...
                    if(lFileSize < 8)
                        return NULL;

                // Load it...
                hResource = LoadResource(GetModuleHandle(NULL), (HRSRC) hResource);

                    // Error...
                    if(!hResource)
                        return NULL;

                // Lock it...
                ppngByte = (png_byte *) LockResource(hResource);

                    // Error...
                    if(!ppngByte)
                        return NULL;

                // Verify image header...
                if(png_sig_cmp(ppngByte, 0, 8) != 0)
                    return NULL;

                // Write image to disk...

                    // Generate temporary file...
                    pszImage = szBuffer;
                    getTemporaryFileName(pszImage);

                    // Open...
                    hFile = fopen(pszImage, "wb");
                   
                        // Failed...
                        if(!hFile)
                            return NULL;
                   
                    // Write and check for error...
                    if((ULONG) lFileSize != fwrite(ppngByte, 1, lFileSize, hFile))
                    {
                        // Cleanup, then abort...
                        fclose(hFile);
                        DeleteFile(pszImage);
                        return NULL;
                    }
               
                // Done...
                fclose(hFile);
            }

        // Initialize png read structure...
        pngRead = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

            // Failed...
            if(!pngRead)
                return NULL;

        // Initialize png info structure...
        pngInfo = png_create_info_struct(pngRead);

            // Failed...
            if(!pngInfo)
            {
                // Cleanup, then abort...
                png_destroy_read_struct(&pngRead, NULL, NULL);
                return NULL;
            }

        // Initialize png end info structure...
        pngInfoEnd = png_create_info_struct(pngRead);

            // Failed...
            if(!pngInfoEnd)
            {
                // Cleanup, then abort...
                png_destroy_read_struct(&pngRead, &pngInfo, NULL);
                return NULL;
            }

        // Open png image...
        hFile = fopen(pszImage, "rb");

            // Failed...
            if(!hFile)
            {
                // Cleanup, then abort...
                png_destroy_read_struct(&pngRead, &pngInfo, &pngInfoEnd);
                return NULL;
            }

        // Initialize png stream...
        png_init_io(pngRead, hFile);
       
        // Read image info up to actual pixel data...
        png_read_info(pngRead, pngInfo);
       
        // Get width, height, bit depth and color type...
        png_get_IHDR(pngRead, pngInfo, &unWidth, &unHeight, &nBitDepth, &nColorType, NULL, NULL, NULL);

        // Retrieve number of rows and channels...
        ulRowBytes = png_get_rowbytes(pngRead, pngInfo);
        ulChannels = png_get_channels(pngRead, pngInfo);

        // Allocate storage space for image...
        ppngByte = (png_byte *) malloc(ulRowBytes * unHeight * sizeof(png_byte));

            // Failed...
            if(!ppngByte)
            {
                // Cleanup, then abort...
                png_destroy_read_struct(&pngRead, &pngInfo, &pngInfoEnd);
                fclose(hFile);
                return NULL;
            }

        // Allocate storage for array of row pointers...
        pppngRow = (png_byte **) malloc(unHeight * sizeof(png_bytep));
       
            // Failed...
            if(!pppngRow)
            {
                // Cleanup, then abort...
                png_destroy_read_struct(&pngRead, &pngInfo, &pngInfoEnd);
                free(ppngByte);
                fclose(hFile);
                return NULL;
            }

        // Initialize row pointers...
        for(i = 0; (unsigned) i < unHeight; i++)
            pppngRow[i] = ppngByte + (i * ulRowBytes);

        // Alright, physically read the graphic shit into memory now...
        png_read_image(pngRead, pppngRow);

        // Done, clean this fucking mess up...
        png_read_end(pngRead, NULL);
        free(pppngRow);
        pppngRow = NULL;
        fclose(hFile);

        // Create bitmap now...
       
            /* ??? */

        // Stubbed...
        return NULL;
    }

    Charles

     
    • Nobody/Anonymous

      actually what you probably want to do is set up a DIB section header and initialize it with info from the PNG for width, height, bitcount, planes, and compression, then create a DIB section with CreateDIBSection, then read each scan line into the bitmap with png_read_row.

       
    • Nobody/Anonymous

      Oh no =(. You have lost me. Could you show me? I would very grateful =)

      Charles

       
    • Nobody/Anonymous

      I don't have a good example I could post, but I can recommend a book, the windows 2000 graphics api black book.

       
    • Liviu Nicolescu

      Liviu Nicolescu - 2003-08-19

      Why don't you try to use the OLE IPicture object?

      Quote from Microsoft:
      The IPicture interface manages a picture object and its properties. Picture objects provide a language-neutral abstraction for bitmaps, icons, and metafiles. As with the standard font object, the system provides a standard implementation of the picture object.

      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/ctin_p_482t.asp

      AFAIK it provides support for bmp, dib, ico, jpg, emf, wmf and png formats.

      You can find an example of usage here:

      http://www.codeproject.com/bitmap/pictureshow.asp?target=ipicture

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.