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;
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
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
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.
Oh no =(. You have lost me. Could you show me? I would very grateful =)
Charles
I don't have a good example I could post, but I can recommend a book, the windows 2000 graphics api black book.
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