diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image/writepng.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writepng.w | 689 |
1 files changed, 689 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.w b/Build/source/texk/web2c/luatexdir/image/writepng.w new file mode 100644 index 00000000000..1b8ecb56b49 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writepng.w @@ -0,0 +1,689 @@ +% writepng.w + +% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> +% Copyright 2006-2010 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/>. + +@ @c +static const char _svn_version[] = + "$Id: writepng.w 3584 2010-04-02 17:45:55Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/image/writepng.w $"; + +#include <assert.h> +#include "ptexlib.h" +#include "image/image.h" + +@ @c +static int transparent_page_group = -1; + +static void close_and_cleanup_png(image_dict * idict) +{ + assert(idict != NULL); + assert(img_file(idict) != NULL); + assert(img_filepath(idict) != NULL); + xfclose(img_file(idict), img_filepath(idict)); + img_file(idict) = NULL; + assert(img_png_ptr(idict) != NULL); + png_destroy_read_struct(&(img_png_png_ptr(idict)), + &(img_png_info_ptr(idict)), NULL); + xfree(img_png_ptr(idict)); + img_png_ptr(idict) = NULL; +} + +@ @c +void read_png_info(PDF pdf, image_dict * idict, img_readtype_e readtype) +{ + double gamma; + png_structp png_p; + png_infop info_p; + assert(idict != NULL); + assert(img_type(idict) == IMG_TYPE_PNG); + img_totalpages(idict) = 1; + img_pagenum(idict) = 1; + img_xres(idict) = img_yres(idict) = 0; + assert(img_file(idict) == NULL); + img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE); + assert(img_png_ptr(idict) == NULL); + img_png_ptr(idict) = xtalloc(1, png_img_struct); + if ((png_p = png_create_read_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL)) == NULL) + pdftex_fail("libpng: png_create_read_struct() failed"); + img_png_png_ptr(idict) = png_p; + if ((info_p = png_create_info_struct(png_p)) == NULL) + pdftex_fail("libpng: png_create_info_struct() failed"); + img_png_info_ptr(idict) = info_p; + if (setjmp(png_p->jmpbuf)) + pdftex_fail("libpng: internal error"); + png_init_io(png_p, img_file(idict)); + png_read_info(png_p, info_p); + /* simple transparency support */ + if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png_p); + } + /* alpha channel support */ + if (pdf->minor_version < 4 && png_p->color_type | PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_p); + /* 16bit depth support */ + if (pdf->minor_version < 5) + pdf->image_hicolor = 0; + if ((info_p->bit_depth == 16) && (pdf->image_hicolor == 0)) + png_set_strip_16(png_p); + /* gamma support */ + if (pdf->image_apply_gamma) { + if (png_get_gAMA(png_p, info_p, &gamma)) + png_set_gamma(png_p, (pdf->gamma / 1000.0), gamma); + else + png_set_gamma(png_p, (pdf->gamma / 1000.0), + (1000.0 / pdf->image_gamma)); + } + /* reset structure */ + png_read_update_info(png_p, info_p); + /* resolution support */ + img_xsize(idict) = (int) info_p->width; + img_ysize(idict) = (int) info_p->height; + if (info_p->valid & PNG_INFO_pHYs) { + img_xres(idict) = + round(0.0254 * (double) png_get_x_pixels_per_meter(png_p, info_p)); + img_yres(idict) = + round(0.0254 * (double) png_get_y_pixels_per_meter(png_p, info_p)); + } + switch (info_p->color_type) { + case PNG_COLOR_TYPE_PALETTE: + img_procset(idict) |= PROCSET_IMAGE_C | PROCSET_IMAGE_I; + break; + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_GRAY_ALPHA: + img_procset(idict) |= PROCSET_IMAGE_B; + break; + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + img_procset(idict) |= PROCSET_IMAGE_C; + break; + default: + pdftex_fail("unsupported type of color_type <%i>", info_p->color_type); + } + img_colordepth(idict) = info_p->bit_depth; + if (readtype == IMG_CLOSEINBETWEEN) + close_and_cleanup_png(idict); +} + +@ @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_simple_pixel(r) pdf_quick_out(pdf,*r++) + +#define write_noninterlaced(outmac) \ + for (i = 0; i < (int)info_p->height; i++) { \ + png_read_row(png_p, row, NULL); \ + r = row; \ + k = (int)info_p->rowbytes; \ + 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)info_p->height; i++) { \ + row = rows[i]; \ + k = (int)info_p->rowbytes; \ + 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_png_palette(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; + int palette_objnum = 0; + if (img_colorspace(idict) != 0) { + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); + } else { + pdf_create_obj(pdf, obj_type_others, 0); + palette_objnum = pdf->obj_ptr; + pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n", + (int) (info_p->num_palette - 1), (int) palette_objnum); + } + pdf_begin_stream(pdf); + if (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + write_noninterlaced(write_simple_pixel(r)); + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, png_byte); + png_read_image(png_p, rows); + write_interlaced(write_simple_pixel(row)); + xfree(rows); + } + pdf_end_stream(pdf); + if (palette_objnum > 0) { + pdf_begin_dict(pdf, palette_objnum, 0); + pdf_begin_stream(pdf); + for (i = 0; (unsigned) i < info_p->num_palette; i++) { + pdf_room(pdf, 3); + pdf_quick_out(pdf, info_p->palette[i].red); + pdf_quick_out(pdf, info_p->palette[i].green); + pdf_quick_out(pdf, info_p->palette[i].blue); + } + pdf_end_stream(pdf); + } +} + +@ @c +static void write_png_gray(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, "/DeviceGray\n"); + } + pdf_begin_stream(pdf); + if (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + write_noninterlaced(write_simple_pixel(r)); + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, 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_gray_alpha(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; + int smask_objnum = 0; + png_bytep smask; + int smask_ptr = 0; + int smask_size = 0; + int bitdepth; + if (img_colorspace(idict) != 0) { + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); + } else { + pdf_puts(pdf, "/DeviceGray\n"); + } + pdf_create_obj(pdf, obj_type_others, 0); + smask_objnum = pdf->obj_ptr; + pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum); + smask_size = (int) ((info_p->rowbytes / 2) * info_p->height); + smask = xtalloc((unsigned) smask_size, png_byte); + pdf_begin_stream(pdf); + if (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) { + write_noninterlaced(write_gray_pixel_16(r)); + } else { + write_noninterlaced(write_gray_pixel_8(r)); + } + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, png_byte); + png_read_image(png_p, rows); + if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) { + write_interlaced(write_gray_pixel_16(row)); + } else { + write_interlaced(write_gray_pixel_8(row)); + } + xfree(rows); + } + pdf_end_stream(pdf); + pdf_flush(pdf); + /* now write the Smask object */ + bitdepth = (int) info_p->bit_depth; + 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) info_p->width, + (int) info_p->height, (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); + 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 (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + write_noninterlaced(write_simple_pixel(r)); + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, 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; + png_structp png_p = img_png_png_ptr(idict); + png_infop info_p = img_png_info_ptr(idict); + png_bytep row, r, *rows; + int smask_objnum = 0; + png_bytep smask; + int smask_ptr = 0; + int smask_size = 0; + int bitdepth; + if (img_colorspace(idict) != 0) { + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); + } else { + pdf_puts(pdf, "/DeviceRGB\n"); + } + pdf_create_obj(pdf, obj_type_others, 0); + smask_objnum = pdf->obj_ptr; + pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum); + smask_size = (int) ((info_p->rowbytes / 2) * info_p->height); + smask = xtalloc((unsigned) smask_size, png_byte); + pdf_begin_stream(pdf); + if (info_p->interlace_type == PNG_INTERLACE_NONE) { + row = xtalloc(info_p->rowbytes, png_byte); + if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) { + write_noninterlaced(write_rgb_pixel_16(r)); + } else { + write_noninterlaced(write_rgb_pixel_8(r)); + } + xfree(row); + } else { + if (info_p->height * info_p->rowbytes >= 10240000L) + pdftex_warn + ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)"); + rows = xtalloc(info_p->height, png_bytep); + for (i = 0; (unsigned) i < info_p->height; i++) + rows[i] = xtalloc(info_p->rowbytes, png_byte); + png_read_image(png_p, rows); + if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) { + write_interlaced(write_rgb_pixel_16(row)); + } else { + write_interlaced(write_rgb_pixel_8(row)); + } + xfree(rows); + } + pdf_end_stream(pdf); + pdf_flush(pdf); + /* now write the Smask object */ + if (smask_objnum > 0) { + bitdepth = (int) info_p->bit_depth; + 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) info_p->width, + (int) info_p->height, (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); + } +} + +@ 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" + + +@c +static int spng_getint(FILE * fp) +{ + unsigned char buf[4]; + if (fread(buf, 1, 4, fp) != 4) + pdftex_fail("writepng: reading chunk type failed"); + return ((((((int) buf[0] << 8) + buf[1]) << 8) + buf[2]) << 8) + buf[3]; +} + +#define SPNG_CHUNK_IDAT 0x49444154 +#define SPNG_CHUNK_IEND 0x49454E44 + +static void copy_png(PDF pdf, image_dict * idict) +{ + 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_p->io_ptr; + /* 1st pass to find overall stream /Length */ + if (fseek(fp, 8, SEEK_SET) != 0) + pdftex_fail("writepng: fseek in PNG file failed"); + do { + len = spng_getint(fp); + type = spng_getint(fp); + switch (type) { + case SPNG_CHUNK_IEND: + endflag = true; + break; + case SPNG_CHUNK_IDAT: + streamlength += len; + default: + if (fseek(fp, len + 4, SEEK_CUR) != 0) + pdftex_fail("writepng: fseek in PNG file failed"); + } + } while (endflag == false); + pdf_printf(pdf, "/Length %d\n" + "/Filter/FlateDecode\n" + "/DecodeParms<<" + "/Colors %d" + "/Columns %d" + "/BitsPerComponent %i" + "/Predictor 10>>\n>>\nstream\n", streamlength, + info_p->color_type == 2 ? 3 : 1, + (int) info_p->width, info_p->bit_depth); + /* 2nd pass to copy data */ + endflag = false; + if (fseek(fp, 8, SEEK_SET) != 0) + pdftex_fail("writepng: fseek in PNG file failed"); + do { + len = spng_getint(fp); + type = spng_getint(fp); + 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"); + 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"); + } + } while (endflag == false); +} + +@ @c +static void reopen_png(PDF pdf, 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); + if (width != img_xsize(idict) || height != img_ysize(idict) + || xres != img_xres(idict) || yres != img_yres(idict)) + pdftex_fail("writepng: image dimensions have changed"); +} + +@ @c +static boolean last_png_needs_page_group; + +void write_png(PDF pdf, image_dict * idict) +{ + double gamma, checked_gamma; + int i; + int palette_objnum = 0; + png_structp png_p; + png_infop info_p; + assert(idict != NULL); + last_png_needs_page_group = false; + if (img_file(idict) == NULL) + reopen_png(pdf, 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)); + pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n", + (int) info_p->width, + (int) info_p->height, (int) info_p->bit_depth); + pdf_puts(pdf, "/ColorSpace "); + checked_gamma = 1.0; + if (pdf->image_apply_gamma) { + if (png_get_gAMA(png_p, info_p, &gamma)) { + checked_gamma = (pdf->gamma / 1000.0) * gamma; + } else { + checked_gamma = (pdf->gamma / 1000.0) * (1000.0 / pdf->image_gamma); + } + } + /* the switching between |info_p| and |png_p| queries has been trial and error. + */ + if (pdf->minor_version > 1 && info_p->interlace_type == PNG_INTERLACE_NONE && + (png_p->transformations == 0 || png_p->transformations == 0x2000) /* gamma */ + &&!(png_p->color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + png_p->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + && ((pdf->image_hicolor != 0) || (png_p->bit_depth <= 8)) + && (checked_gamma <= 1.01 && checked_gamma > 0.99) + ) { + if (img_colorspace(idict) != 0) { + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); + } else { + switch (info_p->color_type) { + case PNG_COLOR_TYPE_PALETTE: + pdf_create_obj(pdf, obj_type_others, 0); + palette_objnum = pdf->obj_ptr; + pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n", + (int) (info_p->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"); + }; + } + 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; (unsigned) i < info_p->num_palette; i++) { + pdf_room(pdf, 3); + pdf_quick_out(pdf, info_p->palette[i].red); + pdf_quick_out(pdf, info_p->palette[i].green); + pdf_quick_out(pdf, info_p->palette[i].blue); + } + pdf_end_stream(pdf); + } + } else { + if (0) { + tex_printf(" PNG copy skipped because: "); + if ((pdf->image_apply_gamma != 0) && + (checked_gamma > 1.01 || checked_gamma < 0.99)) + tex_printf("gamma delta=%lf ", checked_gamma); + if (png_p->transformations != PNG_TRANSFORM_IDENTITY) + tex_printf("transform=%lu", (long) png_p->transformations); + if ((info_p->color_type != PNG_COLOR_TYPE_GRAY) + && (info_p->color_type != PNG_COLOR_TYPE_RGB) + && (info_p->color_type != PNG_COLOR_TYPE_PALETTE)) + tex_printf("colortype "); + if (pdf->minor_version <= 1) + tex_printf("version=%d ", pdf->minor_version); + if (info_p->interlace_type != PNG_INTERLACE_NONE) + tex_printf("interlaced "); + if (info_p->bit_depth > 8) + tex_printf("bitdepth=%d ", info_p->bit_depth); + if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) + tex_printf("simple transparancy "); + } + switch (info_p->color_type) { + case PNG_COLOR_TYPE_PALETTE: + write_png_palette(pdf, idict); + break; + case PNG_COLOR_TYPE_GRAY: + write_png_gray(pdf, idict); + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (pdf->minor_version >= 4) { + write_png_gray_alpha(pdf, idict); + last_png_needs_page_group = true; + } 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); + break; + default: + pdftex_fail("unsupported type of color_type <%i>", + info_p->color_type); + } + } + pdf_flush(pdf); + close_and_cleanup_png(idict); +} + +@ @c +static boolean transparent_page_group_was_written = false; + +@ Called after the xobject generated by |write_png| has been finished; used to +write out additional objects +@c +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 */ +#if 0 + if (last_png_needs_page_group) { + if (!transparent_page_group_was_written && transparent_page_group > 1) { + /* create new group object */ + transparent_page_group_was_written = true; + pdf_begin_obj(pdf, transparent_page_group, 2); + 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_end_obj(pdf); + } + } +#endif +} |