diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2011-05-03 14:58:54 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2011-05-03 14:58:54 +0000 |
commit | e857b8207ecc2ab412cc3e74218c80b508f66561 (patch) | |
tree | 3cb8f140142a9d52cc3ccb927024330580039443 /Build/source/texk/dvipdfmx/dvipdfmx-20110309/src/pngimage.c | |
parent | 8d82da46f9f3c1c2e75a18edcb4224af1673b855 (diff) |
dvipdfmx 20110311
git-svn-id: svn://tug.org/texlive/trunk@22294 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipdfmx/dvipdfmx-20110309/src/pngimage.c')
-rw-r--r-- | Build/source/texk/dvipdfmx/dvipdfmx-20110309/src/pngimage.c | 1064 |
1 files changed, 0 insertions, 1064 deletions
diff --git a/Build/source/texk/dvipdfmx/dvipdfmx-20110309/src/pngimage.c b/Build/source/texk/dvipdfmx/dvipdfmx-20110309/src/pngimage.c deleted file mode 100644 index 12932be9f39..00000000000 --- a/Build/source/texk/dvipdfmx/dvipdfmx-20110309/src/pngimage.c +++ /dev/null @@ -1,1064 +0,0 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pngimage.c,v 1.29 2011/03/06 03:14:15 chofchof Exp $ - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, - the dvipdfmx project team <dvipdfmx@project.ktug.or.kr> - - Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu> - - This program 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. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -*/ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -/* - * PNG SUPPORT - * - * All bitdepth less than 16 is supported. - * Supported color types are: PALETTE, RGB, GRAY, RGB_ALPHA, GRAY_ALPHA. - * Supported ancillary chunks: tRNS, cHRM + gAMA, (sRGB), (iCCP) - * - * gAMA support is available only when cHRM exists. cHRM support is not - * tested well. CalRGB/CalGray colorspace is used for PNG images that - * have cHRM chunk (but not sRGB). - * - * LIMITATIONS - * - * Recent version of PDF (>= 1.5) support 16 bpc, but 16 bit bitdepth PNG - * images are automatically converted to 8 bit bitpedth image. - * - * TODO - * - * sBIT ? iTXT, tEXT and tIME as MetaData ?, pHYS (see below) - * 16 bpc support for PDF-1.5. JBIG compression for monochrome image. - * Predictor for deflate ? - */ - -#include "system.h" -#include "error.h" -#include "mem.h" - -#include "dvipdfmx.h" - -#include "pdfcolor.h" -#include "pdfobj.h" - -#define PNG_DEBUG_STR "PNG" -#define PNG_DEBUG 3 - -#ifdef HAVE_LIBPNG - -/* - * Write, MNG, Progressive not required. - */ -#define PNG_NO_WRITE_SUPPORTED -#define PNG_NO_MNG_FEATURES -#define PNG_NO_PROGRESSIVE_READ -#if 0 -/* 16_TO_8 required. */ -#define PNG_NO_READ_TRANSFORMS -#endif - -#include <png.h> -#include "pngimage.h" - -#include "pdfximage.h" - -#define PDF_TRANS_TYPE_NONE 0 -#define PDF_TRANS_TYPE_BINARY 1 -#define PDF_TRANS_TYPE_ALPHA 2 - -/* ColorSpace */ -static pdf_obj *create_cspace_Indexed (png_structp png_ptr, png_infop info_ptr); - -/* CIE-Based: CalRGB/CalGray - * - * We ignore gAMA if cHRM is not found. - */ -static pdf_obj *create_cspace_CalRGB (png_structp png_ptr, png_infop info_ptr); -static pdf_obj *create_cspace_CalGray (png_structp png_ptr, png_infop info_ptr); -static pdf_obj *make_param_Cal (png_byte color_type, - double G, - double xw, double yw, - double xr, double yr, - double xg, double yg, - double xb, double yb); - -/* sRGB: - * - * We (and PDF) do not have direct sRGB support. The sRGB color space can be - * precisely represented by ICC profile, but we use approximate CalRGB color - * space. - */ -static pdf_obj *create_cspace_sRGB (png_structp png_ptr, png_infop info_ptr); -static pdf_obj *get_rendering_intent (png_structp png_ptr, png_infop info_ptr); - -/* ICCBased: - * - * Not supported yet. - * Must check if ICC profile is valid and can be imported to PDF. - * There are few restrictions (should be applied to PNG too?) in ICC profile - * support in PDF. Some information should be obtained from profile. - */ -static pdf_obj *create_cspace_ICCBased (png_structp png_ptr, png_infop info_ptr); - -/* Transparency */ -static int check_transparency (png_structp png_ptr, png_infop info_ptr); -/* Color-Key Mask */ -static pdf_obj *create_ckey_mask (png_structp png_ptr, png_infop info_ptr); -/* Soft Mask: - * - * create_soft_mask() is for PNG_COLOR_TYPE_PALLETE. - * Images with alpha chunnel use strip_soft_mask(). - * An object representing mask itself is returned. - */ -static pdf_obj *create_soft_mask (png_structp png_ptr, png_infop info_ptr, - png_bytep image_data_ptr, - png_uint_32 width, png_uint_32 height); -static pdf_obj *strip_soft_mask (png_structp png_ptr, png_infop info_ptr, - png_bytep image_data_ptr, - png_uint_32p rowbytes_ptr, - png_uint_32 width, png_uint_32 height); - -/* Read image body */ -static void read_image_data (png_structp png_ptr, png_infop info_ptr, - png_bytep dest_ptr, - png_uint_32 height, png_uint_32 rowbytes); - -int -check_for_png (FILE *png_file) -{ - unsigned char sigbytes[4]; - - rewind (png_file); - if (fread (sigbytes, 1, sizeof(sigbytes), png_file) != - sizeof(sigbytes) || - (png_sig_cmp (sigbytes, 0, sizeof(sigbytes)))) - return 0; - else - return 1; -} - -int -png_include_image (pdf_ximage *ximage, FILE *png_file) -{ - pdf_obj *stream; - pdf_obj *stream_dict; - pdf_obj *colorspace, *mask, *intent; - png_bytep stream_data_ptr; - int trans_type; - ximage_info info; - /* Libpng stuff */ - png_structp png_ptr; - png_infop png_info_ptr; - png_byte bpc, color_type; - png_uint_32 width, height, rowbytes, xppm, yppm; - - pdf_ximage_init_image_info(&info); - - stream = NULL; - stream_dict = NULL; - colorspace = mask = intent = NULL; - - rewind (png_file); - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL || - (png_info_ptr = png_create_info_struct (png_ptr)) == NULL) { - WARN("%s: Creating Libpng read/info struct failed.", PNG_DEBUG_STR); - if (png_ptr) - png_destroy_read_struct(&png_ptr, NULL, NULL); - return -1; - } - - /* Inititializing file IO. */ - png_init_io (png_ptr, png_file); - - /* Read PNG info-header and get some info. */ - png_read_info(png_ptr, png_info_ptr); - color_type = png_get_color_type (png_ptr, png_info_ptr); - width = png_get_image_width (png_ptr, png_info_ptr); - height = png_get_image_height(png_ptr, png_info_ptr); - bpc = png_get_bit_depth (png_ptr, png_info_ptr); - xppm = png_get_x_pixels_per_meter(png_ptr, png_info_ptr); - yppm = png_get_y_pixels_per_meter(png_ptr, png_info_ptr); - - /* We do not need 16-bpc color. Ask libpng to convert down to 8-bpc. */ - if (bpc > 8) { - png_set_strip_16(png_ptr); - bpc = 8; - } - - trans_type = check_transparency(png_ptr, png_info_ptr); - /* check_transparency() does not do updata_info() */ - png_read_update_info(png_ptr, png_info_ptr); - rowbytes = png_get_rowbytes(png_ptr, png_info_ptr); - - /* Values listed below will not be modified in the remaining process. */ - info.width = width; - info.height = height; - info.bits_per_component = bpc; - - if (compat_mode) - info.xdensity = info.ydensity = 72.0 / 100.0; - else { - if (xppm > 0) - info.xdensity = 72.0 / 0.0254 / xppm; - if (yppm > 0) - info.ydensity = 72.0 / 0.0254 / yppm; - } - - stream = pdf_new_stream (STREAM_COMPRESS); - stream_dict = pdf_stream_dict(stream); - - stream_data_ptr = (png_bytep) NEW(rowbytes*height, png_byte); - read_image_data(png_ptr, png_info_ptr, stream_data_ptr, height, rowbytes); - - /* Non-NULL intent means there is valid sRGB chunk. */ - intent = get_rendering_intent(png_ptr, png_info_ptr); - if (intent) - pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent); - - switch (color_type) { - case PNG_COLOR_TYPE_PALETTE: - - colorspace = create_cspace_Indexed(png_ptr, png_info_ptr); - - switch (trans_type) { - case PDF_TRANS_TYPE_BINARY: - /* Color-key masking */ - mask = create_ckey_mask(png_ptr, png_info_ptr); - break; - case PDF_TRANS_TYPE_ALPHA: - /* Soft mask */ - mask = create_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, width, height); - break; - default: - /* Nothing to be done here. - * No tRNS chunk or image already composited with background color. - */ - break; - } - break; - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - - if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP)) - colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr); - else if (intent) { - colorspace = create_cspace_sRGB(png_ptr, png_info_ptr); - } else { - colorspace = create_cspace_CalRGB(png_ptr, png_info_ptr); - } - if (!colorspace) - colorspace = pdf_new_name("DeviceRGB"); - - switch (trans_type) { - case PDF_TRANS_TYPE_BINARY: - if (color_type != PNG_COLOR_TYPE_RGB) - ERROR("Unexpected error in png_include_image()."); - mask = create_ckey_mask(png_ptr, png_info_ptr); - break; - /* rowbytes changes 4 to 3 at here */ - case PDF_TRANS_TYPE_ALPHA: - if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) - ERROR("Unexpected error in png_include_image()."); - mask = strip_soft_mask(png_ptr, png_info_ptr, - stream_data_ptr, &rowbytes, width, height); - break; - default: - mask = NULL; - } - info.num_components = 3; - break; - - case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_GRAY_ALPHA: - - if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP)) - colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr); - else if (intent) { - colorspace = create_cspace_sRGB(png_ptr, png_info_ptr); - } else { - colorspace = create_cspace_CalGray(png_ptr, png_info_ptr); - } - if (!colorspace) - colorspace = pdf_new_name("DeviceGray"); - - switch (trans_type) { - case PDF_TRANS_TYPE_BINARY: - if (color_type != PNG_COLOR_TYPE_GRAY) - ERROR("Unexpected error in png_include_image()."); - mask = create_ckey_mask(png_ptr, png_info_ptr); - break; - case PDF_TRANS_TYPE_ALPHA: - if (color_type != PNG_COLOR_TYPE_GRAY_ALPHA) - ERROR("Unexpected error in png_include_image()."); - mask = strip_soft_mask(png_ptr, png_info_ptr, - stream_data_ptr, &rowbytes, width, height); - break; - default: - mask = NULL; - } - info.num_components = 1; - break; - - default: - WARN("%s: Unknown PNG colortype %d.", PNG_DEBUG_STR, color_type); - } - pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace); - - pdf_add_stream(stream, stream_data_ptr, rowbytes*height); - RELEASE(stream_data_ptr); - - if (mask) { - if (trans_type == PDF_TRANS_TYPE_BINARY) - pdf_add_dict(stream_dict, pdf_new_name("Mask"), mask); - else if (trans_type == PDF_TRANS_TYPE_ALPHA) { - pdf_add_dict(stream_dict, pdf_new_name("SMask"), pdf_ref_obj(mask)); - pdf_release_obj(mask); - } else { - WARN("%s: You found a bug in pngimage.c.", PNG_DEBUG_STR); - pdf_release_obj(mask); - } - } - - png_read_end(png_ptr, NULL); - - /* Cleanup */ - if (png_info_ptr) - png_destroy_info_struct(png_ptr, &png_info_ptr); - if (png_ptr) - png_destroy_read_struct(&png_ptr, NULL, NULL); - - pdf_ximage_set_image(ximage, &info, stream); - - return 0; -} - -/* - * The returned value trans_type is the type of transparency to be used for - * this image. Possible values are: - * - * PDF_TRANS_TYPE_NONE No Masking will be used/required. - * PDF_TRANS_TYPE_BINARY Pixels are either fully opaque/fully transparent. - * PDF_TRANS_TYPE_ALPHA Uses alpha channel, requies SMask.(PDF-1.4) - * - * check_transparency() must check the current setting of output PDF version - * and must choose appropriate trans_type value according to PDF version of - * current output PDF document. - * - * If the PDF version is less than 1.3, no transparency is supported for this - * version of PDF, hence PDF_TRANS_TYPE_NONE must be returned. And when the PDF - * version is equal to 1.3, possible retrun values are PDF_TRANS_TYPE_BINARY or - * PDF_TRANS_TYPE_NONE. The latter case arises when PNG file uses alpha channel - * explicitly (color type PNG_COLOR_TYPE_XXX_ALPHA), or the tRNS chunk for the - * PNG_COLOR_TYPE_PALETTE image contains intermediate values of opacity. - * - * Finally, in the case of PDF version 1.4, all kind of translucent pixels can - * be represented with Soft-Mask. - */ - -static int -check_transparency (png_structp png_ptr, png_infop info_ptr) -{ - int trans_type; - unsigned pdf_version; - png_byte color_type; - png_color_16p trans_values; - png_bytep trans; - int num_trans; - - pdf_version = pdf_get_version(); - color_type = png_get_color_type(png_ptr, info_ptr); - - /* - * First we set trans_type to appropriate value for PNG image. - */ - if (color_type == PNG_COLOR_TYPE_RGB_ALPHA || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - trans_type = PDF_TRANS_TYPE_ALPHA; - } else if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) && - png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values)) { - /* Have valid tRNS chunk. */ - switch (color_type) { - case PNG_COLOR_TYPE_PALETTE: - /* Use color-key mask if possible. */ - trans_type = PDF_TRANS_TYPE_BINARY; - while (num_trans-- > 0) { - if (trans[num_trans] != 0x00 && trans[num_trans] != 0xff) { - /* This seems not binary transparency */ - trans_type = PDF_TRANS_TYPE_ALPHA; - break; - } - } - break; - case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_RGB: - /* RGB or GRAY, single color specified by trans_values is transparent. */ - trans_type = PDF_TRANS_TYPE_BINARY; - break; - default: - /* Else tRNS silently ignored. */ - trans_type = PDF_TRANS_TYPE_NONE; - } - } else { /* no transparency */ - trans_type = PDF_TRANS_TYPE_NONE; - } - - /* - * Now we check PDF version. - * We can convert alpha cahnnels to explicit mask via user supplied alpha- - * threshold value. But I will not do that. - */ - if (( pdf_version < 3 && trans_type != PDF_TRANS_TYPE_NONE ) || - ( pdf_version < 4 && trans_type == PDF_TRANS_TYPE_ALPHA )) { - /* - * No transparency supported but PNG uses transparency, or Soft-Mask - * required but no support for it is available in this version of PDF. - * We must do pre-composition of image with the background image here. But, - * we cannot do that in general since dvipdfmx is not a rasterizer. What we - * can do here is to composite image with a rectangle filled with the - * background color. However, images are stored as an Image XObject which - * can be referenced anywhere in the PDF document content. Hence, we cannot - * know the correct background color at this time. So we will choose white - * as background color, which is most probable color in our cases. - * We ignore bKGD chunk. - */ - png_color_16 bg; - bg.red = 255; bg.green = 255; bg.blue = 255; bg.gray = 255; bg.index = 0; - png_set_background(png_ptr, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - WARN("%s: Transparency will be ignored. (no support in PDF ver. < 1.3)", PNG_DEBUG_STR); - if (pdf_version < 3) - WARN("%s: Please use -V 3 option to enable binary transparency support.", PNG_DEBUG_STR); - if (pdf_version < 4) - WARN("%s: Please use -V 4 option to enable full alpha channel support.", PNG_DEBUG_STR); - trans_type = PDF_TRANS_TYPE_NONE; - } - - return trans_type; -} - -/* - * sRGB: - * - * If sRGB chunk is present, cHRM and gAMA chunk must be ignored. - * - */ -static pdf_obj * -get_rendering_intent (png_structp png_ptr, png_infop info_ptr) -{ - pdf_obj *intent; - int srgb_intent; - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB) && - png_get_sRGB (png_ptr, info_ptr, &srgb_intent)) { - switch (srgb_intent) { - case PNG_sRGB_INTENT_SATURATION: - intent = pdf_new_name("Saturation"); - break; - case PNG_sRGB_INTENT_PERCEPTUAL: - intent = pdf_new_name("Perceptual"); - break; - case PNG_sRGB_INTENT_ABSOLUTE: - intent = pdf_new_name("AbsoluteColorimetric"); - break; - case PNG_sRGB_INTENT_RELATIVE: - intent = pdf_new_name("RelativeColorimetric"); - break; - default: - WARN("%s: Invalid value in PNG sRGB chunk: %d", PNG_DEBUG_STR, srgb_intent); - intent = NULL; - } - } else - intent = NULL; - - return intent; -} - -/* Approximated sRGB */ -static pdf_obj * -create_cspace_sRGB (png_structp png_ptr, png_infop info_ptr) -{ - pdf_obj *colorspace; - pdf_obj *cal_param; - png_byte color_type; - - color_type = png_get_color_type(png_ptr, info_ptr); - - /* Parameters taken from PNG spec. section 4.2.2.3. */ - cal_param = make_param_Cal(color_type, - 2.2, - 0.3127, 0.329, - 0.64, 0.33, 0.3, 0.6, 0.15, 0.06); - if (!cal_param) - return NULL; - - colorspace = pdf_new_array(); - - switch (color_type) { - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - case PNG_COLOR_TYPE_PALETTE: - pdf_add_array(colorspace, pdf_new_name("CalRGB")); - break; - case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_GRAY_ALPHA: - pdf_add_array(colorspace, pdf_new_name("CalGray")); - break; - } - pdf_add_array(colorspace, cal_param); - - return colorspace; -} - -static pdf_obj * -create_cspace_ICCBased (png_structp png_ptr, png_infop info_ptr) -{ - pdf_obj *colorspace; - int csp_id, colortype; - png_byte color_type; - png_charp name; - int compression_type; /* Manual page for libpng does not - * clarify whether profile data is inflated by libpng. - */ -#if PNG_LIBPNG_VER_MINOR < 5 - png_charp profile; -#else - png_bytep profile; -#endif - png_uint_32 proflen; - - if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP) || - !png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile, &proflen)) - return NULL; - - color_type = png_get_color_type(png_ptr, info_ptr); - - if (color_type & PNG_COLOR_MASK_COLOR) { - colortype = PDF_COLORSPACE_TYPE_RGB; -#if 0 - alternate = create_cspace_CalRGB(png_ptr, info_ptr); -#endif - } else { - colortype = PDF_COLORSPACE_TYPE_GRAY; -#if 0 - alternate = create_cspace_CalGray(png_ptr, info_ptr); -#endif - } - -#if 0 - if (alternate) - pdf_add_dict(dict, pdf_new_name("Alternate"), alternate); -#endif - - if (iccp_check_colorspace(colortype, profile, proflen) < 0) - colorspace = NULL; - else { - csp_id = iccp_load_profile(name, profile, proflen); - if (csp_id < 0) { - colorspace = NULL; - } else { - colorspace = pdf_get_colorspace_reference(csp_id); - } - } - - /* Rendering intent ... */ - - return colorspace; -} - -/* - * gAMA, cHRM: - * - * If cHRM is present, we use CIE-Based color space. gAMA is also used here - * if available. - */ - -#define INVALID_CHRM_VALUE(xw,yw,xr,yr,xg,yg,xb,yb) (\ - (xw) <= 0.0 || (yw) < 1.0e-10 || \ - (xr) < 0.0 || (yr) < 0.0 || (xg) < 0.0 || (yg) < 0.0 || \ - (xb) < 0.0 || (yb) < 0.0) - -static pdf_obj * -create_cspace_CalRGB (png_structp png_ptr, png_infop info_ptr) -{ - pdf_obj *colorspace; - pdf_obj *cal_param; - double xw, yw, xr, yr, xg, yg, xb, yb; - double G; - - if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_cHRM) || - !png_get_cHRM(png_ptr, info_ptr, &xw, &yw, &xr, &yr, &xg, &yg, &xb, &yb)) - return NULL; - - if (xw <= 0.0 || yw < 1.0e-10 || - xr < 0.0 || yr < 0.0 || xg < 0.0 || yg < 0.0 || xb < 0.0 || yb < 0.0) { - WARN("%s: Invalid cHRM chunk parameters found.", PNG_DEBUG_STR); - return NULL; - } - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA) && - png_get_gAMA (png_ptr, info_ptr, &G)) { - if (G < 1.0e-2) { - WARN("%s: Unusual Gamma value: %g", PNG_DEBUG_STR, G); - return NULL; - } - G = 1.0 / G; /* Gamma is inverted. */ - } else { - G = 1.0; - } - - cal_param = make_param_Cal(PNG_COLOR_TYPE_RGB, G, xw, yw, xr, yr, xg, yg, xb, yb); - - if (!cal_param) - return NULL; - - colorspace = pdf_new_array(); - pdf_add_array(colorspace, pdf_new_name("CalRGB")); - pdf_add_array(colorspace, cal_param); - - return colorspace; -} - -static pdf_obj * -create_cspace_CalGray (png_structp png_ptr, png_infop info_ptr) -{ - pdf_obj *colorspace; - pdf_obj *cal_param; - double xw, yw, xr, yr, xg, yg, xb, yb; - double G; - - if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_cHRM) || - !png_get_cHRM(png_ptr, info_ptr, &xw, &yw, &xr, &yr, &xg, &yg, &xb, &yb)) - return NULL; - - if (xw <= 0.0 || yw < 1.0e-10 || - xr < 0.0 || yr < 0.0 || xg < 0.0 || yg < 0.0 || xb < 0.0 || yb < 0.0) { - WARN("%s: Invalid cHRM chunk parameters found.", PNG_DEBUG_STR); - return NULL; - } - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA) && - png_get_gAMA (png_ptr, info_ptr, &G)) { - if (G < 1.0e-2) { - WARN("%s: Unusual Gamma value: %g", PNG_DEBUG_STR, G); - return NULL; - } - G = 1.0 / G; /* Gamma is inverted. */ - } else { - G = 1.0; - } - - cal_param = make_param_Cal(PNG_COLOR_TYPE_GRAY, G, xw, yw, xr, yr, xg, yg, xb, yb); - - if (!cal_param) - return NULL; - - colorspace = pdf_new_array(); - pdf_add_array(colorspace, pdf_new_name("CalGray")); - pdf_add_array(colorspace, cal_param); - - return colorspace; -} - -static pdf_obj * -make_param_Cal (png_byte color_type, - double G, /* Gamma */ - double xw, double yw, - double xr, double yr, double xg, double yg, double xb, double yb) -{ - pdf_obj *cal_param; - pdf_obj *white_point, *matrix, *dev_gamma; - double Xw, Yw, Zw; /* Yw = 1.0 */ - double Xr, Xg, Xb, Yr, Yb, Yg, Zr, Zg, Zb; - -#ifndef ABS -#define ABS(x) ((x) < 0 ? -(x) : (x)) -#endif - /* - * TODO: Check validity - * - * Conversion found in - * - * com.sixlegs.image.png - Java package to read and display PNG images - * Copyright (C) 1998, 1999, 2001 Chris Nokleberg - * - * http://www.sixlegs.com/software/png/ - * - */ - { - double zw, zr, zg, zb; - double fr, fg, fb; - double det; - - /* WhitePoint */ - zw = 1 - (xw + yw); - zr = 1 - (xr + yr); zg = 1 - (xg + yg); zb = 1 - (xb + yb); - Xw = xw / yw; Yw = 1.0; Zw = zw / yw; - - /* Matrix */ - det = xr * (yg * zb - zg * yb) - xg * (yr * zb - zr * yb) + xb * (yr * zg - zr * yg); - if (ABS(det) < 1.0e-10) { - WARN("Non invertible matrix: Maybe invalid value(s) specified in cHRM chunk."); - return NULL; - } - fr = (Xw * (yg * zb - zg * yb) - xg * (zb - Zw * yb) + xb * (zg - Zw * yg)) / det; - fg = (xr * (zb - Zw * yb) - Xw * (yr * zb - zr * yb) + xb * (yr * Zw - zr)) / det; - fb = (xr * (yg * Zw - zg) - xg * (yr * Zw - zr) + Xw * (yr * zg - zr * yg)) / det; - Xr = fr * xr; Yr = fr * yr; Zr = fr * zr; - Xg = fg * xg; Yg = fg * yg; Zg = fg * zg; - Xb = fb * xb; Yb = fb * yb; Zb = fb * zb; - } - - if (G < 1.0e-2) { - WARN("Unusual Gamma specified: %g", G); - return NULL; - } - - cal_param = pdf_new_dict(); - - /* White point is always required. */ - white_point = pdf_new_array(); - pdf_add_array(white_point, pdf_new_number(ROUND(Xw, 0.00001))); - pdf_add_array(white_point, pdf_new_number(ROUND(Yw, 0.00001))); - pdf_add_array(white_point, pdf_new_number(ROUND(Zw, 0.00001))); - pdf_add_dict(cal_param, pdf_new_name("WhitePoint"), white_point); - - /* Matrix - default: Identity */ - if (color_type & PNG_COLOR_MASK_COLOR) { - if (G != 1.0) { - dev_gamma = pdf_new_array(); - pdf_add_array(dev_gamma, pdf_new_number(ROUND(G, 0.00001))); - pdf_add_array(dev_gamma, pdf_new_number(ROUND(G, 0.00001))); - pdf_add_array(dev_gamma, pdf_new_number(ROUND(G, 0.00001))); - pdf_add_dict(cal_param, pdf_new_name("Gamma"), dev_gamma); - } - - matrix = pdf_new_array(); - pdf_add_array(matrix, pdf_new_number(ROUND(Xr, 0.00001))); - pdf_add_array(matrix, pdf_new_number(ROUND(Yr, 0.00001))); - pdf_add_array(matrix, pdf_new_number(ROUND(Zr, 0.00001))); - pdf_add_array(matrix, pdf_new_number(ROUND(Xg, 0.00001))); - pdf_add_array(matrix, pdf_new_number(ROUND(Yg, 0.00001))); - pdf_add_array(matrix, pdf_new_number(ROUND(Zg, 0.00001))); - pdf_add_array(matrix, pdf_new_number(ROUND(Xb, 0.00001))); - pdf_add_array(matrix, pdf_new_number(ROUND(Yb, 0.00001))); - pdf_add_array(matrix, pdf_new_number(ROUND(Zb, 0.00001))); - pdf_add_dict (cal_param, pdf_new_name("Matrix"), matrix); - } else { /* Gray */ - if (G != 1.0) - pdf_add_dict(cal_param, - pdf_new_name("Gamma"), - pdf_new_number(ROUND(G, 0.00001))); - } - - return cal_param; -} - -/* - * Set up Indexed ColorSpace for color-type PALETTE: - * - * PNG allows only RGB color for base color space. If gAMA and/or cHRM - * chunk is available, we can use CalRGB color space instead of DeviceRGB - * for base color space. - * - */ -static pdf_obj * -create_cspace_Indexed (png_structp png_ptr, png_infop info_ptr) -{ - pdf_obj *colorspace; - pdf_obj *base, *lookup; - png_byte *data_ptr; - png_colorp plte; - int num_plte, i; - - if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE) || - !png_get_PLTE(png_ptr, info_ptr, &plte, &num_plte)) { - WARN("%s: PNG does not have valid PLTE chunk.", PNG_DEBUG_STR); - return NULL; - } - - /* Order is important. */ - colorspace = pdf_new_array (); - pdf_add_array(colorspace, pdf_new_name("Indexed")); - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) - base = create_cspace_ICCBased(png_ptr, info_ptr); - else { - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) - base = create_cspace_sRGB(png_ptr, info_ptr); - else - base = create_cspace_CalRGB(png_ptr, info_ptr); - } - - if (!base) - base = pdf_new_name("DeviceRGB"); - - pdf_add_array(colorspace, base); - pdf_add_array(colorspace, pdf_new_number(num_plte-1)); - data_ptr = NEW(num_plte*3, png_byte); - for (i = 0; i < num_plte; i++) { - data_ptr[3*i] = plte[i].red; - data_ptr[3*i+1] = plte[i].green; - data_ptr[3*i+2] = plte[i].blue; - } - lookup = pdf_new_string(data_ptr, num_plte*3); - RELEASE(data_ptr); - pdf_add_array(colorspace, lookup); - - return colorspace; -} - -/* - * pHYs: no support - * - * pngimage.c is not responsible for adjusting image size. - * Higher layer must do something for this. - */ - -/* - * Colorkey Mask: array - * - * [component_0_min component_0_max ... component_n_min component_n_max] - * - */ - -static pdf_obj * -create_ckey_mask (png_structp png_ptr, png_infop info_ptr) -{ - pdf_obj *colorkeys; - png_byte color_type; - png_bytep trans; - int num_trans, i; - png_color_16p colors; - - if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) || - !png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &colors)) { - WARN("%s: PNG does not have valid tRNS chunk!", PNG_DEBUG_STR); - return NULL; - } - - colorkeys = pdf_new_array(); - color_type = png_get_color_type(png_ptr, info_ptr); - - switch (color_type) { - case PNG_COLOR_TYPE_PALETTE: - for (i = 0; i < num_trans; i++) { - if (trans[i] == 0x00) { - pdf_add_array(colorkeys, pdf_new_number(i)); - pdf_add_array(colorkeys, pdf_new_number(i)); - } else if (trans[i] != 0xff) { - WARN("%s: You found a bug in pngimage.c.", PNG_DEBUG_STR); - } - } - break; - case PNG_COLOR_TYPE_RGB: - pdf_add_array(colorkeys, pdf_new_number(colors->red)); - pdf_add_array(colorkeys, pdf_new_number(colors->red)); - pdf_add_array(colorkeys, pdf_new_number(colors->green)); - pdf_add_array(colorkeys, pdf_new_number(colors->green)); - pdf_add_array(colorkeys, pdf_new_number(colors->blue)); - pdf_add_array(colorkeys, pdf_new_number(colors->blue)); - break; - case PNG_COLOR_TYPE_GRAY: - pdf_add_array(colorkeys, pdf_new_number(colors->gray)); - pdf_add_array(colorkeys, pdf_new_number(colors->gray)); - break; - default: - WARN("%s: You found a bug in pngimage.c.", PNG_DEBUG_STR); - pdf_release_obj(colorkeys); - colorkeys = NULL; - } - - return colorkeys; -} - -/* - * Soft-Mask: stream - * - * << - * /Type /XObject - * /Subtype /Image - * /Width -int- - * /Height -int- - * /BitsPerComponent bpc - * >> - * stream .... endstream - * - * ColorSpace, Mask, SMask must be absent. ImageMask must be false or absent. - */ - -static pdf_obj * -create_soft_mask (png_structp png_ptr, png_infop info_ptr, - png_bytep image_data_ptr, png_uint_32 width, png_uint_32 height) -{ - pdf_obj *smask, *dict; - png_bytep smask_data_ptr; - png_bytep trans; - int num_trans; - png_uint_32 i; - - if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) || - !png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL)) { - WARN("%s: PNG does not have valid tRNS chunk but tRNS is requested.", PNG_DEBUG_STR); - return NULL; - } - - smask = pdf_new_stream(STREAM_COMPRESS); - dict = pdf_stream_dict(smask); - smask_data_ptr = (png_bytep) NEW(width*height, png_byte); - pdf_add_dict(dict, pdf_new_name("Type"), pdf_new_name("XObjcect")); - pdf_add_dict(dict, pdf_new_name("Subtype"), pdf_new_name("Image")); - pdf_add_dict(dict, pdf_new_name("Width"), pdf_new_number(width)); - pdf_add_dict(dict, pdf_new_name("Height"), pdf_new_number(height)); - pdf_add_dict(dict, pdf_new_name("ColorSpace"), pdf_new_name("DeviceGray")); - pdf_add_dict(dict, pdf_new_name("BitsPerComponent"), pdf_new_number(8)); - for (i = 0; i < width*height; i++) { - png_byte idx = image_data_ptr[i]; - smask_data_ptr[i] = (idx < num_trans) ? trans[idx] : 0xff; - } - pdf_add_stream(smask, (char *)smask_data_ptr, width*height); - RELEASE(smask_data_ptr); - - return smask; -} - -/* bitdepth is always 8 (16 is not supported) */ -static pdf_obj * -strip_soft_mask (png_structp png_ptr, png_infop info_ptr, - /* next two values will be modified. */ - png_bytep image_data_ptr, png_uint_32p rowbytes_ptr, - png_uint_32 width, png_uint_32 height) -{ - pdf_obj *smask, *dict; - png_byte color_type; - png_bytep smask_data_ptr; - png_uint_32 i; - - color_type = png_get_color_type(png_ptr, info_ptr); - - if (color_type & PNG_COLOR_MASK_COLOR) { - if (*rowbytes_ptr != 4*width*sizeof(png_byte)) { /* Something wrong */ - WARN("%s: Inconsistent rowbytes value.", PNG_DEBUG_STR); - return NULL; - } - } else { - if (*rowbytes_ptr != 2*width*sizeof(png_byte)) { /* Something wrong */ - WARN("%s: Inconsistent rowbytes value.", PNG_DEBUG_STR); - return NULL; - } - } - - smask = pdf_new_stream(STREAM_COMPRESS); - dict = pdf_stream_dict(smask); - pdf_add_dict(dict, pdf_new_name("Type"), pdf_new_name("XObjcect")); - pdf_add_dict(dict, pdf_new_name("Subtype"), pdf_new_name("Image")); - pdf_add_dict(dict, pdf_new_name("Width"), pdf_new_number(width)); - pdf_add_dict(dict, pdf_new_name("Height"), pdf_new_number(height)); - pdf_add_dict(dict, pdf_new_name("ColorSpace"), pdf_new_name("DeviceGray")); - pdf_add_dict(dict, pdf_new_name("BitsPerComponent"), pdf_new_number(8)); - - smask_data_ptr = (png_bytep) NEW(width*height, png_byte); - - switch (color_type) { - case PNG_COLOR_TYPE_RGB_ALPHA: - for (i = 0; i < width*height; i++) { - memmove(image_data_ptr+(3*i), image_data_ptr+(4*i), 3); - smask_data_ptr[i] = image_data_ptr[4*i+3]; - } - *rowbytes_ptr = 3*width*sizeof(png_byte); - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - for (i = 0; i < width*height; i++) { - image_data_ptr[i] = image_data_ptr[2*i]; - smask_data_ptr[i] = image_data_ptr[2*i+1]; - } - *rowbytes_ptr = width*sizeof(png_byte); - break; - default: - WARN("You found a bug in pngimage.c!"); - pdf_release_obj(smask); - RELEASE(smask_data_ptr); - return NULL; - } - - pdf_add_stream(smask, smask_data_ptr, width*height); - RELEASE(smask_data_ptr); - - return smask; -} - -static void -read_image_data (png_structp png_ptr, png_infop info_ptr, /* info_ptr unused */ - png_bytep dest_ptr, png_uint_32 height, png_uint_32 rowbytes) -{ - png_bytepp rows_p; - png_uint_32 i; - - rows_p = (png_bytepp) NEW (height, png_bytep); - for (i=0; i< height; i++) - rows_p[i] = dest_ptr + (rowbytes * i); - png_read_image(png_ptr, rows_p); - RELEASE(rows_p); -} - -int -png_get_bbox (FILE *png_file, long *width, long *height, - double *xdensity, double *ydensity) -{ - png_structp png_ptr; - png_infop png_info_ptr; - png_uint_32 xppm, yppm; - - rewind (png_file); - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL || - (png_info_ptr = png_create_info_struct (png_ptr)) == NULL) { - WARN("%s: Creating Libpng read/info struct failed.", PNG_DEBUG_STR); - if (png_ptr) - png_destroy_read_struct(&png_ptr, NULL, NULL); - return -1; - } - - /* Inititializing file IO. */ - png_init_io (png_ptr, png_file); - - /* Read PNG info-header and get some info. */ - png_read_info(png_ptr, png_info_ptr); - *width = png_get_image_width (png_ptr, png_info_ptr); - *height = png_get_image_height(png_ptr, png_info_ptr); - xppm = png_get_x_pixels_per_meter(png_ptr, png_info_ptr); - yppm = png_get_y_pixels_per_meter(png_ptr, png_info_ptr); - - /* Cleanup */ - if (png_info_ptr) - png_destroy_info_struct(png_ptr, &png_info_ptr); - if (png_ptr) - png_destroy_read_struct(&png_ptr, NULL, NULL); - - if (compat_mode) - *xdensity = *ydensity = 72.0 / 100.0; - else { - *xdensity = xppm ? 72.0 / 0.0254 / xppm : 1.0; - *ydensity = yppm ? 72.0 / 0.0254 / yppm : 1.0; - } - - return 0; -} - -#endif /* HAVE_LIBPNG */ |