diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image/writepng.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writepng.c | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.c b/Build/source/texk/web2c/luatexdir/image/writepng.c new file mode 100644 index 00000000000..165e202f4e3 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writepng.c @@ -0,0 +1,645 @@ +/* + +writepng.c + +Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> +Copyright 2006-2013 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/>. + +*/ + +#include "ptexlib.h" +#include <assert.h> +#include "image/image.h" +#include "image/writepng.h" + +static void close_and_cleanup_png(image_dict * idict) +{ + if (img_file(idict) != NULL) { + xfclose(img_file(idict), img_filepath(idict)); + img_file(idict) = NULL; + } + if (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)); + } +} + +void flush_png_info(image_dict * idict) +{ + close_and_cleanup_png(idict); +} + +/*tex A dummy function: */ + +static void warn(png_structp png_ptr, png_const_charp msg) +{ + (void)png_ptr; (void)msg; +} + +void read_png_info(image_dict * idict) +{ + png_structp png_p; + png_infop info_p; + if (img_type(idict) != IMG_TYPE_PNG) { + normal_error("readpng","conflicting image dictionary"); + } + if (img_file(idict) != NULL) { + normal_error("readpng","image data already read"); + } + img_totalpages(idict) = 1; + img_pagenum(idict) = 1; + img_xres(idict) = img_yres(idict) = 0; + img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE); + img_png_ptr(idict) = xtalloc(1, png_img_struct); + if ((png_p = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, warn)) == NULL) { + normal_error("readpng","png_create_read_struct() failed"); + } + img_png_png_ptr(idict) = png_p; + if ((info_p = png_create_info_struct(png_p)) == NULL) { + normal_error("readpng","png_create_info_struct() failed"); + } + img_png_info_ptr(idict) = info_p; + if (setjmp(png_jmpbuf(png_p))) { + normal_error("readpng","internal error"); + } +#if PNG_LIBPNG_VER >= 10603 + /*tex ignore possibly incorrect CMF bytes */ + png_set_option(png_p, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON); +#endif + png_init_io(png_p, img_file(idict)); + png_read_info(png_p, info_p); + /*tex resolution support */ + img_xsize(idict) = (int) png_get_image_width(png_p, info_p); + img_ysize(idict) = (int) png_get_image_height(png_p, info_p); + if (png_get_valid(png_p, info_p, 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 (png_get_color_type(png_p, info_p)) { + 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: + formatted_error("readpng","unsupported type of color_type '%i'",(int) png_get_color_type(png_p, info_p)); + } + img_colordepth(idict) = png_get_bit_depth(png_p, info_p); + /*tex So we can optionally keep open a file in |img|. */ + if (! img_keepopen(idict)) { + close_and_cleanup_png(idict); + } +} + +#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 = (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 = (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]); \ + } + +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); +} + +static void write_smask_streamobj(PDF pdf, image_dict * idict, int smask_objnum, png_bytep smask, int smask_size) +{ + int i; + png_structp png_p = img_png_png_ptr(idict); + png_infop info_p = img_png_info_ptr(idict); + 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); + 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); +} + +static void write_png_gray(PDF pdf, image_dict * idict) +{ + 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; + 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) { + formatted_warning("pngwrite","large interlaced bitmap might cause out of memory"); + } + 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); +} + +static void write_png_gray_alpha(PDF pdf, image_dict * idict) +{ + 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; + int smask_objnum = 0; + png_bytep smask; + int smask_ptr = 0; + int smask_size = 0; + smask_objnum = pdf_create_obj(pdf, obj_type_others, 0); + 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)) { + 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) { + formatted_warning("pngwrite","large interlaced bitmap might cause out of memory"); + } + 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)) { + write_interlaced(write_gray_pixel_16(row)); + } else { + write_interlaced(write_gray_pixel_8(row)); + } + xfree(rows); + } + pdf_end_stream(pdf); + pdf_end_obj(pdf); + write_smask_streamobj(pdf, idict, smask_objnum, smask, smask_size); + xfree(smask); +} + +static void write_png_rgb_alpha(PDF pdf, image_dict * idict) +{ + 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; + int smask_objnum = 0; + png_bytep smask; + int smask_ptr = 0; + int smask_size = 0; + smask_objnum = pdf_create_obj(pdf, obj_type_others, 0); + 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)) { + 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) { + formatted_warning("pngwrite","large interlaced bitmap might cause out of memory"); + } + 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)) { + write_interlaced(write_rgb_pixel_16(row)); + } else { + write_interlaced(write_rgb_pixel_8(row)); + } + xfree(rows); + } + pdf_end_stream(pdf); + pdf_end_obj(pdf); + write_smask_streamobj(pdf, idict, smask_objnum, smask, smask_size); + xfree(smask); +} + +/*tex + +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. + +*/ + +static int spng_getint(FILE * f) +{ + unsigned char buf[4]; + if (fread(buf, 1, 4, f) != 4) { + normal_error("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) +{ + int type, streamlength = 0, idat = 0; + size_t len; + boolean endflag = false; + FILE *f; + png_structp png_p; + png_infop info_p; + assert(idict != NULL); + png_p = img_png_png_ptr(idict); + info_p = img_png_info_ptr(idict); + f = (FILE *) png_get_io_ptr(png_p); + /*tex 1st pass to find overall stream /Length */ + if (fseek(f, 8, SEEK_SET) != 0) + normal_error("writepng", "fseek in file failed"); + do { + len = spng_getint(f); + type = spng_getint(f); + switch (type) { + case SPNG_CHUNK_IEND: + endflag = true; + break; + case SPNG_CHUNK_IDAT: + streamlength += len; + default: + if (fseek(f, len + 4, SEEK_CUR) != 0) { + normal_error("writepng", "fseek in file failed"); + } + } + } while (endflag == false); + 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); + /*tex 2nd pass to copy data */ + endflag = false; + if (fseek(f, 8, SEEK_SET) != 0) + normal_error("writepng", "fseek in file failed"); + do { + len = spng_getint(f); + type = spng_getint(f); + switch (type) { + case SPNG_CHUNK_IDAT: + /*tex do copy */ + if (idat == 2) { + normal_error("writepng", "IDAT chunk sequence broken"); + } + idat = 1; + if (read_file_to_buf(pdf, f, len) != len) { + normal_error("writepng", "fread failed"); + } else if (fseek(f, 4, SEEK_CUR) != 0) { + normal_error("writepng", "fseek in file failed"); + } + break; + case SPNG_CHUNK_IEND: + /*tex done */ + endflag = true; + break; + default: + if (idat == 1) + idat = 2; + if (fseek(f, len + 4, SEEK_CUR) != 0) + normal_error("writepng", "fseek in file failed"); + } + } while (endflag == false); + pdf_end_stream(pdf); + pdf_end_obj(pdf); +} + +static void reopen_png(image_dict * idict) +{ + int width, height, xres, yres; + /*tex A consistency check: */ + width = img_xsize(idict); + height = img_ysize(idict); + xres = img_xres(idict); + yres = img_yres(idict); + /*tex We need to ake sure that the file kept open. */ + img_keepopen(idict) = 1; + read_png_info(idict); + if (width != img_xsize(idict) || height != img_ysize(idict) || xres != img_xres(idict) || yres != img_yres(idict)) { + normal_error("writepng", "image dimensions have changed"); + } +} + +void write_png(PDF pdf, image_dict * idict) +{ +#ifndef PNG_FP_1 + /*tex 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; + png_structp png_p; + png_infop info_p; + png_colorp palette; + assert(idict != NULL); + if (img_file(idict) == NULL) + reopen_png(idict); + assert(img_png_ptr(idict) != NULL); + png_p = img_png_png_ptr(idict); + info_p = img_png_info_ptr(idict); + /*tex simple transparency support */ + if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png_p); + png_copy = false; + } + /*tex alpha channel support */ + if (pdf->minor_version < 4 + && png_get_color_type(png_p, info_p) | PNG_COLOR_MASK_ALPHA) { + png_set_strip_alpha(png_p); + png_copy = false; + } + /*tex 16 bit depth support */ + if (pdf->minor_version < 5) + pdf->image_hicolor = 0; + if ((png_get_bit_depth(png_p, info_p) == 16) && (pdf->image_hicolor == 0)) { + png_set_strip_16(png_p); + png_copy = false; + } + /*tex gamma support */ + if (png_get_valid(png_p, info_p, PNG_INFO_gAMA)) { + png_get_gAMA(png_p, info_p, &gamma); + png_get_gAMA_fixed(png_p, info_p, &int_file_gamma); + } + if (pdf->image_apply_gamma) { + if (png_get_valid(png_p, info_p, PNG_INFO_gAMA)) + 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)); + png_copy = false; + } + /*tex reset structure */ + (void) png_set_interlace_handling(png_p); + png_read_update_info(png_p, info_p); + 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"); + /*tex hival */ + pdf_add_int(pdf, (int) (num_palette - 1)); + /*tex lookup */ + pdf_add_ref(pdf, (int) palette_objnum); + 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: + formatted_error("writepng", "unsupported 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 + || png_get_color_type(png_p, info_p) == PNG_COLOR_TYPE_RGB) + && !pdf->image_apply_gamma + && (!png_get_valid(png_p, info_p, PNG_INFO_gAMA) || int_file_gamma == PNG_FP_1) + && !png_get_valid(png_p, info_p, PNG_INFO_cHRM) + && !png_get_valid(png_p, info_p, PNG_INFO_iCCP) + && !png_get_valid(png_p, info_p, PNG_INFO_sBIT) + && !png_get_valid(png_p, info_p, PNG_INFO_sRGB) + && !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(pdf, idict); + } else { + if (img_errorlevel(idict) > 1) { + if (!png_copy) + normal_warning("pngcopy","failed"); + if (!(pdf->minor_version > 1)) + formatted_warning("pngcopy","skipped because minorversion is '%d'", pdf->minor_version); + if (!(png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE)) + normal_warning("pngcopy","skipped because of interlacing"); + if (!((png_get_color_type(png_p, info_p) == PNG_COLOR_TYPE_GRAY) + || (png_get_color_type(png_p, info_p) == PNG_COLOR_TYPE_RGB))) + normal_warning("pngcopy","skipped because of colortype"); + if (pdf->image_apply_gamma) + normal_warning("pngcopy","skipped because of gamma (1)"); + if (!(!png_get_valid(png_p, info_p, PNG_INFO_gAMA) || int_file_gamma == PNG_FP_1)) + normal_warning("pngcopy","skipped because of gamma (2)"); + if (png_get_valid(png_p, info_p, PNG_INFO_cHRM)) + normal_warning("pngcopy","skipped because of cHRM"); + if (png_get_valid(png_p, info_p, PNG_INFO_iCCP)) + normal_warning("pngcopy","skipped because of iCCP"); + if (png_get_valid(png_p, info_p, PNG_INFO_sBIT)) + normal_warning("pngcopy","skipped because of sBIT"); + if (png_get_valid(png_p, info_p, PNG_INFO_sRGB)) + normal_warning("pngcopy","skipped because of sRGB"); + if (png_get_valid(png_p, info_p, PNG_INFO_bKGD)) + normal_warning("pngcopy","skipped because of bKGD"); + if (png_get_valid(png_p, info_p, PNG_INFO_hIST)) + normal_warning("pngcopy","skipped because of hIST"); + if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) + normal_warning("pngcopy","skipped because of tRNS"); + if (png_get_valid(png_p, info_p, PNG_INFO_sPLT)) + normal_warning("pngcopy","skipped because of sPLT"); + } + switch (png_get_color_type(png_p, info_p)) { + case PNG_COLOR_TYPE_PALETTE: + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_RGB: + write_png_gray(pdf, idict); + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (pdf->minor_version >= 4) { + write_png_gray_alpha(pdf, idict); + } else + write_png_gray(pdf, idict); + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (pdf->minor_version >= 4) { + write_png_rgb_alpha(pdf, idict); + } else + write_png_gray(pdf, idict); + break; + default: + assert(0); + } + } + write_palette_streamobj(pdf, palette_objnum, palette, num_palette); + /*tex always */ + close_and_cleanup_png(idict); +} + + +/*tex + + Called after the xobject generated by |write_png| has been finished; used to + write out additional objects. + +*/ + +void write_additional_png_objects(PDF pdf) +{ + (void) pdf; + return; +} |