summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/image/writepng.w
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image/writepng.w')
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writepng.w586
1 files changed, 266 insertions, 320 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.w b/Build/source/texk/web2c/luatexdir/image/writepng.w
index 08daac984e6..3464f9205fa 100644
--- a/Build/source/texk/web2c/luatexdir/image/writepng.w
+++ b/Build/source/texk/web2c/luatexdir/image/writepng.w
@@ -1,27 +1,27 @@
% writepng.w
-
+%
% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
-% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org>
-
+% Copyright 2006-2011 Taco Hoekwater <taco@@luatex.org>
+%
% This file is part of LuaTeX.
-
+%
% LuaTeX is free software; you can redistribute it and/or modify it under
% the terms of the GNU General Public License as published by the Free
% Software Foundation; either version 2 of the License, or (at your
% option) any later version.
-
+%
% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
% License for more details.
-
+%
% You should have received a copy of the GNU General Public License along
-% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
@ @c
static const char _svn_version[] =
- "$Id: writepng.w 4258 2011-05-11 05:36:13Z taco $ "
- "$URL: http://foundry.supelec.fr/svn/luatex/branches/0.70.x/source/texk/web2c/luatexdir/image/writepng.w $";
+ "$Id: writepng.w 4442 2012-05-25 22:40:34Z hhenkel $"
+ "$URL: http://foundry.supelec.fr/svn/luatex/trunk/source/texk/web2c/luatexdir/image/writepng.w $";
#include <assert.h>
#include "ptexlib.h"
@@ -45,7 +45,7 @@ static void close_and_cleanup_png(image_dict * idict)
}
@ @c
-void read_png_info(PDF pdf, image_dict * idict, img_readtype_e readtype)
+void read_png_info(image_dict * idict, img_readtype_e readtype)
{
png_structp png_p;
png_infop info_p;
@@ -100,139 +100,154 @@ void read_png_info(PDF pdf, image_dict * idict, img_readtype_e readtype)
}
@ @c
-#define write_gray_pixel_16(r) \
- if (j % 4 == 0||j % 4 == 1) pdf_quick_out(pdf,*r++); \
- else smask[smask_ptr++] = *r++
-
-#define write_gray_pixel_8(r) \
- if (j % 2 == 0) pdf_quick_out(pdf,*r++); \
- else smask[smask_ptr++] = *r++
-
-#define write_rgb_pixel_16(r) \
- if (!(j % 8 == 6||j % 8 == 7)) pdf_quick_out(pdf,*r++); \
- else smask[smask_ptr++] = *r++
-
-#define write_rgb_pixel_8(r) \
- if (j % 4 != 3) pdf_quick_out(pdf,*r++); \
- else smask[smask_ptr++] = *r++
+#define write_gray_pixel_16(r) \
+ if (j % 4 == 0 || j % 4 == 1) \
+ pdf_quick_out(pdf, *r++); \
+ else \
+ smask[smask_ptr++] = *r++ \
+
+#define write_gray_pixel_8(r) \
+ if (j % 2 == 0) \
+ pdf_quick_out(pdf, *r++); \
+ else \
+ smask[smask_ptr++] = *r++
+
+#define write_rgb_pixel_16(r) \
+ if (!(j % 8 == 6 || j % 8 == 7)) \
+ pdf_quick_out(pdf, *r++); \
+ else \
+ smask[smask_ptr++] = *r++
+
+#define write_rgb_pixel_8(r) \
+ if (j % 4 != 3) \
+ pdf_quick_out(pdf, *r++); \
+ else \
+ smask[smask_ptr++] = *r++
#define write_simple_pixel(r) pdf_quick_out(pdf,*r++)
-#define write_noninterlaced(outmac) \
- for (i = 0; i < (int)png_get_image_height (png_p, info_p); i++) { \
- png_read_row(png_p, row, NULL); \
- r = row; \
- k = (int)png_get_rowbytes(png_p, info_p); \
- while(k > 0) { \
- l = (k > pdf->buf_size)? pdf->buf_size : k; \
- pdf_room(pdf,l); \
- for (j = 0; j < l; j++) { \
- outmac; \
- } \
- k -= l; \
- } \
- }
+#define write_noninterlaced(outmac) \
+ for (i = 0; i < (int) png_get_image_height(png_p, info_p); i++) { \
+ png_read_row(png_p, row, NULL); \
+ r = row; \
+ k = (size_t) png_get_rowbytes(png_p, info_p); \
+ while (k > 0) { \
+ l = (k > pdf->buf->size) ? pdf->buf->size : k; \
+ pdf_room(pdf, l); \
+ for (j = 0; j < l; j++) { \
+ outmac; \
+ } \
+ k -= l; \
+ } \
+ }
-#define write_interlaced(outmac) \
- for (i = 0; i < (int)png_get_image_height (png_p, info_p); i++) { \
- row = rows[i]; \
- k = (int)png_get_rowbytes(png_p, info_p); \
- while(k > 0) { \
- l = (k > pdf->buf_size)?pdf->buf_size: k;\
- pdf_room(pdf,l); \
- for (j = 0; j < l; j++) { \
- outmac; \
- } \
- k -= l; \
- } \
- xfree(rows[i]); \
- }
+#define write_interlaced(outmac) \
+ for (i = 0; i < (int) png_get_image_height(png_p, info_p); i++) { \
+ row = rows[i]; \
+ k = (size_t) png_get_rowbytes(png_p, info_p); \
+ while (k > 0) { \
+ l = (k > pdf->buf->size) ? pdf->buf->size : k; \
+ pdf_room(pdf, l); \
+ for (j = 0; j < l; j++) { \
+ outmac; \
+ } \
+ k -= l; \
+ } \
+ xfree(rows[i]); \
+ }
+
+@ @c
+static void write_palette_streamobj(PDF pdf, int palette_objnum,
+ png_colorp palette, int num_palette)
+{
+ int i;
+ if (palette_objnum == 0)
+ return;
+ assert(palette != NULL);
+ pdf_begin_obj(pdf, palette_objnum, OBJSTM_NEVER);
+ pdf_begin_dict(pdf);
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
+ pdf_begin_stream(pdf);
+ for (i = 0; i < num_palette; i++) {
+ pdf_room(pdf, 3);
+ pdf_quick_out(pdf, palette[i].red);
+ pdf_quick_out(pdf, palette[i].green);
+ pdf_quick_out(pdf, palette[i].blue);
+ }
+ pdf_end_stream(pdf);
+ pdf_end_obj(pdf);
+}
@ @c
-static void write_png_palette(PDF pdf, image_dict * idict)
+static void write_smask_streamobj(PDF pdf, image_dict * idict, int smask_objnum,
+ png_bytep smask, int smask_size)
{
- int i, j, k, l;
+ int i;
png_structp png_p = img_png_png_ptr(idict);
png_infop info_p = img_png_info_ptr(idict);
- png_bytep row, r, *rows;
- int palette_objnum = 0;
- png_colorp palette;
- int num_palette;
-
- png_get_PLTE(png_p, info_p, &palette, &num_palette);
-
- if (img_colorspace(idict) != 0) {
- pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
- } else {
- palette_objnum = pdf_create_obj(pdf, obj_type_others, 0);
- pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n",
- (int) (num_palette - 1), (int) palette_objnum);
- }
+ png_byte bitdepth = png_get_bit_depth(png_p, info_p);
+ pdf_begin_obj(pdf, smask_objnum, OBJSTM_NEVER);
+ pdf_begin_dict(pdf);
+ pdf_dict_add_name(pdf, "Type", "XObject");
+ pdf_dict_add_name(pdf, "Subtype", "Image");
+ pdf_dict_add_img_filename(pdf, idict);
+ if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
+ pdf_printf(pdf, "\n%s\n", img_attr(idict));
+ pdf_dict_add_int(pdf, "Width", (int) png_get_image_width(png_p, info_p));
+ pdf_dict_add_int(pdf, "Height", (int) png_get_image_height(png_p, info_p));
+ pdf_dict_add_int(pdf, "BitsPerComponent", (bitdepth == 16 ? 8 : bitdepth));
+ pdf_dict_add_name(pdf, "ColorSpace", "DeviceGray");
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
pdf_begin_stream(pdf);
- if (png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE) {
- row = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
- write_noninterlaced(write_simple_pixel(r));
- xfree(row);
- } else {
- if (png_get_image_height (png_p, info_p) * png_get_rowbytes(png_p, info_p) >= 10240000L)
- pdftex_warn
- ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
- rows = xtalloc(png_get_image_height (png_p, info_p), png_bytep);
- for (i = 0; (unsigned) i < png_get_image_height (png_p, info_p); i++)
- rows[i] = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
- png_read_image(png_p, rows);
- write_interlaced(write_simple_pixel(row));
- xfree(rows);
+ for (i = 0; i < smask_size; i++) {
+ if (i % 8 == 0)
+ pdf_room(pdf, 8);
+ pdf_quick_out(pdf, smask[i]);
+ if (bitdepth == 16)
+ i++;
}
pdf_end_stream(pdf);
- if (palette_objnum > 0) {
- pdf_begin_dict(pdf, palette_objnum, 0);
- pdf_begin_stream(pdf);
- for (i = 0; i < num_palette; i++) {
- pdf_room(pdf, 3);
- pdf_quick_out(pdf, palette[i].red);
- pdf_quick_out(pdf, palette[i].green);
- pdf_quick_out(pdf, palette[i].blue);
- }
- pdf_end_stream(pdf);
- }
+ pdf_end_obj(pdf);
}
@ @c
static void write_png_gray(PDF pdf, image_dict * idict)
{
- int i, j, k, l;
+ int i;
+ size_t j, k, l;
png_structp png_p = img_png_png_ptr(idict);
png_infop info_p = img_png_info_ptr(idict);
png_bytep row, r, *rows;
- if (img_colorspace(idict) != 0) {
- pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
- } else {
- pdf_puts(pdf, "/DeviceGray\n");
- }
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
pdf_begin_stream(pdf);
if (png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE) {
row = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
write_noninterlaced(write_simple_pixel(r));
xfree(row);
} else {
- if (png_get_image_height (png_p, info_p) * png_get_rowbytes(png_p, info_p) >= 10240000L)
+ if (png_get_image_height(png_p, info_p) *
+ png_get_rowbytes(png_p, info_p) >= 10240000L)
pdftex_warn
("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
- rows = xtalloc(png_get_image_height (png_p, info_p), png_bytep);
- for (i = 0; (unsigned) i < png_get_image_height (png_p, info_p); i++)
+ rows = xtalloc(png_get_image_height(png_p, info_p), png_bytep);
+ for (i = 0; i < (int) png_get_image_height(png_p, info_p); i++)
rows[i] = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
png_read_image(png_p, rows);
write_interlaced(write_simple_pixel(row));
xfree(rows);
}
pdf_end_stream(pdf);
+ pdf_end_obj(pdf);
}
@ @c
static void write_png_gray_alpha(PDF pdf, image_dict * idict)
{
- int i, j, k, l;
+ int i;
+ size_t j, k, l;
png_structp png_p = img_png_png_ptr(idict);
png_infop info_p = img_png_info_ptr(idict);
png_bytep row, r, *rows;
@@ -240,34 +255,35 @@ static void write_png_gray_alpha(PDF pdf, image_dict * idict)
png_bytep smask;
int smask_ptr = 0;
int smask_size = 0;
- png_byte bitdepth;
- if (img_colorspace(idict) != 0) {
- pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
- } else {
- pdf_puts(pdf, "/DeviceGray\n");
- }
smask_objnum = pdf_create_obj(pdf, obj_type_others, 0);
- pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum);
- smask_size = (int) ((png_get_rowbytes(png_p, info_p) / 2) * png_get_image_height (png_p, info_p));
+ pdf_dict_add_ref(pdf, "SMask", (int) smask_objnum);
+ smask_size =
+ (int) ((png_get_rowbytes(png_p, info_p) / 2) *
+ png_get_image_height(png_p, info_p));
smask = xtalloc((unsigned) smask_size, png_byte);
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
pdf_begin_stream(pdf);
if (png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE) {
row = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
- if ((png_get_bit_depth(png_p, info_p) == 16) && (pdf->image_hicolor != 0)) {
+ if ((png_get_bit_depth(png_p, info_p) == 16)
+ && (pdf->image_hicolor != 0)) {
write_noninterlaced(write_gray_pixel_16(r));
} else {
write_noninterlaced(write_gray_pixel_8(r));
}
xfree(row);
} else {
- if (png_get_image_height (png_p, info_p) * png_get_rowbytes(png_p, info_p) >= 10240000L)
+ if (png_get_image_height(png_p, info_p) *
+ png_get_rowbytes(png_p, info_p) >= 10240000L)
pdftex_warn
("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
- rows = xtalloc(png_get_image_height (png_p, info_p), png_bytep);
- for (i = 0; (unsigned) i < png_get_image_height (png_p, info_p); i++)
+ rows = xtalloc(png_get_image_height(png_p, info_p), png_bytep);
+ for (i = 0; i < (int) png_get_image_height(png_p, info_p); i++)
rows[i] = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
png_read_image(png_p, rows);
- if ((png_get_bit_depth(png_p, info_p) == 16) && (pdf->image_hicolor != 0)) {
+ if ((png_get_bit_depth(png_p, info_p) == 16)
+ && (pdf->image_hicolor != 0)) {
write_interlaced(write_gray_pixel_16(row));
} else {
write_interlaced(write_gray_pixel_8(row));
@@ -275,65 +291,16 @@ static void write_png_gray_alpha(PDF pdf, image_dict * idict)
xfree(rows);
}
pdf_end_stream(pdf);
- pdf_flush(pdf);
- /* now write the Smask object */
- bitdepth = png_get_bit_depth (png_p, info_p);
- pdf_begin_dict(pdf, smask_objnum, 0);
- pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n");
- if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
- pdf_printf(pdf, "%s\n", img_attr(idict));
- pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n",
- (int) png_get_image_width (png_p, info_p),
- (int) png_get_image_height (png_p, info_p),
- (bitdepth == 16 ? 8 : bitdepth));
- pdf_puts(pdf, "/ColorSpace /DeviceGray\n");
- pdf_begin_stream(pdf);
- for (i = 0; i < smask_size; i++) {
- if (i % 8 == 0)
- pdf_room(pdf, 8);
- pdf_quick_out(pdf, smask[i]);
- if (bitdepth == 16)
- i++;
- }
- pdf_end_stream(pdf);
+ pdf_end_obj(pdf);
+ write_smask_streamobj(pdf, idict, smask_objnum, smask, smask_size);
xfree(smask);
}
@ @c
-static void write_png_rgb(PDF pdf, image_dict * idict)
-{
- int i, j, k, l;
- png_structp png_p = img_png_png_ptr(idict);
- png_infop info_p = img_png_info_ptr(idict);
- png_bytep row, r, *rows;
- if (img_colorspace(idict) != 0) {
- pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
- } else {
- pdf_puts(pdf, "/DeviceRGB\n");
- }
- pdf_begin_stream(pdf);
- if (png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE) {
- row = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
- write_noninterlaced(write_simple_pixel(r));
- xfree(row);
- } else {
- if (png_get_image_height (png_p, info_p) * png_get_rowbytes(png_p, info_p) >= 10240000L)
- pdftex_warn
- ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
- rows = xtalloc(png_get_image_height (png_p, info_p), png_bytep);
- for (i = 0; (unsigned) i < png_get_image_height (png_p, info_p); i++)
- rows[i] = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
- png_read_image(png_p, rows);
- write_interlaced(write_simple_pixel(row));
- xfree(rows);
- }
- pdf_end_stream(pdf);
-}
-
-@ @c
static void write_png_rgb_alpha(PDF pdf, image_dict * idict)
{
- int i, j, k, l;
+ int i;
+ size_t j, k, l;
png_structp png_p = img_png_png_ptr(idict);
png_infop info_p = img_png_info_ptr(idict);
png_bytep row, r, *rows;
@@ -341,34 +308,35 @@ static void write_png_rgb_alpha(PDF pdf, image_dict * idict)
png_bytep smask;
int smask_ptr = 0;
int smask_size = 0;
- png_byte bitdepth;
- if (img_colorspace(idict) != 0) {
- pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
- } else {
- pdf_puts(pdf, "/DeviceRGB\n");
- }
smask_objnum = pdf_create_obj(pdf, obj_type_others, 0);
- pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum);
- smask_size = (int) ((png_get_rowbytes (png_p, info_p) / 4) * png_get_image_height (png_p, info_p));
+ pdf_dict_add_ref(pdf, "SMask", (int) smask_objnum);
+ smask_size =
+ (int) ((png_get_rowbytes(png_p, info_p) / 4) *
+ png_get_image_height(png_p, info_p));
smask = xtalloc((unsigned) smask_size, png_byte);
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
pdf_begin_stream(pdf);
if (png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE) {
row = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
- if ((png_get_bit_depth(png_p, info_p) == 16) && (pdf->image_hicolor != 0)) {
+ if ((png_get_bit_depth(png_p, info_p) == 16)
+ && (pdf->image_hicolor != 0)) {
write_noninterlaced(write_rgb_pixel_16(r));
} else {
write_noninterlaced(write_rgb_pixel_8(r));
}
xfree(row);
} else {
- if (png_get_image_height (png_p, info_p) * png_get_rowbytes(png_p, info_p) >= 10240000L)
+ if (png_get_image_height(png_p, info_p) *
+ png_get_rowbytes(png_p, info_p) >= 10240000L)
pdftex_warn
("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
- rows = xtalloc(png_get_image_height (png_p, info_p), png_bytep);
- for (i = 0; (unsigned) i < png_get_image_height (png_p, info_p); i++)
+ rows = xtalloc(png_get_image_height(png_p, info_p), png_bytep);
+ for (i = 0; i < (int) png_get_image_height(png_p, info_p); i++)
rows[i] = xtalloc(png_get_rowbytes(png_p, info_p), png_byte);
png_read_image(png_p, rows);
- if ((png_get_bit_depth(png_p, info_p) == 16) && (pdf->image_hicolor != 0)) {
+ if ((png_get_bit_depth(png_p, info_p) == 16)
+ && (pdf->image_hicolor != 0)) {
write_interlaced(write_rgb_pixel_16(row));
} else {
write_interlaced(write_rgb_pixel_8(row));
@@ -376,47 +344,29 @@ static void write_png_rgb_alpha(PDF pdf, image_dict * idict)
xfree(rows);
}
pdf_end_stream(pdf);
- pdf_flush(pdf);
- /* now write the Smask object */
- if (smask_objnum > 0) {
- bitdepth = png_get_bit_depth (png_p, info_p);
- pdf_begin_dict(pdf, smask_objnum, 0);
- pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n");
- if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
- pdf_printf(pdf, "%s\n", img_attr(idict));
- pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n",
- (int) png_get_image_width (png_p, info_p),
- (int) png_get_image_height (png_p, info_p),
- (bitdepth == 16 ? 8 : bitdepth));
- pdf_puts(pdf, "/ColorSpace /DeviceGray\n");
- pdf_begin_stream(pdf);
- for (i = 0; i < smask_size; i++) {
- if (i % 8 == 0)
- pdf_room(pdf, 8);
- pdf_quick_out(pdf, smask[i]);
- if (bitdepth == 16)
- i++;
- }
- xfree(smask);
- pdf_end_stream(pdf);
- }
+ pdf_end_obj(pdf);
+ write_smask_streamobj(pdf, idict, smask_objnum, smask, smask_size);
+ xfree(smask);
}
-@ The |copy_png| function is from Hartmut Henkel. The goal is to use
-pdf's native FlateDecode support if that is possible.
-
-Only a subset of the png files allows this, but when possible it
-greatly improves inclusion speed.
-
-Code cheerfully gleaned from Thomas Merz' PDFlib,
-file |p_png.c| "SPNG - Simple PNG"
+@ The |copy_png| code is cheerfully gleaned from Thomas Merz' PDFlib,
+file |p_png.c| ``SPNG - Simple PNG''.
+The goal is to use pdf's native FlateDecode support, if that is possible.
+Only a subset of the png files allows this, but for these it greatly
+improves inclusion speed.
+In the ``PNG Copy'' mode only the IDAT chunks are copied;
+all other chunks from the PNG file are discarded.
+If there are any other chunks in the PNG file,
+which might influence the visual appearance of the image,
+or if image processing like gamma change is requested,
+the ``PNG Copy'' function must be skipped; therefore the lengthy tests.
@c
-static int spng_getint(FILE * fp)
+static int spng_getint(FILE * f)
{
unsigned char buf[4];
- if (fread(buf, 1, 4, fp) != 4)
+ if (fread(buf, 1, 4, f) != 4)
pdftex_fail("writepng: reading chunk type failed");
return ((((((int) buf[0] << 8) + buf[1]) << 8) + buf[2]) << 8) + buf[3];
}
@@ -426,22 +376,22 @@ static int spng_getint(FILE * fp)
static void copy_png(PDF pdf, image_dict * idict)
{
+ int type, streamlength = 0, idat = 0;
+ size_t len;
+ boolean endflag = false;
+ FILE *f;
png_structp png_p;
png_infop info_p;
- FILE *fp;
- int i, len, type, streamlength = 0;
- boolean endflag = false;
- int idat = 0; /* flag to check continuous IDAT chunks sequence */
assert(idict != NULL);
png_p = img_png_png_ptr(idict);
info_p = img_png_info_ptr(idict);
- fp = (FILE *) png_get_io_ptr(png_p);
+ f = (FILE *) png_get_io_ptr(png_p);
/* 1st pass to find overall stream /Length */
- if (fseek(fp, 8, SEEK_SET) != 0)
- pdftex_fail("writepng: fseek in PNG file failed");
+ if (fseek(f, 8, SEEK_SET) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed (1)");
do {
- len = spng_getint(fp);
- type = spng_getint(fp);
+ len = spng_getint(f);
+ type = spng_getint(f);
switch (type) {
case SPNG_CHUNK_IEND:
endflag = true;
@@ -449,64 +399,64 @@ static void copy_png(PDF pdf, image_dict * idict)
case SPNG_CHUNK_IDAT:
streamlength += len;
default:
- if (fseek(fp, len + 4, SEEK_CUR) != 0)
- pdftex_fail("writepng: fseek in PNG file failed");
+ if (fseek(f, len + 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed (2)");
}
} while (endflag == false);
- pdf_printf(pdf, "/Length %d\n"
- "/Filter/FlateDecode\n"
- "/DecodeParms<<"
- "/Colors %d"
- "/Columns %u"
- "/BitsPerComponent %i"
- "/Predictor 10>>\n>>\nstream\n", streamlength,
- png_get_color_type (png_p, info_p) == 2 ? 3 : 1,
- png_get_image_width (png_p, info_p),
- png_get_bit_depth (png_p, info_p));
+ pdf_dict_add_int(pdf, "Length", streamlength);
+ pdf_dict_add_name(pdf, "Filter", "FlateDecode");
+ pdf_add_name(pdf, "DecodeParms");
+ pdf_begin_dict(pdf);
+ pdf_dict_add_int(pdf, "Colors",
+ png_get_color_type(png_p,
+ info_p) == PNG_COLOR_TYPE_RGB ? 3 : 1);
+ pdf_dict_add_int(pdf, "Columns", png_get_image_width(png_p, info_p));
+ pdf_dict_add_int(pdf, "BitsPerComponent", png_get_bit_depth(png_p, info_p));
+ pdf_dict_add_int(pdf, "Predictor", 10);
+ pdf_end_dict(pdf);
+ pdf_end_dict(pdf);
+ pdf_begin_stream(pdf);
+ assert(pdf->zip_write_state == NO_ZIP); /* the PNG stream is already compressed */
/* 2nd pass to copy data */
endflag = false;
- if (fseek(fp, 8, SEEK_SET) != 0)
- pdftex_fail("writepng: fseek in PNG file failed");
+ if (fseek(f, 8, SEEK_SET) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed (3)");
do {
- len = spng_getint(fp);
- type = spng_getint(fp);
+ len = spng_getint(f);
+ type = spng_getint(f);
switch (type) {
case SPNG_CHUNK_IDAT: /* do copy */
if (idat == 2)
pdftex_fail("writepng: IDAT chunk sequence broken");
idat = 1;
- while (len > 0) {
- i = (len > pdf->buf_size) ? pdf->buf_size : len;
- pdf_room(pdf, i);
- fread(&pdf->buf[pdf->ptr], 1, (size_t) i, fp);
- pdf->ptr += i;
- len -= i;
- }
- if (fseek(fp, 4, SEEK_CUR) != 0)
- pdftex_fail("writepng: fseek in PNG file failed");
+ if (read_file_to_buf(pdf, f, len) != len)
+ pdftex_fail("writepng: fread failed");
+ if (fseek(f, 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed (4)");
break;
case SPNG_CHUNK_IEND: /* done */
- pdf_end_stream(pdf);
endflag = true;
break;
default:
if (idat == 1)
idat = 2;
- if (fseek(fp, len + 4, SEEK_CUR) != 0)
- pdftex_fail("writepng: fseek in PNG file failed");
+ if (fseek(f, len + 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed (5)");
}
} while (endflag == false);
+ pdf_end_stream(pdf);
+ pdf_end_obj(pdf);
}
@ @c
-static void reopen_png(PDF pdf, image_dict * idict)
+static void reopen_png(image_dict * idict)
{
int width, height, xres, yres;
width = img_xsize(idict); /* do consistency check */
height = img_ysize(idict);
xres = img_xres(idict);
yres = img_yres(idict);
- read_png_info(pdf, idict, IMG_KEEPOPEN);
+ read_png_info(idict, IMG_KEEPOPEN);
if (width != img_xsize(idict) || height != img_ysize(idict)
|| xres != img_xres(idict) || yres != img_yres(idict))
pdftex_fail("writepng: image dimensions have changed");
@@ -517,29 +467,24 @@ static boolean last_png_needs_page_group;
void write_png(PDF pdf, image_dict * idict)
{
+#ifndef PNG_FP_1
+ /* for libpng < 1.5.0 */
+# define PNG_FP_1 100000
+#endif
+ int num_palette, palette_objnum = 0;
boolean png_copy = true;
double gamma = 0.0;
png_fixed_point int_file_gamma = 0;
-#ifndef PNG_FP_1
- /* for libpng < 1.5.0 */
-#define PNG_FP_1 100000
-#endif
- int i;
- int palette_objnum = 0;
png_structp png_p;
png_infop info_p;
+ png_colorp palette;
assert(idict != NULL);
last_png_needs_page_group = false;
if (img_file(idict) == NULL)
- reopen_png(pdf, idict);
+ reopen_png(idict);
assert(img_png_ptr(idict) != NULL);
png_p = img_png_png_ptr(idict);
info_p = img_png_info_ptr(idict);
- if (pdf->minor_version < 5)
- pdf->image_hicolor = 0;
- pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n");
- if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
- pdf_printf(pdf, "%s\n", img_attr(idict));
/* simple transparency support */
if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png_p);
@@ -575,11 +520,45 @@ void write_png(PDF pdf, image_dict * idict)
(void) png_set_interlace_handling(png_p);
png_read_update_info(png_p, info_p);
- pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n",
- (int) png_get_image_width(png_p, info_p),
- (int) png_get_image_height(png_p, info_p),
- (int) png_get_bit_depth(png_p, info_p));
- pdf_puts(pdf, "/ColorSpace ");
+ pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER);
+ pdf_begin_dict(pdf);
+ pdf_dict_add_name(pdf, "Type", "XObject");
+ pdf_dict_add_name(pdf, "Subtype", "Image");
+ pdf_dict_add_img_filename(pdf, idict);
+ if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
+ pdf_printf(pdf, "\n%s\n", img_attr(idict));
+ pdf_dict_add_int(pdf, "Width", (int) png_get_image_width(png_p, info_p));
+ pdf_dict_add_int(pdf, "Height", (int) png_get_image_height(png_p, info_p));
+ pdf_dict_add_int(pdf, "BitsPerComponent",
+ (int) png_get_bit_depth(png_p, info_p));
+ if (img_colorspace(idict) != 0) {
+ pdf_dict_add_ref(pdf, "ColorSpace", (int) img_colorspace(idict));
+ } else {
+ switch (png_get_color_type(png_p, info_p)) {
+ case PNG_COLOR_TYPE_PALETTE:
+ png_get_PLTE(png_p, info_p, &palette, &num_palette);
+ palette_objnum = pdf_create_obj(pdf, obj_type_others, 0);
+ pdf_add_name(pdf, "ColorSpace");
+ pdf_begin_array(pdf);
+ pdf_add_name(pdf, "Indexed");
+ pdf_add_name(pdf, "DeviceRGB"); /* base; PDFRef. 4.5.5 */
+ pdf_add_int(pdf, (int) (num_palette - 1)); /* hival */
+ pdf_add_ref(pdf, (int) palette_objnum); /* lookup */
+ pdf_end_array(pdf);
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ pdf_dict_add_name(pdf, "ColorSpace", "DeviceGray");
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ pdf_dict_add_name(pdf, "ColorSpace", "DeviceRGB");
+ break;
+ default:
+ pdftex_fail("unsupported type of color_type <%i>",
+ png_get_color_type(png_p, info_p));
+ }
+ }
if (png_copy && pdf->minor_version > 1
&& png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE
&& (png_get_color_type(png_p, info_p) == PNG_COLOR_TYPE_GRAY
@@ -594,43 +573,11 @@ void write_png(PDF pdf, image_dict * idict)
&& !png_get_valid(png_p, info_p, PNG_INFO_bKGD)
&& !png_get_valid(png_p, info_p, PNG_INFO_hIST)
&& !png_get_valid(png_p, info_p, PNG_INFO_tRNS)
- && !png_get_valid(png_p, info_p, PNG_INFO_sPLT)
- ) {
- /* Copy PNG */
- png_colorp palette;
- int num_palette;
-
- png_get_PLTE(png_p, info_p, &palette, &num_palette);
- if (img_colorspace(idict) != 0) {
- pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict));
- } else {
- switch (png_get_color_type(png_p, info_p)) {
- case PNG_COLOR_TYPE_PALETTE:
- palette_objnum = pdf_create_obj(pdf, obj_type_others, 0);
- pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n",
- num_palette - 1, (int) palette_objnum);
- break;
- case PNG_COLOR_TYPE_GRAY:
- pdf_puts(pdf, "/DeviceGray\n");
- break;
- default: /* RGB */
- pdf_puts(pdf, "/DeviceRGB\n");
- };
- }
+ && !png_get_valid(png_p, info_p, PNG_INFO_sPLT)) {
+ /* PNG copy */
if (tracefilenames)
tex_printf(" (PNG copy)");
copy_png(pdf, idict);
- if (palette_objnum > 0) {
- pdf_begin_dict(pdf, palette_objnum, 0);
- pdf_begin_stream(pdf);
- for (i = 0; i < num_palette; i++) {
- pdf_room(pdf, 3);
- pdf_quick_out(pdf, palette[i].red);
- pdf_quick_out(pdf, palette[i].green);
- pdf_quick_out(pdf, palette[i].blue);
- }
- pdf_end_stream(pdf);
- }
} else {
if (0) {
tex_printf(" *** PNG copy skipped because: ");
@@ -667,9 +614,8 @@ void write_png(PDF pdf, image_dict * idict)
}
switch (png_get_color_type(png_p, info_p)) {
case PNG_COLOR_TYPE_PALETTE:
- write_png_palette(pdf, idict);
- break;
case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_RGB:
write_png_gray(pdf, idict);
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
@@ -679,22 +625,18 @@ void write_png(PDF pdf, image_dict * idict)
} else
write_png_gray(pdf, idict);
break;
- case PNG_COLOR_TYPE_RGB:
- write_png_rgb(pdf, idict);
- break;
case PNG_COLOR_TYPE_RGB_ALPHA:
if (pdf->minor_version >= 4) {
write_png_rgb_alpha(pdf, idict);
last_png_needs_page_group = true;
} else
- write_png_rgb(pdf, idict);
+ write_png_gray(pdf, idict);
break;
default:
- pdftex_fail("unsupported type of color_type <%i>",
- png_get_color_type(png_p, info_p));
+ assert(0);
}
}
- pdf_flush(pdf);
+ write_palette_streamobj(pdf, palette_objnum, palette, num_palette);
close_and_cleanup_png(idict);
}
@@ -709,7 +651,7 @@ void write_additional_png_objects(PDF pdf)
(void) pdf;
(void) transparent_page_group;
(void) transparent_page_group_was_written;
- return; /* this interferes with current macro-based usage and cannot be configured */
+ return; /* this interferes with current macro-based usage and cannot be configured */
#if 0
if (last_png_needs_page_group) {
if (!transparent_page_group_was_written && transparent_page_group > 1) {
@@ -719,9 +661,13 @@ void write_additional_png_objects(PDF pdf)
if (pdf->compress_level == 0) {
pdf_puts(pdf, "%PTEX Group needed for transparent pngs\n");
}
- pdf_puts
- (pdf,
- "<</Type/Group /S/Transparency /CS/DeviceRGB /I true /K true>>\n");
+ pdf_begin_dict(pdf);
+ pdf_dict_add_name(pdf, "Type", "Group");
+ pdf_dict_add_name(pdf, "S", "Transparency");
+ pdf_dict_add_name(pdf, "CS", "DeviceRGB");
+ pdf_dict_add_bool(pdf, "I", 1);
+ pdf_dict_add_bool(pdf, "K", 1);
+ pdf_end_dict(pdf);
pdf_end_obj(pdf);
}
}