~ubuntu-branches/ubuntu/trusty/mupen64plus-video-rice/trusty

« back to all changes in this revision

Viewing changes to src/liblinux/pngrw.c

  • Committer: Package Import Robot
  • Author(s): Sven Eckelmann
  • Date: 2013-07-05 22:53:25 UTC
  • mfrom: (1.2.2) (3.1.9 experimental)
  • Revision ID: package-import@ubuntu.com-20130705225325-k0fbb2m44xnrju66
Tags: 2.0-1
* New Upstream Version
* Upload to unstable
* debian/control:
  - Build-Depend on debhelper 9.20130604 for support of parameters when
    detecting targets in dh_auto_*
* debian/rules:
  - Work around new debhelper 9.20130624 dh_auto_{clean,test} behavior
    which is causing a FTBFS by adding an explicit
    override_dh_auto_{clean,test} rule
* debian/watch:
  - Verify new upstream versions using GPG key 954F81B094AA5BB226F5

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
#  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
41
41
#endif
42
42
 
43
 
/****************************************************************************/
44
 
/*
45
 
* this function will expand 1 byte of a 4-color bit values to 2 bytes of
46
 
* a 16 color bit value.
47
 
*/
48
 
static void Expand2to4( char *b4, char b2, int NumBytes )
49
 
{
50
 
    struct TwoBit
51
 
    {
52
 
        unsigned char b1 : 2;
53
 
        unsigned char b2 : 2;
54
 
        unsigned char b3 : 2;
55
 
        unsigned char b4 : 2;
56
 
    } bit2;
57
 
 
58
 
    struct FourBit
59
 
    {
60
 
        unsigned char b1 : 4;
61
 
        unsigned char b2 : 4;
62
 
        unsigned char b3 : 4;
63
 
        unsigned char b4 : 4;
64
 
    } bit4;
65
 
 
66
 
    memcpy( (void *)&bit2, (void *)&b2, 1 );
67
 
    bit4.b3 = bit2.b1;
68
 
    bit4.b4 = bit2.b2;
69
 
    bit4.b1 = bit2.b3;
70
 
    bit4.b2 = bit2.b4;
71
 
    memcpy( (void *)b4, (void *)&bit4, NumBytes );
72
 
}
73
43
 
74
44
/* this stuff is necessary because the normal png_init_io() method crashes in Win32 */
75
45
static void user_read_data(png_structp png_read, png_bytep data, png_size_t length)
122
92
 
123
93
    FILE * volatile     file = NULL;
124
94
    int                 BitDepth;
125
 
    int                 BitsPerPixel;
126
 
    int                 FixedBitDepth;
127
95
    int                 ColorType;
128
 
    int                 ImageChannels;
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;
138
 
    int                 i, j, k;
 
104
    int                 i, k;
139
105
    png_color_16p       TransColors = NULL;
140
106
    png_uint_32         Width, Height;
141
107
 
142
 
    unsigned char      *bits, *p, *q;
 
108
    unsigned char      *bits;
143
109
    unsigned char** volatile rows = NULL;
144
 
    int                 NumColors = 0;
145
 
    unsigned char       BgdRed = 0;
146
 
    unsigned char       BgdGreen = 0;
147
 
    unsigned char       BgdBlue = 0;
148
 
    int                 PaletteTo32 = 0;
149
110
 
150
111
    BMGError tmp;
151
 
    unsigned int DIBLineWidth;
152
112
 
153
113
    /* error handler */
154
114
    error = setjmp( err_jmp );
223
183
 
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;
228
 
 
229
 
    /* convert 2 pixel images to 4 pixel images */
230
 
    if ( BitDepth == 2 )
231
 
        FixedBitDepth = 4;
232
 
 
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 )
237
 
        FixedBitDepth = 8;
238
 
    BitsPerPixel = FixedBitDepth *
239
 
            ( ColorType & PNG_COLOR_MASK_ALPHA && !(ColorType & PNG_COLOR_MASK_COLOR)?
240
 
            ImageChannels - 1 : ImageChannels );
241
 
 
242
 
    img->bits_per_pixel = (unsigned char)BitsPerPixel;
 
186
 
 
187
    img->bits_per_pixel = (unsigned char)32;
 
188
    img->scan_width = Width * 4;
243
189
 
244
190
    /* convert 16-bit images to 8-bit images */
245
191
    if (BitDepth == 16)
246
192
        png_set_strip_16(png_ptr);
247
193
 
 
194
    /* These are not really required per Rice format spec,
 
195
     * but is done just in case someone uses them.
 
196
     */
 
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;
 
201
    }
 
202
 
 
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);
 
206
 
 
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;
 
212
    }
 
213
 
 
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;
 
218
    }
 
219
 
 
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;
 
224
    }
 
225
 
 
226
    png_set_bgr(png_ptr);
 
227
 
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 );
255
235
 
256
 
    /* Get the background color if we have transparent pixels */
257
 
    if ( NumTrans > 0 )
258
 
    {
259
 
        if ( NumTrans == 1 )
260
 
        {
261
 
    // we will shove the background color into the palette array
262
 
    // or pixel location
263
 
            if ( ImageBackground )
264
 
            {
265
 
                BgdRed   = (unsigned char)ImageBackground->red;
266
 
                BgdGreen = (unsigned char)ImageBackground->green;
267
 
                BgdBlue  = (unsigned char)ImageBackground->blue;
268
 
            }
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.
275
 
            else
276
 
                PaletteTo32 = 1;
277
 
        }
278
 
    // if we have more than 1 transparent color then create a 32-bit ARGB
279
 
    // image
280
 
        else
281
 
            PaletteTo32 = 1;
282
 
    }
283
 
 
284
 
    /* convert all palette based images to 8-bit arrays */
285
 
    if ( BitDepth < 8 && PaletteTo32 == 1 )
286
 
    {
287
 
        BitDepth = 8;
288
 
        png_set_packing(png_ptr);
289
 
    }
290
 
 
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 )
295
 
    {
296
 
        img->bits_per_pixel = 32U;
297
 
        DIBLineWidth = 4U * (unsigned int) Width;
298
 
    }
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 )
302
 
    {
303
 
        img->bits_per_pixel = 32U;
304
 
        DIBLineWidth = 4U * (unsigned int) Width;
305
 
    }
306
 
    else
307
 
    {
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;
311
 
    }
312
 
 
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))
318
 
    {
319
 
        if ( ColorType & PNG_COLOR_MASK_PALETTE )
320
 
        {
321
 
            png_get_PLTE( png_ptr, info_ptr, &PNGPalette, &NumColors );
322
 
            if ( NumTrans == 1 && PaletteTo32 == 0 && ImageBackground != NULL )
323
 
            {
324
 
                PNGPalette[0].red   =
325
 
                        AlphaComp(PNGPalette[0].red,   trns[0], BgdRed);
326
 
                PNGPalette[0].green =
327
 
                        AlphaComp(PNGPalette[0].green, trns[0], BgdGreen);
328
 
                PNGPalette[0].blue  =
329
 
                        AlphaComp(PNGPalette[0].blue,  trns[0], BgdBlue);
330
 
            }
331
 
        }
332
 
        else  /* gray scale */
333
 
            NumColors = 1 << (BitDepth == 2 ? 2 : FixedBitDepth);
334
 
    }
335
 
 
336
 
    /* set up palette parameters */
337
 
    if ( PaletteTo32 != 1 && BitsPerPixel <= 8 &&
338
 
        !(ColorType & PNG_COLOR_MASK_ALPHA) )
339
 
    {
340
 
        img->palette_size = (unsigned short)NumColors;
341
 
        img->bytes_per_palette_entry = img->opt_for_bmp > 0 ? 4U : 3U;
342
 
    }
 
236
    img->palette_size = (unsigned short)0;
 
237
    img->bytes_per_palette_entry = 4U;
343
238
 
344
239
    tmp = AllocateBMGImage( img );
345
240
    if ( tmp != BMG_OK )
346
241
        longjmp( err_jmp, (int)tmp );
347
242
 
348
 
 
349
 
    if ( img->palette != NULL )
350
 
    {
351
 
        /* color palette */
352
 
        if ( ColorType & PNG_COLOR_MASK_PALETTE )
353
 
        {
354
 
            bits = img->palette;
355
 
            for ( i = 0; i < NumColors; 
356
 
                        i++, bits += img->bytes_per_palette_entry )
357
 
            {
358
 
                bits[2] = PNGPalette[i].red;
359
 
                bits[1] = PNGPalette[i].green;
360
 
                bits[0] = PNGPalette[i].blue;
361
 
            }
362
 
        }
363
 
        else /* Gray scale palette */
364
 
        {
365
 
            j = 255 / (NumColors - 1);
366
 
            bits = img->palette;
367
 
            for ( i = 0; i < NumColors; 
368
 
                        i++, bits += img->bytes_per_palette_entry )
369
 
            {
370
 
                memset( (void *)bits, i*j, 3 );
371
 
            }
372
 
 
373
 
            if ( NumTrans == 1 && ImageBackground != NULL )
374
 
            {
375
 
                img->palette[2] = BgdRed;
376
 
                img->palette[1] = BgdGreen;
377
 
                img->palette[0] = BgdBlue;
378
 
            }
379
 
        }
380
 
    }
381
 
 
382
243
    png_read_update_info( png_ptr, info_ptr );
383
244
 
384
245
    /* create buffer to read data to */
397
258
    /* read the entire image into rows */
398
259
    png_read_image( png_ptr, rows );
399
260
 
400
 
/* extract bits
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++ )
407
263
    {
408
 
        p = rows[i];
409
 
        switch ( BitDepth )
410
 
        {
411
 
            case 1:
412
 
            case 4:
413
 
                memcpy((void *)bits, (void *)p, DIBLineWidth);
414
 
                break;
415
 
            case 2:
416
 
                for ( j = 0; j < (int)(Width/2); j += 2 )
417
 
                    Expand2to4((char*)&bits[j], p[j/2], 2);
418
 
                if ( Width % 2 )
419
 
                    Expand2to4((char*)&bits[Width/2+1], p[Width/4+1], 1);
420
 
                break;
421
 
            case 8:
422
 
                /* 16-bit images were converted to 8-bit */
423
 
            case 16:
424
 
                /* this section for data with alpha components */
425
 
                if ( ColorType & PNG_COLOR_MASK_ALPHA )
426
 
                {
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 )
430
 
                    {
431
 
                        for ( q = bits; q < bits + img->scan_width;
432
 
                                        q += 4, p+=2)
433
 
                        {
434
 
                            memset( (void *)q, *p, 3 );
435
 
                            q[3] = p[1];
436
 
                        }
437
 
                    }
438
 
                    else  /* BitsPerPixel == 32 */
439
 
                    {
440
 
                        for ( j = 0; j < (int)(4*Width); j += 4 )
441
 
                        {
442
 
                            bits[j+3] = p[j+3];
443
 
                            bits[j+2] = p[j  ];
444
 
                            bits[j+1] = p[j+1];
445
 
                            bits[j  ] = p[j+2];
446
 
                        }
447
 
                    }
448
 
                }
449
 
        /* this section is for paletted images that contain multiple
450
 
                transparency values or non-zero alpha transparencies */
451
 
                else if ( PaletteTo32 == 1 )
452
 
                {
453
 
                    for ( q = bits; q < bits + img->scan_width; q += 4, p++ )
454
 
                    {
455
 
                        png_colorp pal = PNGPalette + *p;
456
 
                        q[0] = pal->blue;
457
 
                        q[1] = pal->green;
458
 
                        q[2] = pal->red;
459
 
                        if ( *p >= NumTrans )
460
 
                            q[3] = 0xFF;
461
 
                        else
462
 
                            q[3] = trns[*p];
463
 
                    }
464
 
                }
465
 
                /* no alpha component */
466
 
                else
467
 
                {
468
 
                    if ( BitsPerPixel == 8 )
469
 
                        memcpy( (void *)bits, (void *)p, DIBLineWidth );
470
 
                    else /* BitsPerPixel == 24 */
471
 
                    {
472
 
                        for ( j = 0; j < (int)(3*Width); j += 3 )
473
 
                        {
474
 
                            if ( TransColors != NULL &&
475
 
                                        ImageBackground != NULL )
476
 
                            {
477
 
                                if ( TransColors->red == p[j] &&
478
 
                                        TransColors->green == p[j+1] &&
479
 
                                        TransColors->blue == p[j+2] )
480
 
                                {
481
 
                                    bits[j+2] = BgdRed;
482
 
                                    bits[j+1] = BgdGreen;
483
 
                                    bits[j  ] = BgdBlue;
484
 
                                }
485
 
                                else
486
 
                                {
487
 
                                    bits[j+2] = p[j  ];
488
 
                                    bits[j+1] = p[j+1];
489
 
                                    bits[j  ] = p[j+2];
490
 
                                }
491
 
                            }
492
 
                            else
493
 
                            {
494
 
                                bits[j+2] = p[j  ];
495
 
                                bits[j+1] = p[j+1];
496
 
                                bits[j  ] = p[j+2];
497
 
                            }
498
 
                        }
499
 
                    }
500
 
                }
501
 
                break;
502
 
        }
503
 
 
 
264
        memcpy(bits, rows[i], 4*Width);
504
265
        bits -= img->scan_width;
505
266
    }
506
267
 
513
274
    return BMG_OK;
514
275
}
515
276
 
 
277
BMGError ReadPNGInfo( const char *filename,
 
278
        struct BMGImageStruct * volatile img )
 
279
{
 
280
    jmp_buf             err_jmp;
 
281
    int                 error;
 
282
 
 
283
    FILE * volatile     file = NULL;
 
284
    int                 BitDepth;
 
285
    int                 ColorType;
 
286
    int                 InterlaceType;
 
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;
 
292
 
 
293
    /* error handler */
 
294
    error = setjmp( err_jmp );
 
295
    if (error != 0)
 
296
    {
 
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);
 
303
        if (img)
 
304
            FreeBMGImage(img);
 
305
        if (file)
 
306
            fclose(file);
 
307
        SetLastBMGError((BMGError) error);
 
308
        return (BMGError) error;
 
309
    }
 
310
 
 
311
    if ( img == NULL )
 
312
        longjmp ( err_jmp, (int)errInvalidBMGImage );
 
313
 
 
314
    file = fopen( filename, "rb" );
 
315
    if ( !file || fread( signature, 1, 8, file ) != 8)
 
316
        longjmp ( err_jmp, (int)errFileOpen );
 
317
 
 
318
    /* check the signature */
 
319
    if ( png_sig_cmp( signature, 0, 8 ) != 0 )
 
320
        longjmp( err_jmp, (int)errUnsupportedFileFormat );
 
321
 
 
322
    /* create a pointer to the png read structure */
 
323
    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
 
324
    if ( !png_ptr )
 
325
        longjmp( err_jmp, (int)errMemoryAllocation );
 
326
 
 
327
    /* create a pointer to the png info structure */
 
328
    info_ptr = png_create_info_struct( png_ptr );
 
329
    if ( !info_ptr )
 
330
        longjmp( err_jmp, (int)errMemoryAllocation );
 
331
 
 
332
    /* create a pointer to the png end-info structure */
 
333
    end_info = png_create_info_struct(png_ptr);
 
334
    if (!end_info)
 
335
        longjmp( err_jmp, (int)errMemoryAllocation );
 
336
 
 
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 ) );
 
342
    if ( error > 0 )
 
343
        longjmp( err_jmp, error );
 
344
 
 
345
    /* set function pointers in the PNG library, for read callbacks */
 
346
    png_set_read_fn(png_ptr, (png_voidp) file, user_read_data);
 
347
 
 
348
    /*let the read functions know that we have already read the 1st 8 bytes */
 
349
    png_set_sig_bytes( png_ptr, 8 );
 
350
 
 
351
    /* read all PNG data up to the image data */
 
352
    png_read_info( png_ptr, info_ptr );
 
353
 
 
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);
 
357
 
 
358
    img->width = (unsigned int) Width;
 
359
    img->height = (unsigned int) Height;
 
360
 
 
361
    img->bits_per_pixel = (unsigned char)32;
 
362
    img->scan_width = Width * 4;
 
363
 
 
364
    img->palette_size = (unsigned short)0;
 
365
    img->bytes_per_palette_entry = 4U;
 
366
    img->bits = NULL;
 
367
 
 
368
    png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
 
369
    fclose( file );
 
370
 
 
371
    return BMG_OK;
 
372
}
 
373
 
516
374
/*
517
375
WritePNG - writes the contents of a BMGImageStruct to a PNG file.
518
376
 
540
398
    png_structp png_ptr = NULL;
541
399
    png_infop   info_ptr = NULL;
542
400
    png_colorp  PNGPalette = NULL;
543
 
    int     GrayScale;
544
401
 
545
402
    unsigned char   *bits, *p, *q;
546
403
    unsigned char   **rows = NULL;
547
 
    int     NumColors = 0;
 
404
    volatile int GrayScale, NumColors;  // mark as volatile so GCC won't throw warning with -Wclobbered
548
405
 
549
406
    int     DIBScanWidth;
550
 
    int     HasPalette;
551
407
    FILE        *outfile = NULL;
552
408
    int     i;
553
409
    BMGError    tmp;
595
451
            longjmp( err_jmp, (int)tmp );
596
452
    }
597
453
 
598
 
    HasPalette = img.bits_per_pixel <= 8;
599
 
    if ( HasPalette )
 
454
    GrayScale = 0;
 
455
    NumColors = 0;
 
456
    if (img.bits_per_pixel <= 8)  // has palette
600
457
    {
601
458
        NumColors = img.palette_size;
602
459
        /* if this is a grayscale image then set the flag and delete the palette*/
607
464
            i++;
608
465
            bits += img.bytes_per_palette_entry;
609
466
        }
610
 
        GrayScale = i == NumColors;
 
467
        GrayScale = (i == NumColors);
611
468
    }
612
 
    else
613
 
        GrayScale = 0;
614
469
 
615
470
    /* dimensions */
616
471
    DIBScanWidth = ( img.width * img.bits_per_pixel + 7 ) / 8;