Files
harbour-core/harbour/external/libhpdf/hpdfimap.c
Viktor Szakats 2cc4903d82 2009-09-10 09:52 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* external/libhpdf/Makefile
    + Enabled for all dos platforms (dos/watcom currently and
      probably all dos builds done on MS-DOS hosts).

  + external/libhpdf/ori_dst
  + external/libhpdf/ori_src
  + external/libhpdf/cnv_hb2o.bat
  + external/libhpdf/cnv_o2hb.bat
  - external/libhpdf/hpdf_annotation.c
  - external/libhpdf/hpdf_annotation.h
  - external/libhpdf/hpdf_array.c
  - external/libhpdf/hpdf_binary.c
  - external/libhpdf/hpdf_boolean.c
  - external/libhpdf/hpdf_catalog.c
  - external/libhpdf/hpdf_catalog.h
  - external/libhpdf/hpdf_conf.h
  - external/libhpdf/hpdf_config.h
  - external/libhpdf/hpdf_consts.h
  - external/libhpdf/hpdf_destination.c
  - external/libhpdf/hpdf_destination.h
  - external/libhpdf/hpdf_dict.c
  - external/libhpdf/hpdf_doc.c
  - external/libhpdf/hpdf_doc.h
  - external/libhpdf/hpdf_doc_png.c
  - external/libhpdf/hpdf_encoder.c
  - external/libhpdf/hpdf_encoder.h
  - external/libhpdf/hpdf_encoder_cns.c
  - external/libhpdf/hpdf_encoder_cnt.c
  - external/libhpdf/hpdf_encoder_jp.c
  - external/libhpdf/hpdf_encoder_kr.c
  - external/libhpdf/hpdf_encrypt.c
  - external/libhpdf/hpdf_encrypt.h
  - external/libhpdf/hpdf_encryptdict.c
  - external/libhpdf/hpdf_encryptdict.h
  - external/libhpdf/hpdf_error.c
  - external/libhpdf/hpdf_error.h
  - external/libhpdf/hpdf_ext_gstate.c
  - external/libhpdf/hpdf_ext_gstate.h
  - external/libhpdf/hpdf_font.c
  - external/libhpdf/hpdf_font.h
  - external/libhpdf/hpdf_font_cid.c
  - external/libhpdf/hpdf_font_tt.c
  - external/libhpdf/hpdf_font_type1.c
  - external/libhpdf/hpdf_fontdef.c
  - external/libhpdf/hpdf_fontdef.h
  - external/libhpdf/hpdf_fontdef_base14.c
  - external/libhpdf/hpdf_fontdef_cid.c
  - external/libhpdf/hpdf_fontdef_cns.c
  - external/libhpdf/hpdf_fontdef_cnt.c
  - external/libhpdf/hpdf_fontdef_jp.c
  - external/libhpdf/hpdf_fontdef_kr.c
  - external/libhpdf/hpdf_fontdef_tt.c
  - external/libhpdf/hpdf_fontdef_type1.c
  - external/libhpdf/hpdf_gstate.c
  - external/libhpdf/hpdf_gstate.h
  - external/libhpdf/hpdf_image.c
  - external/libhpdf/hpdf_image.h
  - external/libhpdf/hpdf_image_png.c
  - external/libhpdf/hpdf_info.c
  - external/libhpdf/hpdf_info.h
  - external/libhpdf/hpdf_list.c
  - external/libhpdf/hpdf_list.h
  - external/libhpdf/hpdf_mmgr.c
  - external/libhpdf/hpdf_mmgr.h
  - external/libhpdf/hpdf_name.c
  - external/libhpdf/hpdf_null.c
  - external/libhpdf/hpdf_number.c
  - external/libhpdf/hpdf_objects.c
  - external/libhpdf/hpdf_objects.h
  - external/libhpdf/hpdf_outline.c
  - external/libhpdf/hpdf_outline.h
  - external/libhpdf/hpdf_page_label.c
  - external/libhpdf/hpdf_page_label.h
  - external/libhpdf/hpdf_page_operator.c
  - external/libhpdf/hpdf_pages.c
  - external/libhpdf/hpdf_pages.h
  - external/libhpdf/hpdf_real.c
  - external/libhpdf/hpdf_streams.c
  - external/libhpdf/hpdf_streams.h
  - external/libhpdf/hpdf_string.c
  - external/libhpdf/hpdf_types.h
  - external/libhpdf/hpdf_u3d.c
  - external/libhpdf/hpdf_u3d.h
  - external/libhpdf/hpdf_utils.c
  - external/libhpdf/hpdf_utils.h
  - external/libhpdf/hpdf_version.h
  - external/libhpdf/hpdf_xref.c
  + external/libhpdf/hpdfanno.c
  + external/libhpdf/hpdfanno.h
  + external/libhpdf/hpdfarra.c
  + external/libhpdf/hpdfbina.c
  + external/libhpdf/hpdfbool.c
  + external/libhpdf/hpdfcata.c
  + external/libhpdf/hpdfcata.h
  + external/libhpdf/hpdfcfg.h
  + external/libhpdf/hpdfconf.h
  + external/libhpdf/hpdfcons.h
  + external/libhpdf/hpdfdest.c
  + external/libhpdf/hpdfdest.h
  + external/libhpdf/hpdfdict.c
  + external/libhpdf/hpdfdoc.c
  + external/libhpdf/hpdfdoc.h
  + external/libhpdf/hpdfdocp.c
  + external/libhpdf/hpdfecy.c
  + external/libhpdf/hpdfecyd.c
  + external/libhpdf/hpdfencc.c
  + external/libhpdf/hpdfencj.c
  + external/libhpdf/hpdfenck.c
  + external/libhpdf/hpdfencn.c
  + external/libhpdf/hpdfenco.c
  + external/libhpdf/hpdfenco.h
  + external/libhpdf/hpdfencr.h
  + external/libhpdf/hpdfency.h
  + external/libhpdf/hpdferro.c
  + external/libhpdf/hpdferro.h
  + external/libhpdf/hpdfextg.c
  + external/libhpdf/hpdfextg.h
  + external/libhpdf/hpdffdf.c
  + external/libhpdf/hpdffdf1.c
  + external/libhpdf/hpdffdfb.c
  + external/libhpdf/hpdffdfc.c
  + external/libhpdf/hpdffdfi.c
  + external/libhpdf/hpdffdfj.c
  + external/libhpdf/hpdffdfk.c
  + external/libhpdf/hpdffdfn.c
  + external/libhpdf/hpdffdft.c
  + external/libhpdf/hpdffon1.c
  + external/libhpdf/hpdffonc.c
  + external/libhpdf/hpdffond.h
  + external/libhpdf/hpdffont.c
  + external/libhpdf/hpdffont.h
  + external/libhpdf/hpdffott.c
  + external/libhpdf/hpdfgsta.c
  + external/libhpdf/hpdfgsta.h
  + external/libhpdf/hpdfimag.c
  + external/libhpdf/hpdfimag.h
  + external/libhpdf/hpdfimap.c
  + external/libhpdf/hpdfinfo.c
  + external/libhpdf/hpdfinfo.h
  + external/libhpdf/hpdflist.c
  + external/libhpdf/hpdflist.h
  + external/libhpdf/hpdfmmgr.c
  + external/libhpdf/hpdfmmgr.h
  + external/libhpdf/hpdfname.c
  + external/libhpdf/hpdfnull.c
  + external/libhpdf/hpdfnumb.c
  + external/libhpdf/hpdfobje.c
  + external/libhpdf/hpdfobje.h
  + external/libhpdf/hpdfoutl.c
  + external/libhpdf/hpdfoutl.h
  + external/libhpdf/hpdfpage.c
  + external/libhpdf/hpdfpage.h
  + external/libhpdf/hpdfpago.c
  + external/libhpdf/hpdfpags.c
  + external/libhpdf/hpdfpags.h
  + external/libhpdf/hpdfreal.c
  + external/libhpdf/hpdfstre.c
  + external/libhpdf/hpdfstre.h
  + external/libhpdf/hpdfstri.c
  + external/libhpdf/hpdftype.h
  + external/libhpdf/hpdfu3d.c
  + external/libhpdf/hpdfu3d.h
  + external/libhpdf/hpdfutil.c
  + external/libhpdf/hpdfutil.h
  + external/libhpdf/hpdfvers.h
  + external/libhpdf/hpdfxref.c
  * external/libhpdf/hpdf.h
  * external/libhpdf/Makefile
    * Converted to short filenames. Added converted scripts.

  * source/hbpcre/cnv_hb2o.bat
  * source/hbpcre/cnv_o2hb.bat
    ! Fixed typo in prev.
    * Removed PCRE references from comment texts.
2009-09-10 08:02:45 +00:00

696 lines
19 KiB
C

/*
* << Haru Free PDF Library >> -- hpdf_image.c
*
* URL: http://libharu.org
*
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
* Copyright (c) 2007-2008 Antony Dovgal <tony@daylessday.org>
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
* It is provided "as is" without express or implied warranty.
*
*/
#include "hpdfconf.h"
#include "hpdfutil.h"
#include "hpdfimag.h"
#ifndef HPDF_NOPNGLIB
#include <png.h>
static void
PngErrorFunc (png_structp png_ptr,
const char *msg);
static void
PngReadFunc (png_structp png_ptr,
png_bytep data,
png_uint_32 length)
{
HPDF_UINT len = length;
HPDF_Stream stream = (HPDF_Stream)png_get_io_ptr (png_ptr);
HPDF_Stream_Read (stream, data, &len);
}
static HPDF_STATUS
LoadPngData (HPDF_Dict image,
HPDF_Xref xref,
HPDF_Stream png_data,
HPDF_BOOL delayed_loading);
static void
PngErrorFunc (png_structp png_ptr,
const char *msg);
static HPDF_STATUS
ReadPngData_Interlaced (HPDF_Dict image,
png_structp png_ptr,
png_infop info_ptr);
static HPDF_STATUS
ReadPngData (HPDF_Dict image,
png_structp png_ptr,
png_infop info_ptr);
static HPDF_STATUS
CreatePallet (HPDF_Dict image,
png_structp png_ptr,
png_infop info_ptr);
static HPDF_STATUS
PngBeforeWrite (HPDF_Dict obj);
static HPDF_STATUS
PngAfterWrite (HPDF_Dict obj);
/*---------------------------------------------------------------------------*/
static void
PngErrorFunc (png_structp png_ptr,
const char *msg)
{
char error_number[16];
HPDF_UINT i;
HPDF_STATUS detail_no;
HPDF_Error error;
/* pick out error-number from error message */
HPDF_MemSet (error_number, 0, 16);
for (i = 0; i < 15; i++) {
error_number[i] = *(msg + i);
if (*(msg + i + 1) == ' ')
break;
}
error = (HPDF_Error)png_get_error_ptr (png_ptr);
detail_no = (HPDF_STATUS)HPDF_AToI (error_number);
HPDF_SetError (error, HPDF_LIBPNG_ERROR, detail_no);
}
static HPDF_STATUS
ReadPngData_Interlaced (HPDF_Dict image,
png_structp png_ptr,
png_infop info_ptr)
{
png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
png_bytep* row_pointers = HPDF_GetMem (image->mmgr,
info_ptr->height * sizeof (png_bytep));
if (row_pointers) {
HPDF_UINT i;
HPDF_MemSet (row_pointers, 0, info_ptr->height * sizeof (png_bytep));
for (i = 0; i < (HPDF_UINT)info_ptr->height; i++) {
row_pointers[i] = HPDF_GetMem (image->mmgr, len);
if (image->error->error_no != HPDF_OK)
break;
}
if (image->error->error_no == HPDF_OK) {
png_read_image(png_ptr, row_pointers);
if (image->error->error_no == HPDF_OK) { /* add this line */
for (i = 0; i < (HPDF_UINT)info_ptr->height; i++) {
if (HPDF_Stream_Write (image->stream, row_pointers[i], len) !=
HPDF_OK)
break;
}
}
}
/* clean up */
for (i = 0; i < (HPDF_UINT)info_ptr->height; i++) {
HPDF_FreeMem (image->mmgr, row_pointers[i]);
}
HPDF_FreeMem (image->mmgr, row_pointers);
}
return image->error->error_no;
}
static HPDF_STATUS
ReadPngData (HPDF_Dict image,
png_structp png_ptr,
png_infop info_ptr)
{
png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
png_bytep buf_ptr = HPDF_GetMem (image->mmgr, len);
if (buf_ptr) {
HPDF_UINT i;
for (i = 0; i < (HPDF_UINT)info_ptr->height; i++) {
png_read_rows(png_ptr, (png_byte**)&buf_ptr, NULL, 1);
if (image->error->error_no != HPDF_OK)
break;
if (HPDF_Stream_Write (image->stream, buf_ptr, len) != HPDF_OK)
break;
}
HPDF_FreeMem (image->mmgr, buf_ptr);
}
return image->error->error_no;
}
static HPDF_STATUS
ReadTransparentPaletteData (HPDF_Dict image,
png_structp png_ptr,
png_infop info_ptr,
png_bytep smask_data,
png_bytep trans,
int num_trans)
{
HPDF_STATUS ret = HPDF_OK;
HPDF_UINT i, j;
png_bytep *row_ptr;
row_ptr = HPDF_GetMem (image->mmgr, info_ptr->height * sizeof(png_bytep));
if (!row_ptr) {
return HPDF_FAILD_TO_ALLOC_MEM;
} else {
png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
for (i = 0; i < (HPDF_UINT)info_ptr->height; i++) {
row_ptr[i] = HPDF_GetMem(image->mmgr, len);
if (!row_ptr[i]) {
for (; i >= 0; i--) {
HPDF_FreeMem (image->mmgr, row_ptr[i]);
}
HPDF_FreeMem (image->mmgr, row_ptr);
return HPDF_FAILD_TO_ALLOC_MEM;
}
}
}
png_read_image(png_ptr, row_ptr);
if (image->error->error_no != HPDF_OK) {
ret = HPDF_INVALID_PNG_IMAGE;
goto Error;
}
for (j = 0; j < info_ptr->height; j++) {
for (i = 0; i < info_ptr->width; i++) {
smask_data[info_ptr->width * j + i] = (row_ptr[j][i] < num_trans) ? trans[row_ptr[j][i]] : 0xFF;
}
if (HPDF_Stream_Write (image->stream, row_ptr[j], info_ptr->width) != HPDF_OK) {
ret = HPDF_FILE_IO_ERROR;
goto Error;
}
}
Error:
for (i = 0; i < (HPDF_UINT)info_ptr->height; i++) {
HPDF_FreeMem (image->mmgr, row_ptr[i]);
}
HPDF_FreeMem (image->mmgr, row_ptr);
return ret;
}
static HPDF_STATUS
ReadTransparentPngData (HPDF_Dict image,
png_structp png_ptr,
png_infop info_ptr,
png_bytep smask_data)
{
HPDF_STATUS ret = HPDF_OK;
HPDF_INT row_len;
HPDF_UINT i, j;
png_bytep *row_ptr, row;
png_byte color_type;
color_type = png_get_color_type(png_ptr, info_ptr);
if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
return HPDF_INVALID_PNG_IMAGE;
}
row_ptr = HPDF_GetMem (image->mmgr, info_ptr->height * sizeof(png_bytep));
if (!row_ptr) {
return HPDF_FAILD_TO_ALLOC_MEM;
} else {
png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
for (i = 0; i < (HPDF_UINT)info_ptr->height; i++) {
row_ptr[i] = HPDF_GetMem(image->mmgr, len);
if (!row_ptr[i]) {
for (; i >= 0; i--) {
HPDF_FreeMem (image->mmgr, row_ptr[i]);
}
HPDF_FreeMem (image->mmgr, row_ptr);
return HPDF_FAILD_TO_ALLOC_MEM;
}
}
}
png_read_image(png_ptr, row_ptr);
if (image->error->error_no != HPDF_OK) {
ret = HPDF_INVALID_PNG_IMAGE;
goto Error;
}
switch (color_type) {
case PNG_COLOR_TYPE_RGB_ALPHA:
row_len = 3 * info_ptr->width * sizeof(png_byte);
for (j = 0; j < info_ptr->height; j++) {
for (i = 0; i < info_ptr->width; i++) {
row = row_ptr[j];
memmove(row + (3 * i), row + (4*i), 3);
smask_data[info_ptr->width * j + i] = row[4 * i + 3];
}
if (HPDF_Stream_Write (image->stream, row, row_len) != HPDF_OK) {
ret = HPDF_FILE_IO_ERROR;
goto Error;
}
}
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
row_len = info_ptr->width * sizeof(png_byte);
for (j = 0; j < info_ptr->height; j++) {
for (i = 0; i < info_ptr->width; i++) {
row = row_ptr[j];
row[i] = row[2 * i];
smask_data[info_ptr->width * j + i] = row[2 * i + 1];
}
if (HPDF_Stream_Write (image->stream, row, row_len) != HPDF_OK) {
ret = HPDF_FILE_IO_ERROR;
goto Error;
}
}
break;
default:
ret = HPDF_INVALID_PNG_IMAGE;
goto Error;
}
Error:
for (i = 0; i < (HPDF_UINT)info_ptr->height; i++) {
HPDF_FreeMem (image->mmgr, row_ptr[i]);
}
HPDF_FreeMem (image->mmgr, row_ptr);
return ret;
}
static HPDF_STATUS
CreatePallet (HPDF_Dict image,
png_structp png_ptr,
png_infop info_ptr)
{
HPDF_INT num_pl = 0;
png_color *src_pl = NULL;
HPDF_BYTE *ppallet;
HPDF_BYTE *p;
HPDF_UINT i;
HPDF_Array array;
/* png_get_PLTE does not call PngErrorFunc even if it failed.
* so we call HPDF_Set_Error to set error-code.
*/
if (png_get_PLTE(png_ptr, info_ptr, (png_color**)&src_pl, &num_pl) !=
PNG_INFO_PLTE)
return HPDF_SetError (image->error, HPDF_LIBPNG_ERROR,
HPDF_CANNOT_GET_PALLET);
/* make a pallet array for indexed image. */
ppallet = HPDF_GetMem (image->mmgr, num_pl * 3);
if (!ppallet)
return image->error->error_no;
p = ppallet;
for (i = 0; i < num_pl; i++, src_pl++) {
*p++ = src_pl->red;
*p++ = src_pl->green;
*p++ = src_pl->blue;
}
array = HPDF_Array_New (image->mmgr);
if (array) {
HPDF_Binary b;
HPDF_Dict_Add (image, "ColorSpace", array);
HPDF_Array_AddName (array, "Indexed");
HPDF_Array_AddName (array, "DeviceRGB");
HPDF_Array_AddNumber (array, num_pl - 1);
b = HPDF_Binary_New (image->mmgr, ppallet, num_pl * 3);
if (b)
HPDF_Array_Add (array, b);
}
HPDF_FreeMem (image->mmgr, ppallet);
return image->error->error_no;
}
#define HPDF_PNG_BYTES_TO_CHECK 8
HPDF_Image
HPDF_Image_LoadPngImage (HPDF_MMgr mmgr,
HPDF_Stream png_data,
HPDF_Xref xref,
HPDF_BOOL delayed_loading)
{
HPDF_STATUS ret;
HPDF_Dict image;
png_byte header[HPDF_PNG_BYTES_TO_CHECK];
HPDF_UINT len = HPDF_PNG_BYTES_TO_CHECK;
HPDF_PTRACE ((" HPDF_Image_LoadPngImage\n"));
HPDF_MemSet (header, 0x00, HPDF_PNG_BYTES_TO_CHECK);
ret = HPDF_Stream_Read (png_data, header, &len);
if (ret != HPDF_OK ||
png_sig_cmp (header, (png_size_t)0, HPDF_PNG_BYTES_TO_CHECK)) {
HPDF_SetError (mmgr->error, HPDF_INVALID_PNG_IMAGE, 0);
return NULL;
}
image = HPDF_DictStream_New (mmgr, xref);
if (!image)
return NULL;
image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
ret += HPDF_Dict_AddName (image, "Type", "XObject");
ret += HPDF_Dict_AddName (image, "Subtype", "Image");
if (ret != HPDF_OK)
return NULL;
if (LoadPngData (image, xref, png_data, delayed_loading) != HPDF_OK)
return NULL;
return image;
}
static HPDF_STATUS
LoadPngData (HPDF_Dict image,
HPDF_Xref xref,
HPDF_Stream png_data,
HPDF_BOOL delayed_loading)
{
HPDF_STATUS ret = HPDF_OK;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
HPDF_PTRACE ((" HPDF_Image_LoadPngImage\n"));
/* create read_struct. */
png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
image->error, PngErrorFunc, PngErrorFunc);
if (png_ptr == NULL) {
HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
return HPDF_FAILD_TO_ALLOC_MEM;
}
/* create info-struct */
info_ptr = png_create_info_struct (png_ptr);
if (info_ptr == NULL) {
HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
goto Exit;
}
png_set_sig_bytes (png_ptr, HPDF_PNG_BYTES_TO_CHECK);
png_set_read_fn (png_ptr, (void *)png_data, (png_rw_ptr)&PngReadFunc);
/* reading info structure. */
png_read_info(png_ptr, info_ptr);
if (image->error->error_no != HPDF_OK) {
goto Exit;
}
/* 16bit images are not supported. */
if (info_ptr->bit_depth == 16) {
png_set_strip_16(png_ptr);
}
png_read_update_info(png_ptr, info_ptr);
if (image->error->error_no != HPDF_OK) {
goto Exit;
}
/* check palette-based images for transparent areas and load them immediately if found */
if (xref && PNG_COLOR_TYPE_PALETTE & info_ptr->color_type) {
png_bytep trans;
int num_trans;
HPDF_Dict smask;
png_bytep smask_data;
if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ||
!png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL)) {
goto no_transparent_color_in_palette;
}
smask = HPDF_DictStream_New (image->mmgr, xref);
if (!smask) {
ret = HPDF_FAILD_TO_ALLOC_MEM;
goto Exit;
}
smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
ret = HPDF_Dict_AddName (smask, "Type", "XObject");
ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)info_ptr->width);
ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)info_ptr->height);
ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)info_ptr->bit_depth);
if (ret != HPDF_OK) {
HPDF_Dict_Free(smask);
ret = HPDF_INVALID_PNG_IMAGE;
goto Exit;
}
smask_data = HPDF_GetMem(image->mmgr, info_ptr->width * info_ptr->height);
if (!smask_data) {
HPDF_Dict_Free(smask);
ret = HPDF_FAILD_TO_ALLOC_MEM;
goto Exit;
}
if (ReadTransparentPaletteData(image, png_ptr, info_ptr, smask_data, trans, num_trans) != HPDF_OK) {
HPDF_FreeMem(image->mmgr, smask_data);
HPDF_Dict_Free(smask);
ret = HPDF_INVALID_PNG_IMAGE;
goto Exit;
}
if (HPDF_Stream_Write(smask->stream, smask_data, info_ptr->width * info_ptr->height) != HPDF_OK) {
HPDF_FreeMem(image->mmgr, smask_data);
HPDF_Dict_Free(smask);
ret = HPDF_FILE_IO_ERROR;
goto Exit;
}
HPDF_FreeMem(image->mmgr, smask_data);
ret += CreatePallet(image, png_ptr, info_ptr);
ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)info_ptr->width);
ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)info_ptr->height);
ret += HPDF_Dict_AddNumber (image, "BitsPerComponent", (HPDF_UINT)info_ptr->bit_depth);
ret += HPDF_Dict_Add (image, "SMask", smask);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return HPDF_OK;
}
no_transparent_color_in_palette:
/* read images with alpha channel right away
we have to do this because image transparent mask must be added to the Xref */
if (xref && PNG_COLOR_MASK_ALPHA & info_ptr->color_type) {
HPDF_Dict smask;
png_bytep smask_data;
smask = HPDF_DictStream_New (image->mmgr, xref);
if (!smask) {
ret = HPDF_FAILD_TO_ALLOC_MEM;
goto Exit;
}
smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
ret = HPDF_Dict_AddName (smask, "Type", "XObject");
ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)info_ptr->width);
ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)info_ptr->height);
ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)info_ptr->bit_depth);
if (ret != HPDF_OK) {
HPDF_Dict_Free(smask);
ret = HPDF_INVALID_PNG_IMAGE;
goto Exit;
}
smask_data = HPDF_GetMem(image->mmgr, info_ptr->width * info_ptr->height);
if (!smask_data) {
HPDF_Dict_Free(smask);
ret = HPDF_FAILD_TO_ALLOC_MEM;
goto Exit;
}
if (ReadTransparentPngData(image, png_ptr, info_ptr, smask_data) != HPDF_OK) {
HPDF_FreeMem(image->mmgr, smask_data);
HPDF_Dict_Free(smask);
ret = HPDF_INVALID_PNG_IMAGE;
goto Exit;
}
if (HPDF_Stream_Write(smask->stream, smask_data, info_ptr->width * info_ptr->height) != HPDF_OK) {
HPDF_FreeMem(image->mmgr, smask_data);
HPDF_Dict_Free(smask);
ret = HPDF_FILE_IO_ERROR;
goto Exit;
}
HPDF_FreeMem(image->mmgr, smask_data);
ret += HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");
ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)info_ptr->width);
ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)info_ptr->height);
ret += HPDF_Dict_AddNumber (image, "BitsPerComponent", (HPDF_UINT)info_ptr->bit_depth);
ret += HPDF_Dict_Add (image, "SMask", smask);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return HPDF_OK;
}
/* if the image has color palette, copy the pallet of the image to
* create color map.
*/
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
ret = CreatePallet(image, png_ptr, info_ptr);
else if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)
ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
else
ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");
if (ret != HPDF_OK)
goto Exit;
/* read image-data
* if the image is interlaced, read whole image at once.
* if delayed_loading is HPDF_TRUE, the data does not load this phase.
*/
if (delayed_loading) {
image->before_write_fn = PngBeforeWrite;
image->after_write_fn = PngAfterWrite;
} else {
if (png_get_interlace_type(png_ptr, info_ptr) != PNG_INTERLACE_NONE)
ret = ReadPngData_Interlaced(image, png_ptr, info_ptr);
else
ret = ReadPngData(image, png_ptr, info_ptr);
if (ret != HPDF_OK)
goto Exit;
}
/* setting the info of the image. */
if (HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)info_ptr->width)
!= HPDF_OK)
goto Exit;
if (HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)info_ptr->height)
!= HPDF_OK)
goto Exit;
if (HPDF_Dict_AddNumber (image, "BitsPerComponent",
(HPDF_UINT)info_ptr->bit_depth) != HPDF_OK)
goto Exit;
/* clean up */
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return HPDF_OK;
Exit:
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
if (ret != HPDF_OK) {
return ret;
}
return image->error->error_no;
}
static HPDF_STATUS
PngBeforeWrite (HPDF_Dict obj)
{
HPDF_STATUS ret;
png_byte header[HPDF_PNG_BYTES_TO_CHECK];
HPDF_UINT len = HPDF_PNG_BYTES_TO_CHECK;
HPDF_Stream png_data;
HPDF_String s;
HPDF_PTRACE ((" PngBeforeWrite\n"));
HPDF_MemStream_FreeData(obj->stream);
s = HPDF_Dict_GetItem (obj, "_FILE_NAME", HPDF_OCLASS_STRING);
if (!s)
return HPDF_SetError (obj->error, HPDF_MISSING_FILE_NAME_ENTRY, 0);
png_data = HPDF_FileReader_New (obj->mmgr, (const char *)(s->value));
if (!HPDF_Stream_Validate (png_data))
return obj->error->error_no;
HPDF_MemSet (header, 0x00, HPDF_PNG_BYTES_TO_CHECK);
ret = HPDF_Stream_Read (png_data, header, &len);
if (ret != HPDF_OK ||
png_sig_cmp (header, (png_size_t)0, HPDF_PNG_BYTES_TO_CHECK)) {
HPDF_Stream_Free(png_data);
return HPDF_SetError (obj->error, HPDF_INVALID_PNG_IMAGE, 0);
}
if ((ret = LoadPngData (obj, NULL, png_data, HPDF_FALSE)) != HPDF_OK) {
HPDF_Stream_Free(png_data);
return ret;
}
HPDF_Stream_Free(png_data);
return HPDF_OK;
}
static HPDF_STATUS
PngAfterWrite (HPDF_Dict obj)
{
HPDF_PTRACE ((" PngAfterWrite\n"));
HPDF_MemStream_FreeData(obj->stream);
return HPDF_OK;
}
#endif /* HPDF_NOPNGLIB */