1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| HBITMAP LoadBitmapPNG(LPCTSTR szFile)
{
int size = 0, width, height, bpp, memWidth, i;
HBITMAP hbm = NULL;
LPBITMAPINFO lpbi;
BOOL retVal = FALSE;
FILE *fp;
BYTE header[8], *pixelData;
png_infop info_ptr, end_info;
png_bytep *row_pointers;
png_structp png_ptr;
// check the header first
fp = fopen(szFile, "rb");
if (!fp)
return FALSE;
fread(header, 1, 8, fp);
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fclose(fp);
if (png_sig_cmp(header, 0, 8))
return FALSE;
// now allocate stuff
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
return FALSE;
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
png_destroy_read_struct(&png_ptr,
(png_infopp)NULL, (png_infopp)NULL);
return FALSE;
}
end_info = png_create_info_struct(png_ptr);
if (!end_info)
{
png_destroy_read_struct(&png_ptr, &info_ptr,
(png_infopp)NULL);
return FALSE;
}
fp = fopen(szFile, "rb");
if (fp)
{
png_init_io(png_ptr, fp);
// should really use png_set_rows() to allocate space first, rather than doubling up
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING, NULL);
fclose(fp);
row_pointers = png_get_rows(png_ptr, info_ptr);//new png_bytep[info_ptr->height];
// now for a tonne of ugly DIB setup crap
width = info_ptr->width;
height = info_ptr->height;
bpp = info_ptr->channels * 8;
memWidth = (width * (bpp >> 3) + 3) & ~3;
lpbi = (LPBITMAPINFO) calloc(1, sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
if(lpbi)
{
// create a greyscale palette
for (i = 0; i < 256; i++)
{
lpbi->bmiColors[i].rgbRed = (BYTE)i;
lpbi->bmiColors[i].rgbGreen = (BYTE)i;
lpbi->bmiColors[i].rgbBlue = (BYTE)i;
lpbi->bmiColors[i].rgbReserved = 0;
}
lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lpbi->bmiHeader.biWidth = width;
lpbi->bmiHeader.biHeight = -height; // must be negative for top down
lpbi->bmiHeader.biPlanes = 1;
lpbi->bmiHeader.biBitCount = bpp;
lpbi->bmiHeader.biCompression = BI_RGB;
lpbi->bmiHeader.biSizeImage = memWidth * height;
lpbi->bmiHeader.biXPelsPerMeter = 0;
lpbi->bmiHeader.biYPelsPerMeter = 0;
lpbi->bmiHeader.biClrUsed = 0;
lpbi->bmiHeader.biClrImportant = 0;
hbm = CreateDIBSection(NULL, lpbi, DIB_RGB_COLORS, (void **)&pixelData, NULL, 0 );
if (hbm && pixelData)
{
// now copy the rows
for (i = 0; i < height; i++)
memcpy(pixelData + memWidth * i, row_pointers[i], width * info_ptr->channels);
}
free(lpbi);
}
}
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
return hbm;
} |
Partager