Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | 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-image-surface-private.h"
  43. #include "cairo-output-stream-private.h"
  44.  
  45. #include <stdio.h>
  46. #include <errno.h>
  47. #include <png.h>
  48.  
  49. /**
  50.  * SECTION:cairo-png
  51.  * @Title: PNG Support
  52.  * @Short_Description: Reading and writing PNG images
  53.  * @See_Also: #cairo_surface_t
  54.  *
  55.  * The PNG functions allow reading PNG images into image surfaces, and writing
  56.  * any surface to a PNG file.
  57.  *
  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.  **/
  66.  
  67. /**
  68.  * CAIRO_HAS_PNG_FUNCTIONS:
  69.  *
  70.  * Defined if the PNG functions are available.
  71.  * This macro can be used to conditionally compile code using the cairo
  72.  * PNG functions.
  73.  *
  74.  * Since: 1.0
  75.  **/
  76.  
  77. struct png_read_closure_t {
  78.     cairo_read_func_t            read_func;
  79.     void                        *closure;
  80.     cairo_output_stream_t       *png_data;
  81. };
  82.  
  83.  
  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)
  87. {
  88.     unsigned int i;
  89.  
  90.     for (i = 0; i < row_info->rowbytes; i += 4) {
  91.         uint8_t *b = &data[i];
  92.         uint32_t pixel;
  93.         uint8_t  alpha;
  94.  
  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;
  104.         }
  105.     }
  106. }
  107.  
  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)
  111. {
  112.     unsigned int i;
  113.  
  114.     for (i = 0; i < row_info->rowbytes; i += 4) {
  115.         uint8_t *b = &data[i];
  116.         uint32_t pixel;
  117.  
  118.         memcpy (&pixel, b, sizeof (uint32_t));
  119.  
  120.         b[0] = (pixel & 0xff0000) >> 16;
  121.         b[1] = (pixel & 0x00ff00) >>  8;
  122.         b[2] = (pixel & 0x0000ff) >>  0;
  123.         b[3] = 0;
  124.     }
  125. }
  126.  
  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.
  130.  */
  131. static void
  132. png_simple_error_callback (png_structp png,
  133.                            png_const_charp error_msg)
  134. {
  135.     cairo_status_t *error = png_get_error_ptr (png);
  136.  
  137.     /* default to the most likely error */
  138.     if (*error == CAIRO_STATUS_SUCCESS)
  139.         *error = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  140.  
  141. #ifdef PNG_SETJMP_SUPPORTED
  142.     longjmp (png_jmpbuf (png), 1);
  143. #endif
  144.  
  145.     /* if we get here, then we have to choice but to abort ... */
  146. }
  147.  
  148. static void
  149. png_simple_warning_callback (png_structp png,
  150.                              png_const_charp error_msg)
  151. {
  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.
  155.      *
  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.
  158.      */
  159. }
  160.  
  161.  
  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)
  166. {
  167. }
  168.  
  169. static cairo_status_t
  170. write_png (cairo_surface_t      *surface,
  171.            png_rw_ptr           write_func,
  172.            void                 *closure)
  173. {
  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;
  185.  
  186.     status = _cairo_surface_acquire_source_image (surface,
  187.                                                   &image,
  188.                                                   &image_extra);
  189.  
  190.     if (status == CAIRO_INT_STATUS_UNSUPPORTED)
  191.         return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
  192.     else if (unlikely (status))
  193.         return status;
  194.  
  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;
  199.     }
  200.  
  201.     /* Handle the various fallback formats (e.g. low bit-depth XServers)
  202.      * by coercing them to a simpler format using pixman.
  203.      */
  204.     clone = _cairo_image_surface_coerce (image);
  205.     status = clone->base.status;
  206.     if (unlikely (status))
  207.         goto BAIL1;
  208.  
  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;
  213.     }
  214.  
  215.     for (i = 0; i < clone->height; i++)
  216.         rows[i] = (png_byte *) clone->data + i * clone->stride;
  217.  
  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;
  224.     }
  225.  
  226.     info = png_create_info_struct (png);
  227.     if (unlikely (info == NULL)) {
  228.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  229.         goto BAIL4;
  230.     }
  231.  
  232. #ifdef PNG_SETJMP_SUPPORTED
  233.     if (setjmp (png_jmpbuf (png)))
  234.         goto BAIL4;
  235. #endif
  236.  
  237.     png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn);
  238.  
  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;
  271.     }
  272.  
  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);
  280.  
  281.     white.gray = (1 << bpc) - 1;
  282.     white.red = white.blue = white.green = white.gray;
  283.     png_set_bKGD (png, info, &white);
  284.  
  285.     if (0) { /* XXX extract meta-data from surface (i.e. creation date) */
  286.         png_time pt;
  287.  
  288.         png_convert_from_time_t (&pt, time (NULL));
  289.         png_set_tIME (png, info, &pt);
  290.     }
  291.  
  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.
  295.      */
  296.     png_write_info (png, info);
  297.  
  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);
  303.     }
  304.  
  305.     png_write_image (png, rows);
  306.     png_write_end (png, info);
  307.  
  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);
  316.  
  317.     return status;
  318. }
  319.  
  320. static void
  321. stdio_write_func (png_structp png, png_bytep data, png_size_t size)
  322. {
  323.     FILE *fp;
  324.  
  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);
  335.         }
  336.     }
  337. }
  338.  
  339. /**
  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
  343.  *
  344.  * Writes the contents of @surface to a new file @filename as a PNG
  345.  * image.
  346.  *
  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.
  353.  *
  354.  * Since: 1.0
  355.  **/
  356. cairo_status_t
  357. cairo_surface_write_to_png (cairo_surface_t     *surface,
  358.                             const char          *filename)
  359. {
  360.     FILE *fp;
  361.     cairo_status_t status;
  362.  
  363.     if (surface->status)
  364.         return surface->status;
  365.  
  366.     if (surface->finished)
  367.         return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
  368.  
  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);
  376.         }
  377.     }
  378.  
  379.     status = write_png (surface, stdio_write_func, fp);
  380.  
  381.     if (fclose (fp) && status == CAIRO_STATUS_SUCCESS)
  382.         status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
  383.  
  384.     return status;
  385. }
  386.  
  387. struct png_write_closure_t {
  388.     cairo_write_func_t           write_func;
  389.     void                        *closure;
  390. };
  391.  
  392. static void
  393. stream_write_func (png_structp png, png_bytep data, png_size_t size)
  394. {
  395.     cairo_status_t status;
  396.     struct png_write_closure_t *png_closure;
  397.  
  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);
  405.     }
  406. }
  407.  
  408. /**
  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
  413.  *
  414.  * Writes the image surface to the write function.
  415.  *
  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.
  421.  *
  422.  * Since: 1.0
  423.  **/
  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)
  428. {
  429.     struct png_write_closure_t png_closure;
  430.  
  431.     if (surface->status)
  432.         return surface->status;
  433.  
  434.     if (surface->finished)
  435.         return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
  436.  
  437.     png_closure.write_func = write_func;
  438.     png_closure.closure = closure;
  439.  
  440.     return write_png (surface, stream_write_func, &png_closure);
  441. }
  442. slim_hidden_def (cairo_surface_write_to_png_stream);
  443.  
  444. static inline int
  445. multiply_alpha (int alpha, int color)
  446. {
  447.     int temp = (alpha * color) + 0x80;
  448.     return ((temp + (temp >> 8)) >> 8);
  449. }
  450.  
  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)
  456. {
  457.     unsigned int i;
  458.  
  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;
  463.  
  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];
  470.  
  471.             if (alpha != 0xff) {
  472.                 red   = multiply_alpha (alpha, red);
  473.                 green = multiply_alpha (alpha, green);
  474.                 blue  = multiply_alpha (alpha, blue);
  475.             }
  476.             p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
  477.         }
  478.         memcpy (base, &p, sizeof (uint32_t));
  479.     }
  480. }
  481.  
  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)
  485. {
  486.     unsigned int i;
  487.  
  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;
  494.  
  495.         pixel = (0xff << 24) | (red << 16) | (green << 8) | (blue << 0);
  496.         memcpy (base, &pixel, sizeof (uint32_t));
  497.     }
  498. }
  499.  
  500. static cairo_status_t
  501. stdio_read_func (void *closure, unsigned char *data, unsigned int size)
  502. {
  503.     FILE *file = closure;
  504.  
  505.     while (size) {
  506.         size_t ret;
  507.  
  508.         ret = fread (data, 1, size, file);
  509.         size -= ret;
  510.         data += ret;
  511.  
  512.         if (size && (feof (file) || ferror (file)))
  513.             return _cairo_error (CAIRO_STATUS_READ_ERROR);
  514.     }
  515.  
  516.     return CAIRO_STATUS_SUCCESS;
  517. }
  518.  
  519. static void
  520. stream_read_func (png_structp png, png_bytep data, png_size_t size)
  521. {
  522.     cairo_status_t status;
  523.     struct png_read_closure_t *png_closure;
  524.  
  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);
  532.     }
  533.  
  534.     _cairo_output_stream_write (png_closure->png_data, data, size);
  535. }
  536.  
  537. static cairo_surface_t *
  538. read_png (struct png_read_closure_t *png_closure)
  539. {
  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;
  552.  
  553.     png_closure->png_data = _cairo_memory_stream_create ();
  554.  
  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;
  563.     }
  564.  
  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;
  569.     }
  570.  
  571.     png_set_read_fn (png, png_closure, stream_read_func);
  572.  
  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;
  578.     }
  579. #endif
  580.  
  581.     png_read_info (png, info);
  582.  
  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;
  589.     }
  590.  
  591.     /* convert palette/gray image to rgb */
  592.     if (color_type == PNG_COLOR_TYPE_PALETTE)
  593.         png_set_palette_to_rgb (png);
  594.  
  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
  602.     }
  603.  
  604.     /* transform transparency to alpha */
  605.     if (png_get_valid (png, info, PNG_INFO_tRNS))
  606.         png_set_tRNS_to_alpha (png);
  607.  
  608.     if (depth == 16)
  609.         png_set_strip_16 (png);
  610.  
  611.     if (depth < 8)
  612.         png_set_packing (png);
  613.  
  614.     /* convert grayscale to RGB */
  615.     if (color_type == PNG_COLOR_TYPE_GRAY ||
  616.         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  617.     {
  618.         png_set_gray_to_rgb (png);
  619.     }
  620.  
  621.     if (interlace != PNG_INTERLACE_NONE)
  622.         png_set_interlace_handling (png);
  623.  
  624.     png_set_filler (png, 0xff, PNG_FILLER_AFTER);
  625.  
  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))
  634.     {
  635.         surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_READ_ERROR));
  636.         goto BAIL;
  637.     }
  638.  
  639.     switch (color_type) {
  640.         default:
  641.             ASSERT_NOT_REACHED;
  642.             /* fall-through just in case ;-) */
  643.  
  644.         case PNG_COLOR_TYPE_RGB_ALPHA:
  645.             format = CAIRO_FORMAT_ARGB32;
  646.             png_set_read_user_transform_fn (png, premultiply_data);
  647.             break;
  648.  
  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;
  653.     }
  654.  
  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;
  659.     }
  660.  
  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;
  665.     }
  666.  
  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;
  671.     }
  672.  
  673.     for (i = 0; i < png_height; i++)
  674.         row_pointers[i] = &data[i * stride];
  675.  
  676.     png_read_image (png, row_pointers);
  677.     png_read_end (png, info);
  678.  
  679.     if (unlikely (status)) { /* catch any late warnings - probably hit an error already */
  680.         surface = _cairo_surface_create_in_error (status);
  681.         goto BAIL;
  682.     }
  683.  
  684.     surface = cairo_image_surface_create_for_data (data, format,
  685.                                                    png_width, png_height,
  686.                                                    stride);
  687.     if (surface->status)
  688.         goto BAIL;
  689.  
  690.     _cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t*)surface);
  691.     data = NULL;
  692.  
  693.     _cairo_debug_check_image_surface_is_defined (surface);
  694.  
  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;
  703.     }
  704.  
  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;
  716.     }
  717.  
  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;
  725.  
  726.         status_ignored = _cairo_output_stream_destroy (png_closure->png_data);
  727.     }
  728.  
  729.     return surface;
  730. }
  731.  
  732. /**
  733.  * cairo_image_surface_create_from_png:
  734.  * @filename: name of PNG file to load
  735.  *
  736.  * Creates a new image surface and initializes the contents to the
  737.  * given PNG file.
  738.  *
  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:
  743.  *
  744.  *      %CAIRO_STATUS_NO_MEMORY
  745.  *      %CAIRO_STATUS_FILE_NOT_FOUND
  746.  *      %CAIRO_STATUS_READ_ERROR
  747.  *
  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().
  751.  *
  752.  * Since: 1.0
  753.  **/
  754. cairo_surface_t *
  755. cairo_image_surface_create_from_png (const char *filename)
  756. {
  757.     struct png_read_closure_t png_closure;
  758.     cairo_surface_t *surface;
  759.  
  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;
  773.         }
  774.         return _cairo_surface_create_in_error (status);
  775.     }
  776.  
  777.     png_closure.read_func = stdio_read_func;
  778.  
  779.     surface = read_png (&png_closure);
  780.  
  781.     fclose (png_closure.closure);
  782.  
  783.     return surface;
  784. }
  785.  
  786. /**
  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.
  790.  *
  791.  * Creates a new image surface from PNG data read incrementally
  792.  * via the @read_func function.
  793.  *
  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:
  799.  *
  800.  *      %CAIRO_STATUS_NO_MEMORY
  801.  *      %CAIRO_STATUS_READ_ERROR
  802.  *
  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().
  806.  *
  807.  * Since: 1.0
  808.  **/
  809. cairo_surface_t *
  810. cairo_image_surface_create_from_png_stream (cairo_read_func_t   read_func,
  811.                                             void                *closure)
  812. {
  813.     struct png_read_closure_t png_closure;
  814.  
  815.     png_closure.read_func = read_func;
  816.     png_closure.closure = closure;
  817.  
  818.     return read_png (&png_closure);
  819. }
  820.