123
93
FILE * volatile file = NULL;
129
96
int InterlaceType;
130
97
unsigned char signature[8];
131
98
png_structp volatile png_ptr = NULL;
132
99
png_infop volatile info_ptr = NULL;
133
100
png_infop volatile end_info = NULL;
134
png_colorp PNGPalette = NULL;
135
101
png_color_16 *ImageBackground = NULL;
136
102
png_bytep trns = NULL;
137
103
int NumTrans = 0;
139
105
png_color_16p TransColors = NULL;
140
106
png_uint_32 Width, Height;
142
unsigned char *bits, *p, *q;
143
109
unsigned char** volatile rows = NULL;
145
unsigned char BgdRed = 0;
146
unsigned char BgdGreen = 0;
147
unsigned char BgdBlue = 0;
151
unsigned int DIBLineWidth;
153
113
/* error handler */
154
114
error = setjmp( err_jmp );
224
184
img->width = (unsigned int) Width;
225
185
img->height = (unsigned int) Height;
226
ImageChannels = png_get_channels( png_ptr, info_ptr );
227
FixedBitDepth = BitDepth;
229
/* convert 2 pixel images to 4 pixel images */
233
/* There is logic in the following code that will
234
convert 16-bit grayscale images to 8-bit paletted images and
235
convert 16-bit color images to 24-bit RGB images */
236
if ( BitDepth == 16 )
238
BitsPerPixel = FixedBitDepth *
239
( ColorType & PNG_COLOR_MASK_ALPHA && !(ColorType & PNG_COLOR_MASK_COLOR)?
240
ImageChannels - 1 : ImageChannels );
242
img->bits_per_pixel = (unsigned char)BitsPerPixel;
187
img->bits_per_pixel = (unsigned char)32;
188
img->scan_width = Width * 4;
244
190
/* convert 16-bit images to 8-bit images */
245
191
if (BitDepth == 16)
246
192
png_set_strip_16(png_ptr);
194
/* These are not really required per Rice format spec,
195
* but is done just in case someone uses them.
197
/* convert palette color to rgb color */
198
if (ColorType == PNG_COLOR_TYPE_PALETTE) {
199
png_set_palette_to_rgb(png_ptr);
200
ColorType = PNG_COLOR_TYPE_RGB;
203
/* expand 1,2,4 bit gray scale to 8 bit gray scale */
204
if (ColorType == PNG_COLOR_TYPE_GRAY && BitDepth < 8)
205
png_set_expand_gray_1_2_4_to_8(png_ptr);
207
/* convert gray scale or gray scale + alpha to rgb color */
208
if (ColorType == PNG_COLOR_TYPE_GRAY ||
209
ColorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
210
png_set_gray_to_rgb(png_ptr);
211
ColorType = PNG_COLOR_TYPE_RGB;
214
/* add alpha channel if any */
215
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
216
png_set_tRNS_to_alpha(png_ptr);
217
ColorType = PNG_COLOR_TYPE_RGB_ALPHA;
220
/* convert rgb to rgba */
221
if (ColorType == PNG_COLOR_TYPE_RGB) {
222
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
223
ColorType = PNG_COLOR_TYPE_RGB_ALPHA;
226
png_set_bgr(png_ptr);
248
228
/* set the background color if one is found */
249
229
if ( png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD) )
250
230
png_get_bKGD(png_ptr, info_ptr, &ImageBackground);
253
233
if ( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) )
254
234
png_get_tRNS( png_ptr, info_ptr, &trns, &NumTrans, &TransColors );
256
/* Get the background color if we have transparent pixels */
261
// we will shove the background color into the palette array
263
if ( ImageBackground )
265
BgdRed = (unsigned char)ImageBackground->red;
266
BgdGreen = (unsigned char)ImageBackground->green;
267
BgdBlue = (unsigned char)ImageBackground->blue;
269
// if the alpha component == 0 then set the transparenct index
270
// and let the user deal with it
271
else if ( trns[0] == 0 )
272
img->transparency_index = 0;
273
// otherwise we must perform blending so we will need to create
274
// a 32-bit ARGB image.
278
// if we have more than 1 transparent color then create a 32-bit ARGB
284
/* convert all palette based images to 8-bit arrays */
285
if ( BitDepth < 8 && PaletteTo32 == 1 )
288
png_set_packing(png_ptr);
291
/* calculate the the scan line width */
292
/* 8 & 16-bit images with an alpha component are converted to 32-bit
293
true color images in order to retain the alpha component in the bitmap */
294
if ( ColorType & PNG_COLOR_MASK_ALPHA && BitsPerPixel == 8 )
296
img->bits_per_pixel = 32U;
297
DIBLineWidth = 4U * (unsigned int) Width;
299
/* paletted images with more than 1 transparency index or a non-zero alpha
300
component are converted to 32-bit ABGR images */
301
else if ( ColorType & PNG_COLOR_MASK_PALETTE && PaletteTo32 == 1 )
303
img->bits_per_pixel = 32U;
304
DIBLineWidth = 4U * (unsigned int) Width;
308
DIBLineWidth = img->scan_width = ( BitsPerPixel * (unsigned int) Width + 7 ) / 8;
309
if ( img->opt_for_bmp > 0 && img->scan_width % 4 )
310
img->scan_width += 4 - img->scan_width % 4;
313
/* Determine palette parameters. We will not create a palette for
314
grayscale images that have an alpha component. Those images will be
315
expanded to 32-bit true color images in order to retain the alpha
316
component in the bitmap. */
317
if ( BitsPerPixel <= 8 && !(ColorType & PNG_COLOR_MASK_ALPHA))
319
if ( ColorType & PNG_COLOR_MASK_PALETTE )
321
png_get_PLTE( png_ptr, info_ptr, &PNGPalette, &NumColors );
322
if ( NumTrans == 1 && PaletteTo32 == 0 && ImageBackground != NULL )
325
AlphaComp(PNGPalette[0].red, trns[0], BgdRed);
326
PNGPalette[0].green =
327
AlphaComp(PNGPalette[0].green, trns[0], BgdGreen);
329
AlphaComp(PNGPalette[0].blue, trns[0], BgdBlue);
332
else /* gray scale */
333
NumColors = 1 << (BitDepth == 2 ? 2 : FixedBitDepth);
336
/* set up palette parameters */
337
if ( PaletteTo32 != 1 && BitsPerPixel <= 8 &&
338
!(ColorType & PNG_COLOR_MASK_ALPHA) )
340
img->palette_size = (unsigned short)NumColors;
341
img->bytes_per_palette_entry = img->opt_for_bmp > 0 ? 4U : 3U;
236
img->palette_size = (unsigned short)0;
237
img->bytes_per_palette_entry = 4U;
344
239
tmp = AllocateBMGImage( img );
345
240
if ( tmp != BMG_OK )
346
241
longjmp( err_jmp, (int)tmp );
349
if ( img->palette != NULL )
352
if ( ColorType & PNG_COLOR_MASK_PALETTE )
355
for ( i = 0; i < NumColors;
356
i++, bits += img->bytes_per_palette_entry )
358
bits[2] = PNGPalette[i].red;
359
bits[1] = PNGPalette[i].green;
360
bits[0] = PNGPalette[i].blue;
363
else /* Gray scale palette */
365
j = 255 / (NumColors - 1);
367
for ( i = 0; i < NumColors;
368
i++, bits += img->bytes_per_palette_entry )
370
memset( (void *)bits, i*j, 3 );
373
if ( NumTrans == 1 && ImageBackground != NULL )
375
img->palette[2] = BgdRed;
376
img->palette[1] = BgdGreen;
377
img->palette[0] = BgdBlue;
382
243
png_read_update_info( png_ptr, info_ptr );
384
245
/* create buffer to read data to */
397
258
/* read the entire image into rows */
398
259
png_read_image( png_ptr, rows );
401
The following logic is convoluted compared to the simple examples
402
provided with the source. I wrote the code this way to ensure that
403
hBitmap cantained the minimal amount of information needed to store
404
the image as well as capturing all alpha components */
405
261
bits = img->bits + (Height - 1) * img->scan_width;
406
262
for ( i = 0; i < (int)Height; i++ )
413
memcpy((void *)bits, (void *)p, DIBLineWidth);
416
for ( j = 0; j < (int)(Width/2); j += 2 )
417
Expand2to4((char*)&bits[j], p[j/2], 2);
419
Expand2to4((char*)&bits[Width/2+1], p[Width/4+1], 1);
422
/* 16-bit images were converted to 8-bit */
424
/* this section for data with alpha components */
425
if ( ColorType & PNG_COLOR_MASK_ALPHA )
427
/* expand this format to a 32-bit true color image so that
428
the alpha term is retained in the bitmap */
429
if ( BitsPerPixel == 8 )
431
for ( q = bits; q < bits + img->scan_width;
434
memset( (void *)q, *p, 3 );
438
else /* BitsPerPixel == 32 */
440
for ( j = 0; j < (int)(4*Width); j += 4 )
449
/* this section is for paletted images that contain multiple
450
transparency values or non-zero alpha transparencies */
451
else if ( PaletteTo32 == 1 )
453
for ( q = bits; q < bits + img->scan_width; q += 4, p++ )
455
png_colorp pal = PNGPalette + *p;
459
if ( *p >= NumTrans )
465
/* no alpha component */
468
if ( BitsPerPixel == 8 )
469
memcpy( (void *)bits, (void *)p, DIBLineWidth );
470
else /* BitsPerPixel == 24 */
472
for ( j = 0; j < (int)(3*Width); j += 3 )
474
if ( TransColors != NULL &&
475
ImageBackground != NULL )
477
if ( TransColors->red == p[j] &&
478
TransColors->green == p[j+1] &&
479
TransColors->blue == p[j+2] )
482
bits[j+1] = BgdGreen;
264
memcpy(bits, rows[i], 4*Width);
504
265
bits -= img->scan_width;
277
BMGError ReadPNGInfo( const char *filename,
278
struct BMGImageStruct * volatile img )
283
FILE * volatile file = NULL;
287
unsigned char signature[8];
288
png_structp volatile png_ptr = NULL;
289
png_infop volatile info_ptr = NULL;
290
png_infop volatile end_info = NULL;
291
png_uint_32 Width, Height;
294
error = setjmp( err_jmp );
297
if (end_info != NULL)
298
png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
299
else if (info_ptr != NULL)
300
png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, NULL);
301
else if (png_ptr != NULL)
302
png_destroy_read_struct((png_structp *) &png_ptr, NULL, NULL);
307
SetLastBMGError((BMGError) error);
308
return (BMGError) error;
312
longjmp ( err_jmp, (int)errInvalidBMGImage );
314
file = fopen( filename, "rb" );
315
if ( !file || fread( signature, 1, 8, file ) != 8)
316
longjmp ( err_jmp, (int)errFileOpen );
318
/* check the signature */
319
if ( png_sig_cmp( signature, 0, 8 ) != 0 )
320
longjmp( err_jmp, (int)errUnsupportedFileFormat );
322
/* create a pointer to the png read structure */
323
png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
325
longjmp( err_jmp, (int)errMemoryAllocation );
327
/* create a pointer to the png info structure */
328
info_ptr = png_create_info_struct( png_ptr );
330
longjmp( err_jmp, (int)errMemoryAllocation );
332
/* create a pointer to the png end-info structure */
333
end_info = png_create_info_struct(png_ptr);
335
longjmp( err_jmp, (int)errMemoryAllocation );
337
/* bamboozle the PNG longjmp buffer */
338
/*generic PNG error handler*/
339
/* error will always == 1 which == errLib */
340
// error = png_setjmp(png_ptr);
341
error = setjmp( png_jmpbuf( png_ptr ) );
343
longjmp( err_jmp, error );
345
/* set function pointers in the PNG library, for read callbacks */
346
png_set_read_fn(png_ptr, (png_voidp) file, user_read_data);
348
/*let the read functions know that we have already read the 1st 8 bytes */
349
png_set_sig_bytes( png_ptr, 8 );
351
/* read all PNG data up to the image data */
352
png_read_info( png_ptr, info_ptr );
354
/* extract the data we need to form the HBITMAP from the PNG header */
355
png_get_IHDR( png_ptr, info_ptr, &Width, &Height, &BitDepth, &ColorType,
356
&InterlaceType, NULL, NULL);
358
img->width = (unsigned int) Width;
359
img->height = (unsigned int) Height;
361
img->bits_per_pixel = (unsigned char)32;
362
img->scan_width = Width * 4;
364
img->palette_size = (unsigned short)0;
365
img->bytes_per_palette_entry = 4U;
368
png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
517
375
WritePNG - writes the contents of a BMGImageStruct to a PNG file.