72
72
png_set_tRNS_to_alpha(png_p);
74
74
/* alpha channel support */
75
if (fixed_pdf_minor_version < 4 && png_p->color_type | PNG_COLOR_MASK_ALPHA)
75
if (pdf->minor_version < 4 && png_p->color_type | PNG_COLOR_MASK_ALPHA)
76
76
png_set_strip_alpha(png_p);
77
77
/* 16bit depth support */
78
if (fixed_pdf_minor_version < 5)
79
fixed_image_hicolor = 0;
80
if (info_p->bit_depth == 16 && !fixed_image_hicolor)
78
if (pdf->minor_version < 5)
79
pdf->image_hicolor = 0;
80
if ((info_p->bit_depth == 16) && (pdf->image_hicolor == 0))
81
81
png_set_strip_16(png_p);
82
82
/* gamma support */
83
if (fixed_image_apply_gamma) {
83
if (pdf->image_apply_gamma) {
84
84
if (png_get_gAMA(png_p, info_p, &gamma))
85
png_set_gamma(png_p, (fixed_gamma / 1000.0), gamma);
85
png_set_gamma(png_p, (pdf->gamma / 1000.0), gamma);
87
png_set_gamma(png_p, (fixed_gamma / 1000.0),
88
(1000.0 / fixed_image_gamma));
87
png_set_gamma(png_p, (pdf->gamma / 1000.0),
88
(1000.0 / pdf->image_gamma));
90
90
/* reset structure */
91
91
png_read_update_info(png_p, info_p);
121
121
#define write_gray_pixel_16(r) \
122
if (j % 4 == 0||j % 4 == 1) pdf_buf[pdf_ptr++] = *r++; \
122
if (j % 4 == 0||j % 4 == 1) pdf_quick_out(pdf,*r++); \
123
123
else smask[smask_ptr++] = *r++
125
125
#define write_gray_pixel_8(r) \
126
if (j % 2 == 0) pdf_buf[pdf_ptr++] = *r++; \
126
if (j % 2 == 0) pdf_quick_out(pdf,*r++); \
127
127
else smask[smask_ptr++] = *r++
129
129
#define write_rgb_pixel_16(r) \
130
if (!(j % 8 == 6||j % 8 == 7)) pdf_buf[pdf_ptr++] = *r++; \
130
if (!(j % 8 == 6||j % 8 == 7)) pdf_quick_out(pdf,*r++); \
131
131
else smask[smask_ptr++] = *r++
133
133
#define write_rgb_pixel_8(r) \
134
if (j % 4 != 3) pdf_buf[pdf_ptr++] = *r++; \
134
if (j % 4 != 3) pdf_quick_out(pdf,*r++); \
135
135
else smask[smask_ptr++] = *r++
137
#define write_simple_pixel(r) pdf_buf[pdf_ptr++] = *r++
137
#define write_simple_pixel(r) pdf_quick_out(pdf,*r++)
139
139
#define write_noninterlaced(outmac) \
140
140
for (i = 0; i < (int)info_p->height; i++) { \
166
166
xfree(rows[i]); \
169
static void write_png_palette(image_dict * idict)
169
static void write_png_palette(PDF pdf, image_dict * idict)
172
172
png_structp png_p = img_png_png_ptr(idict);
173
173
png_infop info_p = img_png_info_ptr(idict);
174
174
png_bytep row, r, *rows;
175
integer palette_objnum = 0;
175
int palette_objnum = 0;
176
176
if (img_colorspace(idict) != 0) {
177
pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
177
pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
179
pdf_create_obj(0, 0);
180
palette_objnum = obj_ptr;
181
pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n",
179
pdf_create_obj(pdf, obj_type_others, 0);
180
palette_objnum = pdf->obj_ptr;
181
pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n",
182
182
(int) (info_p->num_palette - 1), (int) palette_objnum);
184
pdf_begin_stream(pdf);
185
185
if (info_p->interlace_type == PNG_INTERLACE_NONE) {
186
186
row = xtalloc(info_p->rowbytes, png_byte);
187
187
write_noninterlaced(write_simple_pixel(r));
197
197
write_interlaced(write_simple_pixel(row));
201
201
if (palette_objnum > 0) {
202
pdf_begin_dict(palette_objnum, 0);
202
pdf_begin_dict(pdf, palette_objnum, 0);
203
pdf_begin_stream(pdf);
204
204
for (i = 0; (unsigned) i < info_p->num_palette; i++) {
206
pdf_buf[pdf_ptr++] = info_p->palette[i].red;
207
pdf_buf[pdf_ptr++] = info_p->palette[i].green;
208
pdf_buf[pdf_ptr++] = info_p->palette[i].blue;
206
pdf_quick_out(pdf, info_p->palette[i].red);
207
pdf_quick_out(pdf, info_p->palette[i].green);
208
pdf_quick_out(pdf, info_p->palette[i].blue);
214
static void write_png_gray(image_dict * idict)
214
static void write_png_gray(PDF pdf, image_dict * idict)
217
217
png_structp png_p = img_png_png_ptr(idict);
218
218
png_infop info_p = img_png_info_ptr(idict);
219
219
png_bytep row, r, *rows;
220
220
if (img_colorspace(idict) != 0) {
221
pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
221
pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
223
pdf_puts("/DeviceGray\n");
223
pdf_puts(pdf, "/DeviceGray\n");
225
pdf_begin_stream(pdf);
226
226
if (info_p->interlace_type == PNG_INTERLACE_NONE) {
227
227
row = xtalloc(info_p->rowbytes, png_byte);
228
228
write_noninterlaced(write_simple_pixel(r));
238
238
write_interlaced(write_simple_pixel(row));
244
static void write_png_gray_alpha(image_dict * idict)
244
static void write_png_gray_alpha(PDF pdf, image_dict * idict)
247
247
png_structp png_p = img_png_png_ptr(idict);
248
248
png_infop info_p = img_png_info_ptr(idict);
249
249
png_bytep row, r, *rows;
250
integer smask_objnum = 0;
250
int smask_objnum = 0;
252
integer smask_ptr = 0;
253
integer smask_size = 0;
255
255
if (img_colorspace(idict) != 0) {
256
pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
256
pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
258
pdf_puts("/DeviceGray\n");
258
pdf_puts(pdf, "/DeviceGray\n");
260
pdf_create_obj(0, 0);
261
smask_objnum = obj_ptr;
262
pdf_printf("/SMask %i 0 R\n", (int) smask_objnum);
260
pdf_create_obj(pdf, obj_type_others, 0);
261
smask_objnum = pdf->obj_ptr;
262
pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum);
263
263
smask_size = (info_p->rowbytes / 2) * info_p->height;
264
264
smask = xtalloc(smask_size, png_byte);
265
pdf_begin_stream(pdf);
266
266
if (info_p->interlace_type == PNG_INTERLACE_NONE) {
267
267
row = xtalloc(info_p->rowbytes, png_byte);
268
if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
268
if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) {
269
269
write_noninterlaced(write_gray_pixel_16(r));
271
271
write_noninterlaced(write_gray_pixel_8(r));
279
279
for (i = 0; (unsigned) i < info_p->height; i++)
280
280
rows[i] = xtalloc(info_p->rowbytes, png_byte);
281
281
png_read_image(png_p, rows);
282
if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
282
if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) {
283
283
write_interlaced(write_gray_pixel_16(row));
285
285
write_interlaced(write_gray_pixel_8(row));
291
291
/* now write the Smask object */
292
292
bitdepth = (int) info_p->bit_depth;
293
pdf_begin_dict(smask_objnum, 0);
294
pdf_puts("/Type /XObject\n/Subtype /Image\n");
293
pdf_begin_dict(pdf, smask_objnum, 0);
294
pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n");
295
295
if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
296
pdf_printf("%s\n", img_attr(idict));
297
pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
296
pdf_printf(pdf, "%s\n", img_attr(idict));
297
pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n",
298
298
(int) info_p->width,
299
299
(int) info_p->height, (bitdepth == 16 ? 8 : bitdepth));
300
pdf_puts("/ColorSpace /DeviceGray\n");
300
pdf_puts(pdf, "/ColorSpace /DeviceGray\n");
301
pdf_begin_stream(pdf);
302
302
for (i = 0; i < smask_size; i++) {
305
pdf_buf[pdf_ptr++] = smask[i];
305
pdf_quick_out(pdf, smask[i]);
306
306
if (bitdepth == 16)
313
static void write_png_rgb(image_dict * idict)
313
static void write_png_rgb(PDF pdf, image_dict * idict)
316
316
png_structp png_p = img_png_png_ptr(idict);
317
317
png_infop info_p = img_png_info_ptr(idict);
318
318
png_bytep row, r, *rows;
319
319
if (img_colorspace(idict) != 0) {
320
pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
320
pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
322
pdf_puts("/DeviceRGB\n");
322
pdf_puts(pdf, "/DeviceRGB\n");
324
pdf_begin_stream(pdf);
325
325
if (info_p->interlace_type == PNG_INTERLACE_NONE) {
326
326
row = xtalloc(info_p->rowbytes, png_byte);
327
327
write_noninterlaced(write_simple_pixel(r));
337
337
write_interlaced(write_simple_pixel(row));
343
static void write_png_rgb_alpha(image_dict * idict)
343
static void write_png_rgb_alpha(PDF pdf, image_dict * idict)
346
346
png_structp png_p = img_png_png_ptr(idict);
347
347
png_infop info_p = img_png_info_ptr(idict);
348
348
png_bytep row, r, *rows;
349
integer smask_objnum = 0;
349
int smask_objnum = 0;
351
integer smask_ptr = 0;
352
integer smask_size = 0;
354
354
if (img_colorspace(idict) != 0) {
355
pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
355
pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
357
pdf_puts("/DeviceRGB\n");
357
pdf_puts(pdf, "/DeviceRGB\n");
359
pdf_create_obj(0, 0);
360
smask_objnum = obj_ptr;
361
pdf_printf("/SMask %i 0 R\n", (int) smask_objnum);
359
pdf_create_obj(pdf, obj_type_others, 0);
360
smask_objnum = pdf->obj_ptr;
361
pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum);
362
362
smask_size = (info_p->rowbytes / 2) * info_p->height;
363
363
smask = xtalloc(smask_size, png_byte);
364
pdf_begin_stream(pdf);
365
365
if (info_p->interlace_type == PNG_INTERLACE_NONE) {
366
366
row = xtalloc(info_p->rowbytes, png_byte);
367
if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
367
if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) {
368
368
write_noninterlaced(write_rgb_pixel_16(r));
370
370
write_noninterlaced(write_rgb_pixel_8(r));
378
378
for (i = 0; (unsigned) i < info_p->height; i++)
379
379
rows[i] = xtalloc(info_p->rowbytes, png_byte);
380
380
png_read_image(png_p, rows);
381
if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
381
if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) {
382
382
write_interlaced(write_rgb_pixel_16(row));
384
384
write_interlaced(write_rgb_pixel_8(row));
390
390
/* now write the Smask object */
391
391
if (smask_objnum > 0) {
392
392
bitdepth = (int) info_p->bit_depth;
393
pdf_begin_dict(smask_objnum, 0);
394
pdf_puts("/Type /XObject\n/Subtype /Image\n");
393
pdf_begin_dict(pdf, smask_objnum, 0);
394
pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n");
395
395
if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
396
pdf_printf("%s\n", img_attr(idict));
397
pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
396
pdf_printf(pdf, "%s\n", img_attr(idict));
397
pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n",
398
398
(int) info_p->width,
399
399
(int) info_p->height, (bitdepth == 16 ? 8 : bitdepth));
400
pdf_puts("/ColorSpace /DeviceGray\n");
400
pdf_puts(pdf, "/ColorSpace /DeviceGray\n");
401
pdf_begin_stream(pdf);
402
402
for (i = 0; i < smask_size; i++) {
405
pdf_buf[pdf_ptr++] = smask[i];
405
pdf_quick_out(pdf, smask[i]);
406
406
if (bitdepth == 16)
507
507
} while (endflag == false);
510
static void reopen_png(image_dict * idict)
510
static void reopen_png(PDF pdf, image_dict * idict)
512
integer width, height, xres, yres;
512
int width, height, xres, yres;
513
513
width = img_xsize(idict); /* do consistency check */
514
514
height = img_ysize(idict);
515
515
xres = img_xres(idict);
516
516
yres = img_yres(idict);
517
read_png_info(idict, IMG_KEEPOPEN);
517
read_png_info(pdf, idict, IMG_KEEPOPEN);
518
518
if (width != img_xsize(idict) || height != img_ysize(idict)
519
519
|| xres != img_xres(idict) || yres != img_yres(idict))
520
520
pdftex_fail("writepng: image dimensions have changed");
523
523
static boolean last_png_needs_page_group;
525
void write_png(image_dict * idict)
525
void write_png(PDF pdf, image_dict * idict)
527
527
double gamma, checked_gamma;
529
integer palette_objnum = 0;
529
int palette_objnum = 0;
530
530
png_structp png_p;
531
531
png_infop info_p;
532
532
assert(idict != NULL);
533
533
last_png_needs_page_group = false;
534
534
if (img_file(idict) == NULL)
535
reopen_png(pdf, idict);
536
536
assert(img_png_ptr(idict) != NULL);
537
537
png_p = img_png_png_ptr(idict);
538
538
info_p = img_png_info_ptr(idict);
539
if (fixed_pdf_minor_version < 5)
540
fixed_image_hicolor = 0;
541
pdf_puts("/Type /XObject\n/Subtype /Image\n");
539
if (pdf->minor_version < 5)
540
pdf->image_hicolor = 0;
541
pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n");
542
542
if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
543
pdf_printf("%s\n", img_attr(idict));
544
pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
543
pdf_printf(pdf, "%s\n", img_attr(idict));
544
pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n",
545
545
(int) info_p->width,
546
546
(int) info_p->height, (int) info_p->bit_depth);
547
pdf_puts("/ColorSpace ");
547
pdf_puts(pdf, "/ColorSpace ");
548
548
checked_gamma = 1.0;
549
if (fixed_image_apply_gamma) {
549
if (pdf->image_apply_gamma) {
550
550
if (png_get_gAMA(png_p, info_p, &gamma)) {
551
checked_gamma = (fixed_gamma / 1000.0) * gamma;
551
checked_gamma = (pdf->gamma / 1000.0) * gamma;
554
(fixed_gamma / 1000.0) * (1000.0 / fixed_image_gamma);
553
checked_gamma = (pdf->gamma / 1000.0) * (1000.0 / pdf->image_gamma);
557
556
/* the switching between |info_p| and |png_p| queries has been trial and error.
559
if (fixed_pdf_minor_version > 1 && info_p->interlace_type == PNG_INTERLACE_NONE && (png_p->transformations == 0 || png_p->transformations == 0x2000) /* gamma */
558
if (pdf->minor_version > 1 && info_p->interlace_type == PNG_INTERLACE_NONE && (png_p->transformations == 0 || png_p->transformations == 0x2000) /* gamma */
560
559
&&!(png_p->color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
561
560
png_p->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
562
&& (fixed_image_hicolor || (png_p->bit_depth <= 8))
561
&& ((pdf->image_hicolor != 0) || (png_p->bit_depth <= 8))
563
562
&& (checked_gamma <= 1.01 && checked_gamma > 0.99)
565
564
if (img_colorspace(idict) != 0) {
566
pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
565
pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
568
567
switch (info_p->color_type) {
569
568
case PNG_COLOR_TYPE_PALETTE:
570
pdf_create_obj(0, 0);
571
palette_objnum = obj_ptr;
572
pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n",
569
pdf_create_obj(pdf, obj_type_others, 0);
570
palette_objnum = pdf->obj_ptr;
571
pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n",
573
572
(int) (info_p->num_palette - 1),
574
573
(int) palette_objnum);
576
575
case PNG_COLOR_TYPE_GRAY:
577
pdf_puts("/DeviceGray\n");
576
pdf_puts(pdf, "/DeviceGray\n");
579
578
default: /* RGB */
580
pdf_puts("/DeviceRGB\n");
579
pdf_puts(pdf, "/DeviceRGB\n");
583
582
if (tracefilenames)
584
583
tex_printf(" (PNG copy)");
584
copy_png(pdf, idict);
586
585
if (palette_objnum > 0) {
587
pdf_begin_dict(palette_objnum, 0);
586
pdf_begin_dict(pdf, palette_objnum, 0);
587
pdf_begin_stream(pdf);
589
588
for (i = 0; (unsigned) i < info_p->num_palette; i++) {
591
pdf_buf[pdf_ptr++] = info_p->palette[i].red;
592
pdf_buf[pdf_ptr++] = info_p->palette[i].green;
593
pdf_buf[pdf_ptr++] = info_p->palette[i].blue;
590
pdf_quick_out(pdf, info_p->palette[i].red);
591
pdf_quick_out(pdf, info_p->palette[i].green);
592
pdf_quick_out(pdf, info_p->palette[i].blue);
599
598
tex_printf(" PNG copy skipped because: ");
600
if (fixed_image_apply_gamma &&
599
if ((pdf->image_apply_gamma != 0) &&
601
600
(checked_gamma > 1.01 || checked_gamma < 0.99))
602
601
tex_printf("gamma delta=%lf ", checked_gamma);
603
602
if (png_p->transformations != PNG_TRANSFORM_IDENTITY)
618
617
switch (info_p->color_type) {
619
618
case PNG_COLOR_TYPE_PALETTE:
620
write_png_palette(idict);
619
write_png_palette(pdf, idict);
622
621
case PNG_COLOR_TYPE_GRAY:
623
write_png_gray(idict);
622
write_png_gray(pdf, idict);
625
624
case PNG_COLOR_TYPE_GRAY_ALPHA:
626
if (fixed_pdf_minor_version >= 4) {
627
write_png_gray_alpha(idict);
625
if (pdf->minor_version >= 4) {
626
write_png_gray_alpha(pdf, idict);
628
627
last_png_needs_page_group = true;
630
write_png_gray(idict);
629
write_png_gray(pdf, idict);
632
631
case PNG_COLOR_TYPE_RGB:
633
write_png_rgb(idict);
632
write_png_rgb(pdf, idict);
635
634
case PNG_COLOR_TYPE_RGB_ALPHA:
636
if (fixed_pdf_minor_version >= 4) {
637
write_png_rgb_alpha(idict);
635
if (pdf->minor_version >= 4) {
636
write_png_rgb_alpha(pdf, idict);
638
637
last_png_needs_page_group = true;
640
write_png_rgb(idict);
639
write_png_rgb(pdf, idict);
643
642
pdftex_fail("unsupported type of color_type <%i>",
644
643
info_p->color_type);
648
647
close_and_cleanup_png(idict);
653
652
/* Called after the xobject generated by write_png has been finished; used to
654
653
* write out additional objects */
656
void write_additional_png_objects(void)
655
void write_additional_png_objects(PDF pdf)
658
657
return; /* this interferes with current macro-based usage and cannot be configured */
659
658
if (last_png_needs_page_group) {
660
659
if (!transparent_page_group_was_written && transparent_page_group > 1) {
661
660
/* create new group object */
662
661
transparent_page_group_was_written = true;
663
pdf_begin_obj(transparent_page_group, 2);
664
if (get_pdf_compress_level() == 0) {
665
pdf_puts("%PTEX Group needed for transparent pngs\n");
662
pdf_begin_obj(pdf, transparent_page_group, 2);
663
if (pdf->compress_level == 0) {
664
pdf_puts(pdf, "%PTEX Group needed for transparent pngs\n");
668
("<</Type/Group /S/Transparency /CS/DeviceRGB /I true /K true>>\n");
668
"<</Type/Group /S/Transparency /CS/DeviceRGB /I true /K true>>\n");