tizen 2.4 release
[framework/graphics/cairo.git] / src / cairo-png.c
1 /* cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2003 University of Southern California
4  *
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.
12  *
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
18  *
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/
23  *
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.
27  *
28  * The Original Code is the cairo graphics library.
29  *
30  * The Initial Developer of the Original Code is University of Southern
31  * California.
32  *
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>
37  */
38
39 #include "cairoint.h"
40
41 #include "cairo-error-private.h"
42 #include "cairo-image-surface-private.h"
43 #include "cairo-output-stream-private.h"
44 #include "cairo-ttrace.h"
45
46 #include <stdio.h>
47 #include <errno.h>
48 #include <png.h>
49
50 /**
51  * SECTION:cairo-png
52  * @Title: PNG Support
53  * @Short_Description: Reading and writing PNG images
54  * @See_Also: #cairo_surface_t
55  *
56  * The PNG functions allow reading PNG images into image surfaces, and writing
57  * any surface to a PNG file.
58  *
59  * It is a toy API. It only offers very simple support for reading and
60  * writing PNG files, which is sufficient for testing and
61  * demonstration purposes. Applications which need more control over
62  * the generated PNG file should access the pixel data directly, using
63  * cairo_image_surface_get_data() or a backend-specific access
64  * function, and process it with another library, e.g. gdk-pixbuf or
65  * libpng.
66  **/
67
68 /**
69  * CAIRO_HAS_PNG_FUNCTIONS:
70  *
71  * Defined if the PNG functions are available.
72  * This macro can be used to conditionally compile code using the cairo
73  * PNG functions.
74  *
75  * Since: 1.0
76  **/
77
78 struct png_read_closure_t {
79     cairo_read_func_t            read_func;
80     void                        *closure;
81     cairo_output_stream_t       *png_data;
82 };
83
84
85 /* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
86 static void
87 unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
88 {
89     unsigned int i;
90
91     for (i = 0; i < row_info->rowbytes; i += 4) {
92         uint8_t *b = &data[i];
93         uint32_t pixel;
94         uint8_t  alpha;
95
96         memcpy (&pixel, b, sizeof (uint32_t));
97         alpha = (pixel & 0xff000000) >> 24;
98         if (alpha == 0) {
99             b[0] = b[1] = b[2] = b[3] = 0;
100         } else {
101             b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
102             b[1] = (((pixel & 0x00ff00) >>  8) * 255 + alpha / 2) / alpha;
103             b[2] = (((pixel & 0x0000ff) >>  0) * 255 + alpha / 2) / alpha;
104             b[3] = alpha;
105         }
106     }
107 }
108
109 /* Converts native endian xRGB => RGBx bytes */
110 static void
111 convert_data_to_bytes (png_structp png, png_row_infop row_info, png_bytep data)
112 {
113     unsigned int i;
114
115     for (i = 0; i < row_info->rowbytes; i += 4) {
116         uint8_t *b = &data[i];
117         uint32_t pixel;
118
119         memcpy (&pixel, b, sizeof (uint32_t));
120
121         b[0] = (pixel & 0xff0000) >> 16;
122         b[1] = (pixel & 0x00ff00) >>  8;
123         b[2] = (pixel & 0x0000ff) >>  0;
124         b[3] = 0;
125     }
126 }
127
128 /* Use a couple of simple error callbacks that do not print anything to
129  * stderr and rely on the user to check for errors via the #cairo_status_t
130  * return.
131  */
132 static void
133 png_simple_error_callback (png_structp png,
134                            png_const_charp error_msg)
135 {
136     cairo_status_t *error = png_get_error_ptr (png);
137
138     /* default to the most likely error */
139     if (*error == CAIRO_STATUS_SUCCESS)
140         *error = _cairo_error (CAIRO_STATUS_NO_MEMORY);
141
142 #ifdef PNG_SETJMP_SUPPORTED
143     longjmp (png_jmpbuf (png), 1);
144 #endif
145
146     /* if we get here, then we have to choice but to abort ... */
147 }
148
149 static void
150 png_simple_warning_callback (png_structp png,
151                              png_const_charp error_msg)
152 {
153     cairo_status_t *error = png_get_error_ptr (png);
154
155     /* default to the most likely error */
156     if (*error == CAIRO_STATUS_SUCCESS)
157         *error = _cairo_error (CAIRO_STATUS_NO_MEMORY);
158
159     /* png does not expect to abort and will try to tidy up after a warning */
160 }
161
162
163 /* Starting with libpng-1.2.30, we must explicitly specify an output_flush_fn.
164  * Otherwise, we will segfault if we are writing to a stream. */
165 static void
166 png_simple_output_flush_fn (png_structp png_ptr)
167 {
168 }
169
170 static cairo_status_t
171 write_png (cairo_surface_t      *surface,
172            png_rw_ptr           write_func,
173            void                 *closure)
174 {
175     CAIRO_TRACE_BEGIN (__func__);
176     int i;
177     cairo_int_status_t status;
178     cairo_image_surface_t *image;
179     cairo_image_surface_t * volatile clone;
180     void *image_extra;
181     png_struct *png;
182     png_info *info;
183     png_byte **volatile rows = NULL;
184     png_color_16 white;
185     int png_color_type;
186     int bpc;
187
188     status = _cairo_surface_acquire_source_image (surface,
189                                                   &image,
190                                                   &image_extra);
191
192     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
193         CAIRO_TRACE_END (__func__);
194         return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
195     }
196     else if (unlikely (status)) {
197         CAIRO_TRACE_END (__func__);
198         return status;
199     }
200
201     /* PNG complains about "Image width or height is zero in IHDR" */
202     if (image->width == 0 || image->height == 0) {
203         status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
204         goto BAIL1;
205     }
206
207     /* Handle the various fallback formats (e.g. low bit-depth XServers)
208      * by coercing them to a simpler format using pixman.
209      */
210     clone = _cairo_image_surface_coerce (image);
211     status = clone->base.status;
212     if (unlikely (status))
213         goto BAIL1;
214
215     rows = _cairo_malloc_ab (clone->height, sizeof (png_byte*));
216     if (unlikely (rows == NULL)) {
217         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
218         goto BAIL2;
219     }
220
221     for (i = 0; i < clone->height; i++)
222         rows[i] = (png_byte *) clone->data + i * clone->stride;
223
224     png = png_create_write_struct (PNG_LIBPNG_VER_STRING, &status,
225                                    png_simple_error_callback,
226                                    png_simple_warning_callback);
227     if (unlikely (png == NULL)) {
228         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
229         goto BAIL3;
230     }
231
232     info = png_create_info_struct (png);
233     if (unlikely (info == NULL)) {
234         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
235         goto BAIL4;
236     }
237
238 #ifdef PNG_SETJMP_SUPPORTED
239     if (setjmp (png_jmpbuf (png)))
240         goto BAIL4;
241 #endif
242
243     png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn);
244
245     switch (clone->format) {
246     case CAIRO_FORMAT_ARGB32:
247         bpc = 8;
248         if (_cairo_image_analyze_transparency (clone) == CAIRO_IMAGE_IS_OPAQUE)
249             png_color_type = PNG_COLOR_TYPE_RGB;
250         else
251             png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
252         break;
253     case CAIRO_FORMAT_RGB30:
254         bpc = 10;
255         png_color_type = PNG_COLOR_TYPE_RGB;
256         break;
257     case CAIRO_FORMAT_RGB24:
258         bpc = 8;
259         png_color_type = PNG_COLOR_TYPE_RGB;
260         break;
261     case CAIRO_FORMAT_A8:
262         bpc = 8;
263         png_color_type = PNG_COLOR_TYPE_GRAY;
264         break;
265     case CAIRO_FORMAT_A1:
266         bpc = 1;
267         png_color_type = PNG_COLOR_TYPE_GRAY;
268 #ifndef WORDS_BIGENDIAN
269         png_set_packswap (png);
270 #endif
271         break;
272     case CAIRO_FORMAT_INVALID:
273     case CAIRO_FORMAT_RGB16_565:
274     default:
275         status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
276         goto BAIL4;
277     }
278
279     png_set_IHDR (png, info,
280                   clone->width,
281                   clone->height, bpc,
282                   png_color_type,
283                   PNG_INTERLACE_NONE,
284                   PNG_COMPRESSION_TYPE_DEFAULT,
285                   PNG_FILTER_TYPE_DEFAULT);
286
287     white.gray = (1 << bpc) - 1;
288     white.red = white.blue = white.green = white.gray;
289     png_set_bKGD (png, info, &white);
290
291     if (0) { /* XXX extract meta-data from surface (i.e. creation date) */
292         png_time pt;
293
294         png_convert_from_time_t (&pt, time (NULL));
295         png_set_tIME (png, info, &pt);
296     }
297
298     /* We have to call png_write_info() before setting up the write
299      * transformation, since it stores data internally in 'png'
300      * that is needed for the write transformation functions to work.
301      */
302     png_write_info (png, info);
303
304     if (png_color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
305         png_set_write_user_transform_fn (png, unpremultiply_data);
306     } else if (png_color_type == PNG_COLOR_TYPE_RGB) {
307         png_set_write_user_transform_fn (png, convert_data_to_bytes);
308         png_set_filler (png, 0, PNG_FILLER_AFTER);
309     }
310
311     png_write_image (png, rows);
312     png_write_end (png, info);
313
314 BAIL4:
315     png_destroy_write_struct (&png, &info);
316 BAIL3:
317     free (rows);
318 BAIL2:
319     cairo_surface_destroy (&clone->base);
320 BAIL1:
321     _cairo_surface_release_source_image (surface, image, image_extra);
322
323     CAIRO_TRACE_END (__func__);
324     return status;
325 }
326
327 static void
328 stdio_write_func (png_structp png, png_bytep data, png_size_t size)
329 {
330     FILE *fp;
331
332     fp = png_get_io_ptr (png);
333     while (size) {
334         size_t ret = fwrite (data, 1, size, fp);
335         size -= ret;
336         data += ret;
337         if (size && ferror (fp)) {
338             cairo_status_t *error = png_get_error_ptr (png);
339             if (*error == CAIRO_STATUS_SUCCESS)
340                 *error = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
341             png_error (png, NULL);
342         }
343     }
344 }
345
346 /**
347  * cairo_surface_write_to_png:
348  * @surface: a #cairo_surface_t with pixel contents
349  * @filename: the name of a file to write to
350  *
351  * Writes the contents of @surface to a new file @filename as a PNG
352  * image.
353  *
354  * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
355  * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY if memory could not
356  * be allocated for the operation or
357  * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
358  * pixel contents, or %CAIRO_STATUS_WRITE_ERROR if an I/O error occurs
359  * while attempting to write the file.
360  *
361  * Since: 1.0
362  **/
363 cairo_status_t
364 cairo_surface_write_to_png (cairo_surface_t     *surface,
365                             const char          *filename)
366 {
367     FILE *fp;
368     cairo_status_t status;
369
370     if (surface->status)
371         return surface->status;
372
373     if (surface->finished)
374         return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
375
376     fp = fopen (filename, "wb");
377     if (fp == NULL) {
378         switch (errno) {
379         case ENOMEM:
380             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
381         default:
382             return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
383         }
384     }
385
386     status = write_png (surface, stdio_write_func, fp);
387
388     if (fclose (fp) && status == CAIRO_STATUS_SUCCESS)
389         status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
390
391     return status;
392 }
393
394 struct png_write_closure_t {
395     cairo_write_func_t           write_func;
396     void                        *closure;
397 };
398
399 static void
400 stream_write_func (png_structp png, png_bytep data, png_size_t size)
401 {
402     cairo_status_t status;
403     struct png_write_closure_t *png_closure;
404
405     png_closure = png_get_io_ptr (png);
406     status = png_closure->write_func (png_closure->closure, data, size);
407     if (unlikely (status)) {
408         cairo_status_t *error = png_get_error_ptr (png);
409         if (*error == CAIRO_STATUS_SUCCESS)
410             *error = status;
411         png_error (png, NULL);
412     }
413 }
414
415 /**
416  * cairo_surface_write_to_png_stream:
417  * @surface: a #cairo_surface_t with pixel contents
418  * @write_func: a #cairo_write_func_t
419  * @closure: closure data for the write function
420  *
421  * Writes the image surface to the write function.
422  *
423  * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
424  * successfully.  Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if
425  * memory could not be allocated for the operation,
426  * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
427  * pixel contents.
428  *
429  * Since: 1.0
430  **/
431 cairo_status_t
432 cairo_surface_write_to_png_stream (cairo_surface_t      *surface,
433                                    cairo_write_func_t   write_func,
434                                    void                 *closure)
435 {
436     CAIRO_TRACE_BEGIN (__func__);
437     struct png_write_closure_t png_closure;
438
439     if (surface->status) {
440         CAIRO_TRACE_END (__func__);
441         return surface->status;
442     }
443
444     if (surface->finished) {
445         CAIRO_TRACE_END (__func__);
446         return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
447     }
448
449     png_closure.write_func = write_func;
450     png_closure.closure = closure;
451
452     CAIRO_TRACE_END (__func__);
453     return write_png (surface, stream_write_func, &png_closure);
454 }
455 slim_hidden_def (cairo_surface_write_to_png_stream);
456
457 static inline int
458 multiply_alpha (int alpha, int color)
459 {
460     int temp = (alpha * color) + 0x80;
461     return ((temp + (temp >> 8)) >> 8);
462 }
463
464 /* Premultiplies data and converts RGBA bytes => native endian */
465 static void
466 premultiply_data (png_structp   png,
467                   png_row_infop row_info,
468                   png_bytep     data)
469 {
470     unsigned int i;
471
472     for (i = 0; i < row_info->rowbytes; i += 4) {
473         uint8_t *base  = &data[i];
474         uint8_t  alpha = base[3];
475         uint32_t p;
476
477         if (alpha == 0) {
478             p = 0;
479         } else {
480             uint8_t  red   = base[0];
481             uint8_t  green = base[1];
482             uint8_t  blue  = base[2];
483
484             if (alpha != 0xff) {
485                 red   = multiply_alpha (alpha, red);
486                 green = multiply_alpha (alpha, green);
487                 blue  = multiply_alpha (alpha, blue);
488             }
489             p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
490         }
491         memcpy (base, &p, sizeof (uint32_t));
492     }
493 }
494
495 /* Converts RGBx bytes to native endian xRGB */
496 static void
497 convert_bytes_to_data (png_structp png, png_row_infop row_info, png_bytep data)
498 {
499     unsigned int i;
500
501     for (i = 0; i < row_info->rowbytes; i += 4) {
502         uint8_t *base  = &data[i];
503         uint8_t  red   = base[0];
504         uint8_t  green = base[1];
505         uint8_t  blue  = base[2];
506         uint32_t pixel;
507
508         pixel = (0xff << 24) | (red << 16) | (green << 8) | (blue << 0);
509         memcpy (base, &pixel, sizeof (uint32_t));
510     }
511 }
512
513 static cairo_status_t
514 stdio_read_func (void *closure, unsigned char *data, unsigned int size)
515 {
516     FILE *file = closure;
517
518     while (size) {
519         size_t ret;
520
521         ret = fread (data, 1, size, file);
522         size -= ret;
523         data += ret;
524
525         if (size && (feof (file) || ferror (file)))
526             return _cairo_error (CAIRO_STATUS_READ_ERROR);
527     }
528
529     return CAIRO_STATUS_SUCCESS;
530 }
531
532 static void
533 stream_read_func (png_structp png, png_bytep data, png_size_t size)
534 {
535     cairo_status_t status;
536     struct png_read_closure_t *png_closure;
537
538     png_closure = png_get_io_ptr (png);
539     status = png_closure->read_func (png_closure->closure, data, size);
540     if (unlikely (status)) {
541         cairo_status_t *error = png_get_error_ptr (png);
542         if (*error == CAIRO_STATUS_SUCCESS)
543             *error = status;
544         png_error (png, NULL);
545     }
546
547     _cairo_output_stream_write (png_closure->png_data, data, size);
548 }
549
550 static cairo_surface_t *
551 read_png (struct png_read_closure_t *png_closure)
552 {
553     cairo_surface_t *surface;
554     png_struct *png = NULL;
555     png_info *info;
556     png_byte *data = NULL;
557     png_byte **row_pointers = NULL;
558     png_uint_32 png_width, png_height;
559     int depth, color_type, interlace, stride;
560     unsigned int i;
561     cairo_format_t format;
562     cairo_status_t status;
563     unsigned char *mime_data;
564     unsigned long mime_data_length;
565
566     png_closure->png_data = _cairo_memory_stream_create ();
567
568     /* XXX: Perhaps we'll want some other error handlers? */
569     png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
570                                   &status,
571                                   png_simple_error_callback,
572                                   png_simple_warning_callback);
573     if (unlikely (png == NULL)) {
574         surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
575         goto BAIL;
576     }
577
578     info = png_create_info_struct (png);
579     if (unlikely (info == NULL)) {
580         surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
581         goto BAIL;
582     }
583
584     png_set_read_fn (png, png_closure, stream_read_func);
585
586     status = CAIRO_STATUS_SUCCESS;
587 #ifdef PNG_SETJMP_SUPPORTED
588     if (setjmp (png_jmpbuf (png))) {
589         surface = _cairo_surface_create_in_error (status);
590         goto BAIL;
591     }
592 #endif
593
594     png_read_info (png, info);
595
596     png_get_IHDR (png, info,
597                   &png_width, &png_height, &depth,
598                   &color_type, &interlace, NULL, NULL);
599     if (unlikely (status)) { /* catch any early warnings */
600         surface = _cairo_surface_create_in_error (status);
601         goto BAIL;
602     }
603
604     /* convert palette/gray image to rgb */
605     if (color_type == PNG_COLOR_TYPE_PALETTE)
606         png_set_palette_to_rgb (png);
607
608     /* expand gray bit depth if needed */
609     if (color_type == PNG_COLOR_TYPE_GRAY) {
610 #if PNG_LIBPNG_VER >= 10209
611         png_set_expand_gray_1_2_4_to_8 (png);
612 #else
613         png_set_gray_1_2_4_to_8 (png);
614 #endif
615     }
616
617     /* transform transparency to alpha */
618     if (png_get_valid (png, info, PNG_INFO_tRNS))
619         png_set_tRNS_to_alpha (png);
620
621     if (depth == 16)
622         png_set_strip_16 (png);
623
624     if (depth < 8)
625         png_set_packing (png);
626
627     /* convert grayscale to RGB */
628     if (color_type == PNG_COLOR_TYPE_GRAY ||
629         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
630     {
631         png_set_gray_to_rgb (png);
632     }
633
634     if (interlace != PNG_INTERLACE_NONE)
635         png_set_interlace_handling (png);
636
637     png_set_filler (png, 0xff, PNG_FILLER_AFTER);
638
639     /* recheck header after setting EXPAND options */
640     png_read_update_info (png, info);
641     png_get_IHDR (png, info,
642                   &png_width, &png_height, &depth,
643                   &color_type, &interlace, NULL, NULL);
644     if (depth != 8 ||
645         ! (color_type == PNG_COLOR_TYPE_RGB ||
646            color_type == PNG_COLOR_TYPE_RGB_ALPHA))
647     {
648         surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_READ_ERROR));
649         goto BAIL;
650     }
651
652     switch (color_type) {
653         default:
654             ASSERT_NOT_REACHED;
655             /* fall-through just in case ;-) */
656
657         case PNG_COLOR_TYPE_RGB_ALPHA:
658             format = CAIRO_FORMAT_ARGB32;
659             png_set_read_user_transform_fn (png, premultiply_data);
660             break;
661
662         case PNG_COLOR_TYPE_RGB:
663             format = CAIRO_FORMAT_RGB24;
664             png_set_read_user_transform_fn (png, convert_bytes_to_data);
665             break;
666     }
667
668     stride = cairo_format_stride_for_width (format, png_width);
669     if (stride < 0) {
670         surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
671         goto BAIL;
672     }
673
674     data = _cairo_malloc_ab (png_height, stride);
675     if (unlikely (data == NULL)) {
676         surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
677         goto BAIL;
678     }
679
680     row_pointers = _cairo_malloc_ab (png_height, sizeof (char *));
681     if (unlikely (row_pointers == NULL)) {
682         surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
683         goto BAIL;
684     }
685
686     for (i = 0; i < png_height; i++)
687         row_pointers[i] = &data[i * stride];
688
689     png_read_image (png, row_pointers);
690     png_read_end (png, info);
691
692     if (unlikely (status)) { /* catch any late warnings - probably hit an error already */
693         surface = _cairo_surface_create_in_error (status);
694         goto BAIL;
695     }
696
697     surface = cairo_image_surface_create_for_data (data, format,
698                                                    png_width, png_height,
699                                                    stride);
700     if (surface->status)
701         goto BAIL;
702
703     _cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t*)surface);
704     data = NULL;
705
706     _cairo_debug_check_image_surface_is_defined (surface);
707
708     status = _cairo_memory_stream_destroy (png_closure->png_data,
709                                            &mime_data,
710                                            &mime_data_length);
711     png_closure->png_data = NULL;
712     if (unlikely (status)) {
713         cairo_surface_destroy (surface);
714         surface = _cairo_surface_create_in_error (status);
715         goto BAIL;
716     }
717
718     status = cairo_surface_set_mime_data (surface,
719                                           CAIRO_MIME_TYPE_PNG,
720                                           mime_data,
721                                           mime_data_length,
722                                           free,
723                                           mime_data);
724     if (unlikely (status)) {
725         free (mime_data);
726         cairo_surface_destroy (surface);
727         surface = _cairo_surface_create_in_error (status);
728         goto BAIL;
729     }
730
731  BAIL:
732     free (row_pointers);
733     free (data);
734     if (png != NULL)
735         png_destroy_read_struct (&png, &info, NULL);
736     if (png_closure->png_data != NULL) {
737         cairo_status_t status_ignored;
738
739         status_ignored = _cairo_output_stream_destroy (png_closure->png_data);
740     }
741
742     return surface;
743 }
744
745 /**
746  * cairo_image_surface_create_from_png:
747  * @filename: name of PNG file to load
748  *
749  * Creates a new image surface and initializes the contents to the
750  * given PNG file.
751  *
752  * Return value: a new #cairo_surface_t initialized with the contents
753  * of the PNG file, or a "nil" surface if any error occurred. A nil
754  * surface can be checked for with cairo_surface_status(surface) which
755  * may return one of the following values:
756  *
757  *      %CAIRO_STATUS_NO_MEMORY
758  *      %CAIRO_STATUS_FILE_NOT_FOUND
759  *      %CAIRO_STATUS_READ_ERROR
760  *
761  * Alternatively, you can allow errors to propagate through the drawing
762  * operations and check the status on the context upon completion
763  * using cairo_status().
764  *
765  * Since: 1.0
766  **/
767 cairo_surface_t *
768 cairo_image_surface_create_from_png (const char *filename)
769 {
770     struct png_read_closure_t png_closure;
771     cairo_surface_t *surface;
772
773     png_closure.closure = fopen (filename, "rb");
774     if (png_closure.closure == NULL) {
775         cairo_status_t status;
776         switch (errno) {
777         case ENOMEM:
778             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
779             break;
780         case ENOENT:
781             status = _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND);
782             break;
783         default:
784             status = _cairo_error (CAIRO_STATUS_READ_ERROR);
785             break;
786         }
787         return _cairo_surface_create_in_error (status);
788     }
789
790     png_closure.read_func = stdio_read_func;
791
792     surface = read_png (&png_closure);
793
794     fclose (png_closure.closure);
795
796     return surface;
797 }
798
799 /**
800  * cairo_image_surface_create_from_png_stream:
801  * @read_func: function called to read the data of the file
802  * @closure: data to pass to @read_func.
803  *
804  * Creates a new image surface from PNG data read incrementally
805  * via the @read_func function.
806  *
807  * Return value: a new #cairo_surface_t initialized with the contents
808  * of the PNG file or a "nil" surface if the data read is not a valid PNG image
809  * or memory could not be allocated for the operation.  A nil
810  * surface can be checked for with cairo_surface_status(surface) which
811  * may return one of the following values:
812  *
813  *      %CAIRO_STATUS_NO_MEMORY
814  *      %CAIRO_STATUS_READ_ERROR
815  *
816  * Alternatively, you can allow errors to propagate through the drawing
817  * operations and check the status on the context upon completion
818  * using cairo_status().
819  *
820  * Since: 1.0
821  **/
822 cairo_surface_t *
823 cairo_image_surface_create_from_png_stream (cairo_read_func_t   read_func,
824                                             void                *closure)
825 {
826     struct png_read_closure_t png_closure;
827
828     png_closure.read_func = read_func;
829     png_closure.closure = closure;
830
831     return read_png (&png_closure);
832 }