@@ -60,7 +60,7 @@ typedef pdfio_obj_t *(*_pdfio_image_func_t)(pdfio_dict_t *dict, int fd);
60
60
static pdfio_obj_t * copy_jpeg (pdfio_dict_t * dict , int fd );
61
61
static pdfio_obj_t * copy_png (pdfio_dict_t * dict , int fd );
62
62
static bool create_cp1252 (pdfio_file_t * pdf );
63
- static pdfio_obj_t * create_image (pdfio_dict_t * dict , const unsigned char * data , size_t width , size_t height , size_t num_colors , bool alpha );
63
+ static pdfio_obj_t * create_image (pdfio_dict_t * dict , const unsigned char * data , size_t width , size_t height , size_t depth , size_t num_colors , bool alpha );
64
64
#ifdef HAVE_LIBPNG
65
65
static void png_error_func (png_structp pp , png_const_charp message );
66
66
static void png_read_func (png_structp png_ptr , png_bytep data , size_t length );
@@ -2027,7 +2027,7 @@ pdfioFileCreateImageObjFromData(
2027
2027
pdfioDictSetName (dict , "ColorSpace" , defcolors [num_colors ]);
2028
2028
2029
2029
// Create the image object(s)...
2030
- return (create_image (dict , data , width , height , num_colors , alpha ));
2030
+ return (create_image (dict , data , width , height , 8 , num_colors , alpha ));
2031
2031
}
2032
2032
2033
2033
@@ -2484,6 +2484,11 @@ copy_png(pdfio_dict_t *dict, // I - Dictionary
2484
2484
int fd ) // I - File descriptor
2485
2485
{
2486
2486
pdfio_obj_t * obj = NULL ; // Object
2487
+ double gamma = 2.2 , // Gamma value
2488
+ wx = 0.0 , wy = 0.0 , // White point chromacity
2489
+ rx = 0.0 , ry = 0.0 , // Red chromacity
2490
+ gx = 0.0 , gy = 0.0 , // Green chromacity
2491
+ bx = 0.0 , by = 0.0 ; // Blue chromacity
2487
2492
#ifdef HAVE_LIBPNG
2488
2493
png_structp pp = NULL ; // PNG read pointer
2489
2494
png_infop info = NULL ; // PNG info pointers
@@ -2493,9 +2498,14 @@ copy_png(pdfio_dict_t *dict, // I - Dictionary
2493
2498
color_type , // PNG color mode
2494
2499
width , // Width in columns
2495
2500
height , // Height in lines
2501
+ depth , // Bit depth
2496
2502
num_colors = 0 , // Number of colors
2497
- bpp ; // Bytes per pixel
2503
+ linesize ; // Bytes per line
2498
2504
bool alpha ; // Alpha transparency?
2505
+ png_color * palette ; // Color palette information
2506
+ int num_palette ; // Number of colors
2507
+ int num_trans ; // Number of transparent colors
2508
+ png_color_16 * trans ; // Transparent colors
2499
2509
2500
2510
2501
2511
PDFIO_DEBUG ("copy_png(dict=%p, fd=%d)\n" , (void * )dict , fd );
@@ -2539,51 +2549,28 @@ copy_png(pdfio_dict_t *dict, // I - Dictionary
2539
2549
2540
2550
width = png_get_image_width (pp , info );
2541
2551
height = png_get_image_height (pp , info );
2552
+ depth = png_get_bit_depth (pp , info );
2542
2553
color_type = png_get_color_type (pp , info );
2543
2554
2544
- if (color_type & PNG_COLOR_MASK_COLOR )
2555
+ if (color_type & PNG_COLOR_MASK_PALETTE )
2556
+ num_colors = 1 ;
2557
+ else if (color_type & PNG_COLOR_MASK_COLOR )
2545
2558
num_colors = 3 ;
2546
2559
else
2547
2560
num_colors = 1 ;
2548
2561
2549
- PDFIO_DEBUG ("copy_png: width=%u, height=%u, color_type=%u, num_colors=%d\n" , width , height , color_type , num_colors );
2562
+ PDFIO_DEBUG ("copy_png: width=%u, height=%u, depth=%u, color_type=%u, num_colors=%d\n" , width , height , depth , color_type , num_colors );
2550
2563
2551
2564
// Set decoding options...
2552
- if (png_get_valid (pp , info , PNG_INFO_tRNS ))
2553
- {
2554
- // Map transparency to alpha
2555
- png_set_tRNS_to_alpha (pp );
2556
- color_type |= PNG_COLOR_MASK_ALPHA ;
2557
- }
2558
-
2559
- if (png_get_bit_depth (pp , info ) > 8 )
2560
- {
2561
- // Strip the bottom bits of 16-bit values
2562
- png_set_strip_16 (pp );
2563
- }
2564
- else if (png_get_bit_depth (pp , info ) < 8 )
2565
- {
2566
- // Expand 1, 2, and 4-bit values to 8 bits
2567
- if (num_colors == 1 )
2568
- png_set_expand_gray_1_2_4_to_8 (pp );
2569
- else
2570
- png_set_packing (pp );
2571
- }
2572
-
2573
- #if 1
2574
- if (color_type & PNG_COLOR_MASK_PALETTE )
2575
- {
2576
- // Convert indexed images to RGB...
2577
- png_set_palette_to_rgb (pp );
2578
- num_colors = 3 ;
2579
- }
2580
- #endif // 0
2565
+ alpha = (color_type & PNG_COLOR_MASK_ALPHA ) != 0 ;
2566
+ linesize = (width * num_colors * depth + 7 ) / 8 ;
2567
+ if (alpha )
2568
+ linesize += width ;
2581
2569
2582
- alpha = (color_type & PNG_COLOR_MASK_ALPHA ) != 0 ;
2583
- bpp = num_colors + (alpha ? 1 : 0 );
2570
+ PDFIO_DEBUG ("copy_png: alpha=%s, linesize=%u\n" , alpha ? "true" : "false" , (unsigned )linesize );
2584
2571
2585
2572
// Allocate memory for the image...
2586
- if ((pixels = (unsigned char * )calloc (height , width * bpp )) == NULL )
2573
+ if ((pixels = (unsigned char * )calloc (height , linesize )) == NULL )
2587
2574
{
2588
2575
_pdfioFileError (dict -> pdf , "Unable to allocate memory for PNG image: %s" , strerror (errno ));
2589
2576
goto finish_png ;
@@ -2596,7 +2583,7 @@ copy_png(pdfio_dict_t *dict, // I - Dictionary
2596
2583
}
2597
2584
2598
2585
for (i = 0 ; i < height ; i ++ )
2599
- rows [i ] = pixels + i * width * bpp ;
2586
+ rows [i ] = pixels + i * linesize ;
2600
2587
2601
2588
// Read the image...
2602
2589
for (i = png_set_interlace_handling (pp ); i > 0 ; i -- )
@@ -2605,13 +2592,67 @@ copy_png(pdfio_dict_t *dict, // I - Dictionary
2605
2592
// Add image dictionary information...
2606
2593
pdfioDictSetNumber (dict , "Width" , width );
2607
2594
pdfioDictSetNumber (dict , "Height" , height );
2608
- pdfioDictSetNumber (dict , "BitsPerComponent" , 8 );
2595
+ pdfioDictSetNumber (dict , "BitsPerComponent" , depth );
2609
2596
2610
2597
// Grab any color space/palette information...
2611
- pdfioDictSetArray (dict , "ColorSpace" , pdfioArrayCreateColorFromStandard (dict -> pdf , num_colors , PDFIO_CS_SRGB ));
2598
+ if (png_get_PLTE (pp , info , & palette , & num_palette ))
2599
+ {
2600
+ pdfioDictSetArray (dict , "ColorSpace" , pdfioArrayCreateColorFromPalette (dict -> pdf , num_palette , (unsigned char * )palette ));
2601
+ }
2602
+ else if (png_get_cHRM (pp , info , & wx , & wy , & rx , & ry , & gx , & gy , & bx , & by ) && png_get_gAMA (pp , info , & gamma ))
2603
+ {
2604
+ pdfioDictSetArray (dict , "ColorSpace" , pdfioArrayCreateColorFromPrimaries (dict -> pdf , num_colors , gamma , wx , wy , rx , ry , gx , gy , bx , by ));
2605
+ }
2606
+ else
2607
+ {
2608
+ // Default to sRGB...
2609
+ pdfioDictSetArray (dict , "ColorSpace" , pdfioArrayCreateColorFromStandard (dict -> pdf , num_colors , PDFIO_CS_SRGB ));
2610
+ }
2611
+
2612
+ if (png_get_tRNS (pp , info , /*trans_alpha*/ NULL , & num_trans , & trans ))
2613
+ {
2614
+ int m ; // Looping var
2615
+ pdfio_array_t * mask ; // Mask array
2616
+
2617
+ mask = pdfioArrayCreate (dict -> pdf );
2618
+
2619
+ if (color_type & PNG_COLOR_MASK_PALETTE )
2620
+ {
2621
+ // List color indices that are transparent...
2622
+ for (m = 0 ; m < num_trans ; m ++ )
2623
+ {
2624
+ pdfioArrayAppendNumber (mask , trans [m ].index );
2625
+ pdfioArrayAppendNumber (mask , trans [m ].index );
2626
+ }
2627
+ }
2628
+ else if (num_colors == 1 )
2629
+ {
2630
+ // List grayscale values that are transparent...
2631
+ for (m = 0 ; m < num_trans ; m ++ )
2632
+ {
2633
+ pdfioArrayAppendNumber (mask , trans [m ].gray >> (16 - depth ));
2634
+ pdfioArrayAppendNumber (mask , trans [m ].gray >> (16 - depth ));
2635
+ }
2636
+ }
2637
+ else
2638
+ {
2639
+ // List RGB color values that are transparent...
2640
+ for (m = 0 ; m < num_trans ; m ++ )
2641
+ {
2642
+ pdfioArrayAppendNumber (mask , trans [m ].red >> (16 - depth ));
2643
+ pdfioArrayAppendNumber (mask , trans [m ].green >> (16 - depth ));
2644
+ pdfioArrayAppendNumber (mask , trans [m ].blue >> (16 - depth ));
2645
+ pdfioArrayAppendNumber (mask , trans [m ].red >> (16 - depth ));
2646
+ pdfioArrayAppendNumber (mask , trans [m ].green >> (16 - depth ));
2647
+ pdfioArrayAppendNumber (mask , trans [m ].blue >> (16 - depth ));
2648
+ }
2649
+ }
2650
+
2651
+ pdfioDictSetArray (dict , "Mask" , mask );
2652
+ }
2612
2653
2613
2654
// Create the image object...
2614
- obj = create_image (dict , pixels , width , height , num_colors , alpha );
2655
+ obj = create_image (dict , pixels , width , height , depth , num_colors , alpha );
2615
2656
2616
2657
finish_png :
2617
2658
@@ -2648,11 +2689,6 @@ copy_png(pdfio_dict_t *dict, // I - Dictionary
2648
2689
unsigned char bit_depth = 0 , // Bit depth
2649
2690
color_type = 0 , // Color type
2650
2691
interlace = 0 ; // Interlace type
2651
- double gamma = 2.2 , // Gamma value
2652
- wx = 0.0 , wy = 0.0 , // White point chromacity
2653
- rx = 0.0 , ry = 0.0 , // Red chromacity
2654
- gx = 0.0 , gy = 0.0 , // Green chromacity
2655
- bx = 0.0 , by = 0.0 ; // Blue chromacity
2656
2692
pdfio_array_t * mask = NULL ; // Color masking array
2657
2693
2658
2694
@@ -2803,7 +2839,7 @@ copy_png(pdfio_dict_t *dict, // I - Dictionary
2803
2839
return (NULL );
2804
2840
}
2805
2841
2806
- num_colors = ( color_type == _PDFIO_PNG_TYPE_RGB || color_type == _PDFIO_PNG_TYPE_RGBA ) ? 3 : 1 ;
2842
+ num_colors = color_type == _PDFIO_PNG_TYPE_RGB ? 3 : 1 ;
2807
2843
2808
2844
pdfioDictSetNumber (dict , "Width" , width );
2809
2845
pdfioDictSetNumber (dict , "Height" , height );
@@ -3304,6 +3340,7 @@ create_image(
3304
3340
const unsigned char * data , // I - Image data
3305
3341
size_t width , // I - Width in columns
3306
3342
size_t height , // I - Height in lines
3343
+ size_t depth , // I - Bit depth
3307
3344
size_t num_colors , // I - Number of colors
3308
3345
bool alpha ) // I - `true` if there is transparency
3309
3346
{
@@ -3316,16 +3353,17 @@ create_image(
3316
3353
// Mask image object, if any
3317
3354
pdfio_stream_t * st ; // Image stream
3318
3355
size_t x , y , // X and Y position in image
3319
- bpp , // Bytes per pixel
3356
+ bpc = depth / 8 ,// Bytes per component
3357
+ bpp = num_colors * bpc ,
3358
+ // Bytes per pixel (less alpha)
3320
3359
linelen ; // Line length
3321
3360
const unsigned char * dataptr ; // Pointer into image data
3322
3361
unsigned char * line = NULL , // Current line
3323
3362
* lineptr ; // Pointer into line
3324
3363
3325
3364
3326
3365
// Allocate memory for one line of data...
3327
- bpp = alpha ? num_colors + 1 : num_colors ;
3328
- linelen = num_colors * width ;
3366
+ linelen = (width * num_colors * depth + 7 ) / 8 ;
3329
3367
3330
3368
if ((line = malloc (linelen )) == NULL )
3331
3369
return (NULL );
@@ -3353,7 +3391,7 @@ create_image(
3353
3391
return (NULL );
3354
3392
}
3355
3393
3356
- pdfioDictSetNumber (decode , "BitsPerComponent" , 8 );
3394
+ pdfioDictSetNumber (decode , "BitsPerComponent" , depth );
3357
3395
pdfioDictSetNumber (decode , "Colors" , 1 );
3358
3396
pdfioDictSetNumber (decode , "Columns" , width );
3359
3397
pdfioDictSetNumber (decode , "Predictor" , _PDFIO_PREDICTOR_PNG_AUTO );
@@ -3373,12 +3411,23 @@ create_image(
3373
3411
return (NULL );
3374
3412
}
3375
3413
3376
- for (y = height , dataptr = data + num_colors ; y > 0 ; y -- )
3414
+ for (y = height , dataptr = data + bpp ; y > 0 ; y -- )
3377
3415
{
3378
- for (x = width , lineptr = line ; x > 0 ; x -- , dataptr += bpp )
3379
- * lineptr ++ = * dataptr ;
3416
+ if (bpc == 1 )
3417
+ {
3418
+ for (x = width , lineptr = line ; x > 0 ; x -- , dataptr += bpp )
3419
+ * lineptr ++ = * dataptr ++ ;
3420
+ }
3421
+ else
3422
+ {
3423
+ for (x = width , lineptr = line ; x > 0 ; x -- , dataptr += bpp )
3424
+ {
3425
+ * lineptr ++ = * dataptr ++ ;
3426
+ * lineptr ++ = * dataptr ++ ;
3427
+ }
3428
+ }
3380
3429
3381
- pdfioStreamWrite (st , line , width );
3430
+ pdfioStreamWrite (st , line , width * bpc );
3382
3431
}
3383
3432
3384
3433
pdfioStreamClose (st );
@@ -3394,7 +3443,7 @@ create_image(
3394
3443
return (NULL );
3395
3444
}
3396
3445
3397
- pdfioDictSetNumber (decode , "BitsPerComponent" , 8 );
3446
+ pdfioDictSetNumber (decode , "BitsPerComponent" , depth );
3398
3447
pdfioDictSetNumber (decode , "Colors" , num_colors );
3399
3448
pdfioDictSetNumber (decode , "Columns" , width );
3400
3449
pdfioDictSetNumber (decode , "Predictor" , _PDFIO_PREDICTOR_PNG_AUTO );
@@ -3418,29 +3467,15 @@ create_image(
3418
3467
{
3419
3468
if (alpha )
3420
3469
{
3421
- switch ( num_colors )
3470
+ if ( bpp == 1 )
3422
3471
{
3423
- case 1 :
3424
- for (x = width , lineptr = line ; x > 0 ; x -- , dataptr += bpp )
3425
- * lineptr ++ = * dataptr ;
3426
- break ;
3427
- case 3 :
3428
- for (x = width , lineptr = line ; x > 0 ; x -- , dataptr += bpp )
3429
- {
3430
- * lineptr ++ = dataptr [0 ];
3431
- * lineptr ++ = dataptr [1 ];
3432
- * lineptr ++ = dataptr [2 ];
3433
- }
3434
- break ;
3435
- case 4 :
3436
- for (x = width , lineptr = line ; x > 0 ; x -- , dataptr += bpp )
3437
- {
3438
- * lineptr ++ = dataptr [0 ];
3439
- * lineptr ++ = dataptr [1 ];
3440
- * lineptr ++ = dataptr [2 ];
3441
- * lineptr ++ = dataptr [3 ];
3442
- }
3443
- break ;
3472
+ for (x = width , lineptr = line ; x > 0 ; x -- , dataptr += bpc )
3473
+ * lineptr ++ = * dataptr ++ ;
3474
+ }
3475
+ else
3476
+ {
3477
+ for (x = width , lineptr = line ; x > 0 ; x -- , dataptr += bpp + bpc , lineptr += bpp )
3478
+ memcpy (lineptr , dataptr , bpp );
3444
3479
}
3445
3480
3446
3481
pdfioStreamWrite (st , line , linelen );
0 commit comments