1/*
2 * << Haru Free PDF Library >> -- hpdf_image.c
3 *
4 * URL: http://libharu.org
5 *
6 * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
7 * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
8 *
9 * Permission to use, copy, modify, distribute and sell this software
10 * and its documentation for any purpose is hereby granted without fee,
11 * provided that the above copyright notice appear in all copies and
12 * that both that copyright notice and this permission notice appear
13 * in supporting documentation.
14 * It is provided "as is" without express or implied warranty.
15 *
16 */
17
18#include "hpdf_conf.h"
19#include "hpdf_utils.h"
20#include "hpdf_image.h"
21
22#ifndef LIBHPDF_HAVE_NOPNGLIB
23#include <png.h>
24#include <string.h>
25
26static void
27PngErrorFunc (png_structp png_ptr,
28 const char *msg);
29
30
31static void
32PngReadFunc (png_structp png_ptr,
33 png_bytep data,
34 png_uint_32 length)
35{
36 HPDF_UINT len = length;
37 HPDF_Stream stream = (HPDF_Stream)png_get_io_ptr (png_ptr);
38
39 HPDF_Stream_Read (stream, data, &len);
40}
41
42
43static HPDF_STATUS
44LoadPngData (HPDF_Dict image,
45 HPDF_Xref xref,
46 HPDF_Stream png_data,
47 HPDF_BOOL delayed_loading);
48
49
50static void
51PngErrorFunc (png_structp png_ptr,
52 const char *msg);
53
54
55static HPDF_STATUS
56ReadPngData_Interlaced (HPDF_Dict image,
57 png_structp png_ptr,
58 png_infop info_ptr);
59
60
61static HPDF_STATUS
62ReadPngData (HPDF_Dict image,
63 png_structp png_ptr,
64 png_infop info_ptr);
65
66
67static HPDF_STATUS
68CreatePallet (HPDF_Dict image,
69 png_structp png_ptr,
70 png_infop info_ptr);
71
72
73static HPDF_STATUS
74PngBeforeWrite (HPDF_Dict obj);
75
76
77static HPDF_STATUS
78PngAfterWrite (HPDF_Dict obj);
79
80
81/*---------------------------------------------------------------------------*/
82
83static void
84PngErrorFunc (png_structp png_ptr,
85 const char *msg)
86{
87 char error_number[16];
88 HPDF_UINT i;
89 HPDF_STATUS detail_no;
90 HPDF_Error error;
91
92 /* pick out error-number from error message */
93 HPDF_MemSet (error_number, 0, 16);
94
95 for (i = 0; i < 15; i++) {
96 error_number[i] = *(msg + i);
97 if (*(msg + i + 1) == ' ')
98 break;
99 }
100
101 error = (HPDF_Error)png_get_error_ptr (png_ptr);
102 detail_no = (HPDF_STATUS)HPDF_AToI (error_number);
103 HPDF_SetError (error, HPDF_LIBPNG_ERROR, detail_no);
104}
105
106
107static HPDF_STATUS
108ReadPngData_Interlaced (HPDF_Dict image,
109 png_structp png_ptr,
110 png_infop info_ptr)
111{
112 png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
113 png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
114 png_bytep* row_pointers = HPDF_GetMem (image->mmgr,
115 height * sizeof (png_bytep));
116
117 if (row_pointers) {
118 HPDF_UINT i;
119
120 HPDF_MemSet (row_pointers, 0, height * sizeof (png_bytep));
121 for (i = 0; i < (HPDF_UINT)height; i++) {
122 row_pointers[i] = HPDF_GetMem (image->mmgr, len);
123
124 if (image->error->error_no != HPDF_OK)
125 break;
126 }
127
128 if (image->error->error_no == HPDF_OK) {
129 png_read_image(png_ptr, row_pointers);
130 if (image->error->error_no == HPDF_OK) { /* add this line */
131 for (i = 0; i < (HPDF_UINT)height; i++) {
132 if (HPDF_Stream_Write (image->stream, row_pointers[i], len) !=
133 HPDF_OK)
134 break;
135 }
136 }
137 }
138
139 /* clean up */
140 for (i = 0; i < (HPDF_UINT)height; i++) {
141 HPDF_FreeMem (image->mmgr, row_pointers[i]);
142 }
143
144 HPDF_FreeMem (image->mmgr, row_pointers);
145 }
146
147 return image->error->error_no;
148}
149
150static HPDF_STATUS
151ReadPngData (HPDF_Dict image,
152 png_structp png_ptr,
153 png_infop info_ptr)
154{
155 png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
156 png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
157 png_bytep buf_ptr = HPDF_GetMem (image->mmgr, len);
158
159 if (buf_ptr) {
160 HPDF_UINT i;
161
162 for (i = 0; i < (HPDF_UINT)height; i++) {
163 png_read_rows(png_ptr, (png_byte**)&buf_ptr, NULL, 1);
164 if (image->error->error_no != HPDF_OK)
165 break;
166
167 if (HPDF_Stream_Write (image->stream, buf_ptr, len) != HPDF_OK)
168 break;
169 }
170
171 HPDF_FreeMem (image->mmgr, buf_ptr);
172 }
173
174 return image->error->error_no;
175}
176
177static HPDF_STATUS
178ReadTransparentPaletteData (HPDF_Dict image,
179 png_structp png_ptr,
180 png_infop info_ptr,
181 png_bytep smask_data,
182 png_bytep trans,
183 int num_trans)
184{
185 HPDF_STATUS ret = HPDF_OK;
186 HPDF_UINT i, j;
187 png_bytep *row_ptr;
188 png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
189 png_uint_32 width = png_get_image_width(png_ptr, info_ptr);
190
191 row_ptr = HPDF_GetMem (image->mmgr, height * sizeof(png_bytep));
192 if (!row_ptr) {
193 return HPDF_FAILD_TO_ALLOC_MEM;
194 } else {
195 png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
196
197 for (i = 0; i < (HPDF_UINT)height; i++) {
198 row_ptr[i] = HPDF_GetMem(image->mmgr, len);
199 if (!row_ptr[i]) {
200 for (; i > 0; i--) {
201 HPDF_FreeMem (image->mmgr, row_ptr[i]);
202 }
203 HPDF_FreeMem (image->mmgr, row_ptr);
204 return HPDF_FAILD_TO_ALLOC_MEM;
205 }
206 }
207 }
208
209 png_read_image(png_ptr, row_ptr);
210 if (image->error->error_no != HPDF_OK) {
211 ret = HPDF_INVALID_PNG_IMAGE;
212 goto Error;
213 }
214
215 for (j = 0; j < height; j++) {
216 for (i = 0; i < width; i++) {
217 smask_data[width * j + i] = (row_ptr[j][i] < num_trans) ? trans[row_ptr[j][i]] : 0xFF;
218 }
219
220 if (HPDF_Stream_Write (image->stream, row_ptr[j], width) != HPDF_OK) {
221 ret = HPDF_FILE_IO_ERROR;
222 goto Error;
223 }
224 }
225
226Error:
227 for (i = 0; i < (HPDF_UINT)height; i++) {
228 HPDF_FreeMem (image->mmgr, row_ptr[i]);
229 }
230
231 HPDF_FreeMem (image->mmgr, row_ptr);
232 return ret;
233}
234
235static HPDF_STATUS
236ReadTransparentPngData (HPDF_Dict image,
237 png_structp png_ptr,
238 png_infop info_ptr,
239 png_bytep smask_data)
240{
241 HPDF_STATUS ret = HPDF_OK;
242 HPDF_INT row_len;
243 HPDF_UINT i, j;
244 png_bytep *row_ptr, row;
245 png_byte color_type;
246 png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
247 png_uint_32 width = png_get_image_width(png_ptr, info_ptr);
248
249 color_type = png_get_color_type(png_ptr, info_ptr);
250
251 if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
252 return HPDF_INVALID_PNG_IMAGE;
253 }
254
255 row_ptr = HPDF_GetMem (image->mmgr, height * sizeof(png_bytep));
256 if (!row_ptr) {
257 return HPDF_FAILD_TO_ALLOC_MEM;
258 } else {
259 png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
260
261 for (i = 0; i < (HPDF_UINT)height; i++) {
262 row_ptr[i] = HPDF_GetMem(image->mmgr, len);
263 if (!row_ptr[i]) {
264 for (; i > 0; i--) {
265 HPDF_FreeMem (image->mmgr, row_ptr[i]);
266 }
267 HPDF_FreeMem (image->mmgr, row_ptr);
268 return HPDF_FAILD_TO_ALLOC_MEM;
269 }
270 }
271 }
272
273 png_read_image(png_ptr, row_ptr);
274 if (image->error->error_no != HPDF_OK) {
275 ret = HPDF_INVALID_PNG_IMAGE;
276 goto Error;
277 }
278
279 switch (color_type) {
280 case PNG_COLOR_TYPE_RGB_ALPHA:
281 row_len = 3 * width * sizeof(png_byte);
282 for (j = 0; j < height; j++) {
283 for (i = 0; i < width; i++) {
284 row = row_ptr[j];
285 memmove(row + (3 * i), row + (4*i), 3);
286 smask_data[width * j + i] = row[4 * i + 3];
287 }
288
289 if (HPDF_Stream_Write (image->stream, row, row_len) != HPDF_OK) {
290 ret = HPDF_FILE_IO_ERROR;
291 goto Error;
292 }
293 }
294 break;
295 case PNG_COLOR_TYPE_GRAY_ALPHA:
296 row_len = width * sizeof(png_byte);
297 for (j = 0; j < height; j++) {
298 for (i = 0; i < width; i++) {
299 row = row_ptr[j];
300 row[i] = row[2 * i];
301 smask_data[width * j + i] = row[2 * i + 1];
302 }
303
304 if (HPDF_Stream_Write (image->stream, row, row_len) != HPDF_OK) {
305 ret = HPDF_FILE_IO_ERROR;
306 goto Error;
307 }
308 }
309 break;
310 default:
311 ret = HPDF_INVALID_PNG_IMAGE;
312 goto Error;
313 }
314
315Error:
316 for (i = 0; i < (HPDF_UINT)height; i++) {
317 HPDF_FreeMem (image->mmgr, row_ptr[i]);
318 }
319
320 HPDF_FreeMem (image->mmgr, row_ptr);
321 return ret;
322}
323
324static HPDF_STATUS
325CreatePallet (HPDF_Dict image,
326 png_structp png_ptr,
327 png_infop info_ptr)
328{
329 HPDF_INT num_pl = 0;
330 png_color *src_pl = NULL;
331 HPDF_BYTE *ppallet;
332 HPDF_BYTE *p;
333 HPDF_UINT i;
334 HPDF_Array array;
335
336 /* png_get_PLTE does not call PngErrorFunc even if it failed.
337 * so we call HPDF_Set_Error to set error-code.
338 */
339 if (png_get_PLTE(png_ptr, info_ptr, (png_color**)&src_pl, &num_pl) !=
340 PNG_INFO_PLTE)
341 return HPDF_SetError (image->error, HPDF_LIBPNG_ERROR,
342 HPDF_CANNOT_GET_PALLET);
343
344
345 /* make a pallet array for indexed image. */
346 ppallet = HPDF_GetMem (image->mmgr, num_pl * 3);
347 if (!ppallet)
348 return image->error->error_no;
349
350 p = ppallet;
351 for (i = 0; i < num_pl; i++, src_pl++) {
352 *p++ = src_pl->red;
353 *p++ = src_pl->green;
354 *p++ = src_pl->blue;
355 }
356
357 array = HPDF_Array_New (image->mmgr);
358 if (array) {
359 HPDF_Binary b;
360
361 HPDF_Dict_Add (image, "ColorSpace", array);
362
363 HPDF_Array_AddName (array, "Indexed");
364 HPDF_Array_AddName (array, "DeviceRGB");
365 HPDF_Array_AddNumber (array, num_pl - 1);
366
367 b = HPDF_Binary_New (image->mmgr, ppallet, num_pl * 3);
368 if (b)
369 HPDF_Array_Add (array, b);
370 }
371
372 HPDF_FreeMem (image->mmgr, ppallet);
373
374 return image->error->error_no;
375}
376
377#define HPDF_PNG_BYTES_TO_CHECK 8
378
379HPDF_Image
380HPDF_Image_LoadPngImage (HPDF_MMgr mmgr,
381 HPDF_Stream png_data,
382 HPDF_Xref xref,
383 HPDF_BOOL delayed_loading)
384{
385 HPDF_STATUS ret;
386 HPDF_Dict image;
387 png_byte header[HPDF_PNG_BYTES_TO_CHECK];
388 HPDF_UINT len = HPDF_PNG_BYTES_TO_CHECK;
389
390 HPDF_PTRACE ((" HPDF_Image_LoadPngImage\n"));
391
392 HPDF_MemSet (header, 0x00, HPDF_PNG_BYTES_TO_CHECK);
393 ret = HPDF_Stream_Read (png_data, header, &len);
394 if (ret != HPDF_OK ||
395 png_sig_cmp (header, (png_size_t)0, HPDF_PNG_BYTES_TO_CHECK)) {
396 HPDF_SetError (mmgr->error, HPDF_INVALID_PNG_IMAGE, 0);
397 return NULL;
398 }
399
400 image = HPDF_DictStream_New (mmgr, xref);
401 if (!image)
402 return NULL;
403
404 image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
405 ret += HPDF_Dict_AddName (image, "Type", "XObject");
406 ret += HPDF_Dict_AddName (image, "Subtype", "Image");
407 if (ret != HPDF_OK)
408 return NULL;
409
410 if (LoadPngData (image, xref, png_data, delayed_loading) != HPDF_OK)
411 return NULL;
412
413 return image;
414}
415
416
417static HPDF_STATUS
418LoadPngData (HPDF_Dict image,
419 HPDF_Xref xref,
420 HPDF_Stream png_data,
421 HPDF_BOOL delayed_loading)
422
423{
424 HPDF_STATUS ret = HPDF_OK;
425 png_uint_32 width, height;
426 int bit_depth, color_type;
427 png_structp png_ptr = NULL;
428 png_infop info_ptr = NULL;
429
430 HPDF_PTRACE ((" HPDF_Image_LoadPngImage\n"));
431
432 /* create read_struct. */
433 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
434 image->error, PngErrorFunc, PngErrorFunc);
435
436 if (png_ptr == NULL) {
437 HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
438 return HPDF_FAILD_TO_ALLOC_MEM;
439 }
440
441 /* create info-struct */
442 info_ptr = png_create_info_struct (png_ptr);
443
444 if (info_ptr == NULL) {
445 HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
446 goto Exit;
447 }
448
449 png_set_sig_bytes (png_ptr, HPDF_PNG_BYTES_TO_CHECK);
450 png_set_read_fn (png_ptr, (void *)png_data, (png_rw_ptr)&PngReadFunc);
451
452 /* reading info structure. */
453 png_read_info(png_ptr, info_ptr);
454 if (image->error->error_no != HPDF_OK) {
455 goto Exit;
456 }
457
458 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
459
460 /* 16bit images are not supported. */
461 if (bit_depth == 16) {
462 png_set_strip_16(png_ptr);
463 }
464
465 png_read_update_info(png_ptr, info_ptr);
466 if (image->error->error_no != HPDF_OK) {
467 goto Exit;
468 }
469
470 /* check palette-based images for transparent areas and load them immediately if found */
471 if (xref && PNG_COLOR_TYPE_PALETTE & color_type) {
472 png_bytep trans;
473 int num_trans;
474 HPDF_Dict smask;
475 png_bytep smask_data;
476
477 if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ||
478 !png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL)) {
479 goto no_transparent_color_in_palette;
480 }
481
482 smask = HPDF_DictStream_New (image->mmgr, xref);
483 if (!smask) {
484 ret = HPDF_FAILD_TO_ALLOC_MEM;
485 goto Exit;
486 }
487
488 smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
489 ret = HPDF_Dict_AddName (smask, "Type", "XObject");
490 ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
491 ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)width);
492 ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)height);
493 ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
494 ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)bit_depth);
495
496 if (ret != HPDF_OK) {
497 HPDF_Dict_Free(smask);
498 ret = HPDF_INVALID_PNG_IMAGE;
499 goto Exit;
500 }
501
502 smask_data = HPDF_GetMem(image->mmgr, width * height);
503 if (!smask_data) {
504 HPDF_Dict_Free(smask);
505 ret = HPDF_FAILD_TO_ALLOC_MEM;
506 goto Exit;
507 }
508
509 if (ReadTransparentPaletteData(image, png_ptr, info_ptr, smask_data, trans, num_trans) != HPDF_OK) {
510 HPDF_FreeMem(image->mmgr, smask_data);
511 HPDF_Dict_Free(smask);
512 ret = HPDF_INVALID_PNG_IMAGE;
513 goto Exit;
514 }
515
516 if (HPDF_Stream_Write(smask->stream, smask_data, width * height) != HPDF_OK) {
517 HPDF_FreeMem(image->mmgr, smask_data);
518 HPDF_Dict_Free(smask);
519 ret = HPDF_FILE_IO_ERROR;
520 goto Exit;
521 }
522 HPDF_FreeMem(image->mmgr, smask_data);
523
524
525 ret += CreatePallet(image, png_ptr, info_ptr);
526 ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width);
527 ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height);
528 ret += HPDF_Dict_AddNumber (image, "BitsPerComponent", (HPDF_UINT)bit_depth);
529 ret += HPDF_Dict_Add (image, "SMask", smask);
530
531 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
532 return HPDF_OK;
533 }
534
535no_transparent_color_in_palette:
536
537 /* read images with alpha channel right away
538 we have to do this because image transparent mask must be added to the Xref */
539 if (xref && PNG_COLOR_MASK_ALPHA & color_type) {
540 HPDF_Dict smask;
541 png_bytep smask_data;
542
543 smask = HPDF_DictStream_New (image->mmgr, xref);
544 if (!smask) {
545 ret = HPDF_FAILD_TO_ALLOC_MEM;
546 goto Exit;
547 }
548
549 smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
550 ret = HPDF_Dict_AddName (smask, "Type", "XObject");
551 ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
552 ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)width);
553 ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)height);
554 ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
555 ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)bit_depth);
556
557 if (ret != HPDF_OK) {
558 HPDF_Dict_Free(smask);
559 ret = HPDF_INVALID_PNG_IMAGE;
560 goto Exit;
561 }
562
563 smask_data = HPDF_GetMem(image->mmgr, width * height);
564 if (!smask_data) {
565 HPDF_Dict_Free(smask);
566 ret = HPDF_FAILD_TO_ALLOC_MEM;
567 goto Exit;
568 }
569
570 if (ReadTransparentPngData(image, png_ptr, info_ptr, smask_data) != HPDF_OK) {
571 HPDF_FreeMem(image->mmgr, smask_data);
572 HPDF_Dict_Free(smask);
573 ret = HPDF_INVALID_PNG_IMAGE;
574 goto Exit;
575 }
576
577 if (HPDF_Stream_Write(smask->stream, smask_data, width * height) != HPDF_OK) {
578 HPDF_FreeMem(image->mmgr, smask_data);
579 HPDF_Dict_Free(smask);
580 ret = HPDF_FILE_IO_ERROR;
581 goto Exit;
582 }
583 HPDF_FreeMem(image->mmgr, smask_data);
584
585 if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
586 ret += HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
587 } else {
588 ret += HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");
589 }
590 ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width);
591 ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height);
592 ret += HPDF_Dict_AddNumber (image, "BitsPerComponent", (HPDF_UINT)bit_depth);
593 ret += HPDF_Dict_Add (image, "SMask", smask);
594
595 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
596 return HPDF_OK;
597 }
598
599 /* if the image has color palette, copy the pallet of the image to
600 * create color map.
601 */
602 if (color_type == PNG_COLOR_TYPE_PALETTE)
603 ret = CreatePallet(image, png_ptr, info_ptr);
604 else if (color_type == PNG_COLOR_TYPE_GRAY)
605 ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
606 else
607 ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");
608
609 if (ret != HPDF_OK)
610 goto Exit;
611
612 /* read image-data
613 * if the image is interlaced, read whole image at once.
614 * if delayed_loading is HPDF_TRUE, the data does not load this phase.
615 */
616 if (delayed_loading) {
617 image->before_write_fn = PngBeforeWrite;
618 image->after_write_fn = PngAfterWrite;
619 } else {
620 if (png_get_interlace_type(png_ptr, info_ptr) != PNG_INTERLACE_NONE)
621 ret = ReadPngData_Interlaced(image, png_ptr, info_ptr);
622 else
623 ret = ReadPngData(image, png_ptr, info_ptr);
624
625 if (ret != HPDF_OK)
626 goto Exit;
627 }
628
629 /* setting the info of the image. */
630 if (HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width)
631 != HPDF_OK)
632 goto Exit;
633
634 if (HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height)
635 != HPDF_OK)
636 goto Exit;
637
638 if (HPDF_Dict_AddNumber (image, "BitsPerComponent",
639 (HPDF_UINT)bit_depth) != HPDF_OK)
640 goto Exit;
641
642 /* clean up */
643 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
644
645 return HPDF_OK;
646
647Exit:
648 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
649
650 if (ret != HPDF_OK) {
651 return ret;
652 }
653 return image->error->error_no;
654}
655
656
657static HPDF_STATUS
658PngBeforeWrite (HPDF_Dict obj)
659{
660 HPDF_STATUS ret;
661 png_byte header[HPDF_PNG_BYTES_TO_CHECK];
662 HPDF_UINT len = HPDF_PNG_BYTES_TO_CHECK;
663 HPDF_Stream png_data;
664 HPDF_String s;
665
666 HPDF_PTRACE ((" PngBeforeWrite\n"));
667
668 HPDF_MemStream_FreeData(obj->stream);
669
670 s = HPDF_Dict_GetItem (obj, "_FILE_NAME", HPDF_OCLASS_STRING);
671 if (!s)
672 return HPDF_SetError (obj->error, HPDF_MISSING_FILE_NAME_ENTRY, 0);
673
674 png_data = HPDF_FileReader_New (obj->mmgr, (const char *)(s->value));
675 if (!HPDF_Stream_Validate (png_data))
676 return obj->error->error_no;
677
678 HPDF_MemSet (header, 0x00, HPDF_PNG_BYTES_TO_CHECK);
679 ret = HPDF_Stream_Read (png_data, header, &len);
680 if (ret != HPDF_OK ||
681 png_sig_cmp (header, (png_size_t)0, HPDF_PNG_BYTES_TO_CHECK)) {
682 HPDF_Stream_Free(png_data);
683 return HPDF_SetError (obj->error, HPDF_INVALID_PNG_IMAGE, 0);
684 }
685
686 if ((ret = LoadPngData (obj, NULL, png_data, HPDF_FALSE)) != HPDF_OK) {
687 HPDF_Stream_Free(png_data);
688 return ret;
689 }
690
691 HPDF_Stream_Free(png_data);
692
693 return HPDF_OK;
694}
695
696
697static HPDF_STATUS
698PngAfterWrite (HPDF_Dict obj)
699{
700 HPDF_PTRACE ((" PngAfterWrite\n"));
701
702 HPDF_MemStream_FreeData(obj->stream);
703
704 return HPDF_OK;
705}
706
707
708#endif /* LIBHPDF_HAVE_NOPNGLIB */
709
710