diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image/writepng.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writepng.w | 586 |
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); } } |