Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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