beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-png.c
blob068617d588d8b0cc3947024c409dfaac95c10803
1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2003 University of Southern California
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is University of Southern
31 * California.
33 * Contributor(s):
34 * Carl D. Worth <cworth@cworth.org>
35 * Kristian Høgsberg <krh@redhat.com>
36 * Chris Wilson <chris@chris-wilson.co.uk>
39 #include "cairoint.h"
41 #include "cairo-error-private.h"
42 #include "cairo-image-surface-private.h"
43 #include "cairo-output-stream-private.h"
45 #include <stdio.h>
46 #include <errno.h>
47 #include <png.h>
49 /**
50 * SECTION:cairo-png
51 * @Title: PNG Support
52 * @Short_Description: Reading and writing PNG images
53 * @See_Also: #cairo_surface_t
55 * The PNG functions allow reading PNG images into image surfaces, and writing
56 * any surface to a PNG file.
58 * It is a toy API. It only offers very simple support for reading and
59 * writing PNG files, which is sufficient for testing and
60 * demonstration purposes. Applications which need more control over
61 * the generated PNG file should access the pixel data directly, using
62 * cairo_image_surface_get_data() or a backend-specific access
63 * function, and process it with another library, e.g. gdk-pixbuf or
64 * libpng.
65 **/
67 /**
68 * CAIRO_HAS_PNG_FUNCTIONS:
70 * Defined if the PNG functions are available.
71 * This macro can be used to conditionally compile code using the cairo
72 * PNG functions.
74 * Since: 1.0
75 **/
77 struct png_read_closure_t {
78 cairo_read_func_t read_func;
79 void *closure;
80 cairo_output_stream_t *png_data;
84 /* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
85 static void
86 unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
88 unsigned int i;
90 for (i = 0; i < row_info->rowbytes; i += 4) {
91 uint8_t *b = &data[i];
92 uint32_t pixel;
93 uint8_t alpha;
95 memcpy (&pixel, b, sizeof (uint32_t));
96 alpha = (pixel & 0xff000000) >> 24;
97 if (alpha == 0) {
98 b[0] = b[1] = b[2] = b[3] = 0;
99 } else {
100 b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
101 b[1] = (((pixel & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
102 b[2] = (((pixel & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
103 b[3] = alpha;
108 /* Converts native endian xRGB => RGBx bytes */
109 static void
110 convert_data_to_bytes (png_structp png, png_row_infop row_info, png_bytep data)
112 unsigned int i;
114 for (i = 0; i < row_info->rowbytes; i += 4) {
115 uint8_t *b = &data[i];
116 uint32_t pixel;
118 memcpy (&pixel, b, sizeof (uint32_t));
120 b[0] = (pixel & 0xff0000) >> 16;
121 b[1] = (pixel & 0x00ff00) >> 8;
122 b[2] = (pixel & 0x0000ff) >> 0;
123 b[3] = 0;
127 /* Use a couple of simple error callbacks that do not print anything to
128 * stderr and rely on the user to check for errors via the #cairo_status_t
129 * return.
131 static void
132 png_simple_error_callback (png_structp png,
133 png_const_charp error_msg)
135 cairo_status_t *error = png_get_error_ptr (png);
137 /* default to the most likely error */
138 if (*error == CAIRO_STATUS_SUCCESS)
139 *error = _cairo_error (CAIRO_STATUS_NO_MEMORY);
141 #ifdef PNG_SETJMP_SUPPORTED
142 longjmp (png_jmpbuf (png), 1);
143 #endif
145 /* if we get here, then we have to choice but to abort ... */
148 static void
149 png_simple_warning_callback (png_structp png,
150 png_const_charp error_msg)
152 /* png does not expect to abort and will try to tidy up and continue
153 * loading the image after a warning. So we also want to return the
154 * (incorrect?) surface.
156 * We use our own warning callback to squelch any attempts by libpng
157 * to write to stderr as we may not be in control of that output.
162 /* Starting with libpng-1.2.30, we must explicitly specify an output_flush_fn.
163 * Otherwise, we will segfault if we are writing to a stream. */
164 static void
165 png_simple_output_flush_fn (png_structp png_ptr)
169 static cairo_status_t
170 write_png (cairo_surface_t *surface,
171 png_rw_ptr write_func,
172 void *closure)
174 int i;
175 cairo_int_status_t status;
176 cairo_image_surface_t *image;
177 cairo_image_surface_t * volatile clone;
178 void *image_extra;
179 png_struct *png;
180 png_info *info;
181 png_byte **volatile rows = NULL;
182 png_color_16 white;
183 int png_color_type;
184 int bpc;
186 status = _cairo_surface_acquire_source_image (surface,
187 &image,
188 &image_extra);
190 if (status == CAIRO_INT_STATUS_UNSUPPORTED)
191 return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
192 else if (unlikely (status))
193 return status;
195 /* PNG complains about "Image width or height is zero in IHDR" */
196 if (image->width == 0 || image->height == 0) {
197 status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
198 goto BAIL1;
201 /* Handle the various fallback formats (e.g. low bit-depth XServers)
202 * by coercing them to a simpler format using pixman.
204 clone = _cairo_image_surface_coerce (image);
205 status = clone->base.status;
206 if (unlikely (status))
207 goto BAIL1;
209 rows = _cairo_malloc_ab (clone->height, sizeof (png_byte*));
210 if (unlikely (rows == NULL)) {
211 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
212 goto BAIL2;
215 for (i = 0; i < clone->height; i++)
216 rows[i] = (png_byte *) clone->data + i * clone->stride;
218 png = png_create_write_struct (PNG_LIBPNG_VER_STRING, &status,
219 png_simple_error_callback,
220 png_simple_warning_callback);
221 if (unlikely (png == NULL)) {
222 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
223 goto BAIL3;
226 info = png_create_info_struct (png);
227 if (unlikely (info == NULL)) {
228 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
229 goto BAIL4;
232 #ifdef PNG_SETJMP_SUPPORTED
233 if (setjmp (png_jmpbuf (png)))
234 goto BAIL4;
235 #endif
237 png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn);
239 switch (clone->format) {
240 case CAIRO_FORMAT_ARGB32:
241 bpc = 8;
242 if (_cairo_image_analyze_transparency (clone) == CAIRO_IMAGE_IS_OPAQUE)
243 png_color_type = PNG_COLOR_TYPE_RGB;
244 else
245 png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
246 break;
247 case CAIRO_FORMAT_RGB30:
248 bpc = 10;
249 png_color_type = PNG_COLOR_TYPE_RGB;
250 break;
251 case CAIRO_FORMAT_RGB24:
252 bpc = 8;
253 png_color_type = PNG_COLOR_TYPE_RGB;
254 break;
255 case CAIRO_FORMAT_A8:
256 bpc = 8;
257 png_color_type = PNG_COLOR_TYPE_GRAY;
258 break;
259 case CAIRO_FORMAT_A1:
260 bpc = 1;
261 png_color_type = PNG_COLOR_TYPE_GRAY;
262 #ifndef WORDS_BIGENDIAN
263 png_set_packswap (png);
264 #endif
265 break;
266 case CAIRO_FORMAT_INVALID:
267 case CAIRO_FORMAT_RGB16_565:
268 default:
269 status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
270 goto BAIL4;
273 png_set_IHDR (png, info,
274 clone->width,
275 clone->height, bpc,
276 png_color_type,
277 PNG_INTERLACE_NONE,
278 PNG_COMPRESSION_TYPE_DEFAULT,
279 PNG_FILTER_TYPE_DEFAULT);
281 white.gray = (1 << bpc) - 1;
282 white.red = white.blue = white.green = white.gray;
283 png_set_bKGD (png, info, &white);
285 if (0) { /* XXX extract meta-data from surface (i.e. creation date) */
286 png_time pt;
288 png_convert_from_time_t (&pt, time (NULL));
289 png_set_tIME (png, info, &pt);
292 /* We have to call png_write_info() before setting up the write
293 * transformation, since it stores data internally in 'png'
294 * that is needed for the write transformation functions to work.
296 png_write_info (png, info);
298 if (png_color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
299 png_set_write_user_transform_fn (png, unpremultiply_data);
300 } else if (png_color_type == PNG_COLOR_TYPE_RGB) {
301 png_set_write_user_transform_fn (png, convert_data_to_bytes);
302 png_set_filler (png, 0, PNG_FILLER_AFTER);
305 png_write_image (png, rows);
306 png_write_end (png, info);
308 BAIL4:
309 png_destroy_write_struct (&png, &info);
310 BAIL3:
311 free (rows);
312 BAIL2:
313 cairo_surface_destroy (&clone->base);
314 BAIL1:
315 _cairo_surface_release_source_image (surface, image, image_extra);
317 return status;
320 static void
321 stdio_write_func (png_structp png, png_bytep data, png_size_t size)
323 FILE *fp;
325 fp = png_get_io_ptr (png);
326 while (size) {
327 size_t ret = fwrite (data, 1, size, fp);
328 size -= ret;
329 data += ret;
330 if (size && ferror (fp)) {
331 cairo_status_t *error = png_get_error_ptr (png);
332 if (*error == CAIRO_STATUS_SUCCESS)
333 *error = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
334 png_error (png, NULL);
340 * cairo_surface_write_to_png:
341 * @surface: a #cairo_surface_t with pixel contents
342 * @filename: the name of a file to write to
344 * Writes the contents of @surface to a new file @filename as a PNG
345 * image.
347 * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
348 * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY if memory could not
349 * be allocated for the operation or
350 * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
351 * pixel contents, or %CAIRO_STATUS_WRITE_ERROR if an I/O error occurs
352 * while attempting to write the file.
354 * Since: 1.0
356 cairo_status_t
357 cairo_surface_write_to_png (cairo_surface_t *surface,
358 const char *filename)
360 FILE *fp;
361 cairo_status_t status;
363 if (surface->status)
364 return surface->status;
366 if (surface->finished)
367 return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
369 fp = fopen (filename, "wb");
370 if (fp == NULL) {
371 switch (errno) {
372 case ENOMEM:
373 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
374 default:
375 return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
379 status = write_png (surface, stdio_write_func, fp);
381 if (fclose (fp) && status == CAIRO_STATUS_SUCCESS)
382 status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
384 return status;
387 struct png_write_closure_t {
388 cairo_write_func_t write_func;
389 void *closure;
392 static void
393 stream_write_func (png_structp png, png_bytep data, png_size_t size)
395 cairo_status_t status;
396 struct png_write_closure_t *png_closure;
398 png_closure = png_get_io_ptr (png);
399 status = png_closure->write_func (png_closure->closure, data, size);
400 if (unlikely (status)) {
401 cairo_status_t *error = png_get_error_ptr (png);
402 if (*error == CAIRO_STATUS_SUCCESS)
403 *error = status;
404 png_error (png, NULL);
409 * cairo_surface_write_to_png_stream:
410 * @surface: a #cairo_surface_t with pixel contents
411 * @write_func: a #cairo_write_func_t
412 * @closure: closure data for the write function
414 * Writes the image surface to the write function.
416 * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
417 * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if
418 * memory could not be allocated for the operation,
419 * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
420 * pixel contents.
422 * Since: 1.0
424 cairo_status_t
425 cairo_surface_write_to_png_stream (cairo_surface_t *surface,
426 cairo_write_func_t write_func,
427 void *closure)
429 struct png_write_closure_t png_closure;
431 if (surface->status)
432 return surface->status;
434 if (surface->finished)
435 return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
437 png_closure.write_func = write_func;
438 png_closure.closure = closure;
440 return write_png (surface, stream_write_func, &png_closure);
442 slim_hidden_def (cairo_surface_write_to_png_stream);
444 static inline int
445 multiply_alpha (int alpha, int color)
447 int temp = (alpha * color) + 0x80;
448 return ((temp + (temp >> 8)) >> 8);
451 /* Premultiplies data and converts RGBA bytes => native endian */
452 static void
453 premultiply_data (png_structp png,
454 png_row_infop row_info,
455 png_bytep data)
457 unsigned int i;
459 for (i = 0; i < row_info->rowbytes; i += 4) {
460 uint8_t *base = &data[i];
461 uint8_t alpha = base[3];
462 uint32_t p;
464 if (alpha == 0) {
465 p = 0;
466 } else {
467 uint8_t red = base[0];
468 uint8_t green = base[1];
469 uint8_t blue = base[2];
471 if (alpha != 0xff) {
472 red = multiply_alpha (alpha, red);
473 green = multiply_alpha (alpha, green);
474 blue = multiply_alpha (alpha, blue);
476 p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
478 memcpy (base, &p, sizeof (uint32_t));
482 /* Converts RGBx bytes to native endian xRGB */
483 static void
484 convert_bytes_to_data (png_structp png, png_row_infop row_info, png_bytep data)
486 unsigned int i;
488 for (i = 0; i < row_info->rowbytes; i += 4) {
489 uint8_t *base = &data[i];
490 uint8_t red = base[0];
491 uint8_t green = base[1];
492 uint8_t blue = base[2];
493 uint32_t pixel;
495 pixel = (0xff << 24) | (red << 16) | (green << 8) | (blue << 0);
496 memcpy (base, &pixel, sizeof (uint32_t));
500 static cairo_status_t
501 stdio_read_func (void *closure, unsigned char *data, unsigned int size)
503 FILE *file = closure;
505 while (size) {
506 size_t ret;
508 ret = fread (data, 1, size, file);
509 size -= ret;
510 data += ret;
512 if (size && (feof (file) || ferror (file)))
513 return _cairo_error (CAIRO_STATUS_READ_ERROR);
516 return CAIRO_STATUS_SUCCESS;
519 static void
520 stream_read_func (png_structp png, png_bytep data, png_size_t size)
522 cairo_status_t status;
523 struct png_read_closure_t *png_closure;
525 png_closure = png_get_io_ptr (png);
526 status = png_closure->read_func (png_closure->closure, data, size);
527 if (unlikely (status)) {
528 cairo_status_t *error = png_get_error_ptr (png);
529 if (*error == CAIRO_STATUS_SUCCESS)
530 *error = status;
531 png_error (png, NULL);
534 _cairo_output_stream_write (png_closure->png_data, data, size);
537 static cairo_surface_t *
538 read_png (struct png_read_closure_t *png_closure)
540 cairo_surface_t *surface;
541 png_struct *png = NULL;
542 png_info *info;
543 png_byte *data = NULL;
544 png_byte **row_pointers = NULL;
545 png_uint_32 png_width, png_height;
546 int depth, color_type, interlace, stride;
547 unsigned int i;
548 cairo_format_t format;
549 cairo_status_t status;
550 unsigned char *mime_data;
551 unsigned long mime_data_length;
553 png_closure->png_data = _cairo_memory_stream_create ();
555 /* XXX: Perhaps we'll want some other error handlers? */
556 png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
557 &status,
558 png_simple_error_callback,
559 png_simple_warning_callback);
560 if (unlikely (png == NULL)) {
561 surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
562 goto BAIL;
565 info = png_create_info_struct (png);
566 if (unlikely (info == NULL)) {
567 surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
568 goto BAIL;
571 png_set_read_fn (png, png_closure, stream_read_func);
573 status = CAIRO_STATUS_SUCCESS;
574 #ifdef PNG_SETJMP_SUPPORTED
575 if (setjmp (png_jmpbuf (png))) {
576 surface = _cairo_surface_create_in_error (status);
577 goto BAIL;
579 #endif
581 png_read_info (png, info);
583 png_get_IHDR (png, info,
584 &png_width, &png_height, &depth,
585 &color_type, &interlace, NULL, NULL);
586 if (unlikely (status)) { /* catch any early warnings */
587 surface = _cairo_surface_create_in_error (status);
588 goto BAIL;
591 /* convert palette/gray image to rgb */
592 if (color_type == PNG_COLOR_TYPE_PALETTE)
593 png_set_palette_to_rgb (png);
595 /* expand gray bit depth if needed */
596 if (color_type == PNG_COLOR_TYPE_GRAY) {
597 #if PNG_LIBPNG_VER >= 10209
598 png_set_expand_gray_1_2_4_to_8 (png);
599 #else
600 png_set_gray_1_2_4_to_8 (png);
601 #endif
604 /* transform transparency to alpha */
605 if (png_get_valid (png, info, PNG_INFO_tRNS))
606 png_set_tRNS_to_alpha (png);
608 if (depth == 16)
609 png_set_strip_16 (png);
611 if (depth < 8)
612 png_set_packing (png);
614 /* convert grayscale to RGB */
615 if (color_type == PNG_COLOR_TYPE_GRAY ||
616 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
618 png_set_gray_to_rgb (png);
621 if (interlace != PNG_INTERLACE_NONE)
622 png_set_interlace_handling (png);
624 png_set_filler (png, 0xff, PNG_FILLER_AFTER);
626 /* recheck header after setting EXPAND options */
627 png_read_update_info (png, info);
628 png_get_IHDR (png, info,
629 &png_width, &png_height, &depth,
630 &color_type, &interlace, NULL, NULL);
631 if (depth != 8 ||
632 ! (color_type == PNG_COLOR_TYPE_RGB ||
633 color_type == PNG_COLOR_TYPE_RGB_ALPHA))
635 surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_READ_ERROR));
636 goto BAIL;
639 switch (color_type) {
640 default:
641 ASSERT_NOT_REACHED;
642 /* fall-through just in case ;-) */
644 case PNG_COLOR_TYPE_RGB_ALPHA:
645 format = CAIRO_FORMAT_ARGB32;
646 png_set_read_user_transform_fn (png, premultiply_data);
647 break;
649 case PNG_COLOR_TYPE_RGB:
650 format = CAIRO_FORMAT_RGB24;
651 png_set_read_user_transform_fn (png, convert_bytes_to_data);
652 break;
655 stride = cairo_format_stride_for_width (format, png_width);
656 if (stride < 0) {
657 surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
658 goto BAIL;
661 data = _cairo_malloc_ab (png_height, stride);
662 if (unlikely (data == NULL)) {
663 surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
664 goto BAIL;
667 row_pointers = _cairo_malloc_ab (png_height, sizeof (char *));
668 if (unlikely (row_pointers == NULL)) {
669 surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
670 goto BAIL;
673 for (i = 0; i < png_height; i++)
674 row_pointers[i] = &data[i * stride];
676 png_read_image (png, row_pointers);
677 png_read_end (png, info);
679 if (unlikely (status)) { /* catch any late warnings - probably hit an error already */
680 surface = _cairo_surface_create_in_error (status);
681 goto BAIL;
684 surface = cairo_image_surface_create_for_data (data, format,
685 png_width, png_height,
686 stride);
687 if (surface->status)
688 goto BAIL;
690 _cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t*)surface);
691 data = NULL;
693 _cairo_debug_check_image_surface_is_defined (surface);
695 status = _cairo_memory_stream_destroy (png_closure->png_data,
696 &mime_data,
697 &mime_data_length);
698 png_closure->png_data = NULL;
699 if (unlikely (status)) {
700 cairo_surface_destroy (surface);
701 surface = _cairo_surface_create_in_error (status);
702 goto BAIL;
705 status = cairo_surface_set_mime_data (surface,
706 CAIRO_MIME_TYPE_PNG,
707 mime_data,
708 mime_data_length,
709 free,
710 mime_data);
711 if (unlikely (status)) {
712 free (mime_data);
713 cairo_surface_destroy (surface);
714 surface = _cairo_surface_create_in_error (status);
715 goto BAIL;
718 BAIL:
719 free (row_pointers);
720 free (data);
721 if (png != NULL)
722 png_destroy_read_struct (&png, &info, NULL);
723 if (png_closure->png_data != NULL) {
724 cairo_status_t status_ignored;
726 status_ignored = _cairo_output_stream_destroy (png_closure->png_data);
729 return surface;
733 * cairo_image_surface_create_from_png:
734 * @filename: name of PNG file to load
736 * Creates a new image surface and initializes the contents to the
737 * given PNG file.
739 * Return value: a new #cairo_surface_t initialized with the contents
740 * of the PNG file, or a "nil" surface if any error occurred. A nil
741 * surface can be checked for with cairo_surface_status(surface) which
742 * may return one of the following values:
744 * %CAIRO_STATUS_NO_MEMORY
745 * %CAIRO_STATUS_FILE_NOT_FOUND
746 * %CAIRO_STATUS_READ_ERROR
748 * Alternatively, you can allow errors to propagate through the drawing
749 * operations and check the status on the context upon completion
750 * using cairo_status().
752 * Since: 1.0
754 cairo_surface_t *
755 cairo_image_surface_create_from_png (const char *filename)
757 struct png_read_closure_t png_closure;
758 cairo_surface_t *surface;
760 png_closure.closure = fopen (filename, "rb");
761 if (png_closure.closure == NULL) {
762 cairo_status_t status;
763 switch (errno) {
764 case ENOMEM:
765 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
766 break;
767 case ENOENT:
768 status = _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND);
769 break;
770 default:
771 status = _cairo_error (CAIRO_STATUS_READ_ERROR);
772 break;
774 return _cairo_surface_create_in_error (status);
777 png_closure.read_func = stdio_read_func;
779 surface = read_png (&png_closure);
781 fclose (png_closure.closure);
783 return surface;
787 * cairo_image_surface_create_from_png_stream:
788 * @read_func: function called to read the data of the file
789 * @closure: data to pass to @read_func.
791 * Creates a new image surface from PNG data read incrementally
792 * via the @read_func function.
794 * Return value: a new #cairo_surface_t initialized with the contents
795 * of the PNG file or a "nil" surface if the data read is not a valid PNG image
796 * or memory could not be allocated for the operation. A nil
797 * surface can be checked for with cairo_surface_status(surface) which
798 * may return one of the following values:
800 * %CAIRO_STATUS_NO_MEMORY
801 * %CAIRO_STATUS_READ_ERROR
803 * Alternatively, you can allow errors to propagate through the drawing
804 * operations and check the status on the context upon completion
805 * using cairo_status().
807 * Since: 1.0
809 cairo_surface_t *
810 cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
811 void *closure)
813 struct png_read_closure_t png_closure;
815 png_closure.read_func = read_func;
816 png_closure.closure = closure;
818 return read_png (&png_closure);