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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
34 * Carl D. Worth <cworth@cworth.org>
35 * Kristian Høgsberg <krh@redhat.com>
36 * Chris Wilson <chris@chris-wilson.co.uk>
40 #include "cairo-output-stream-private.h"
46 struct png_read_closure_t
{
47 cairo_read_func_t read_func
;
49 cairo_output_stream_t
*png_data
;
53 /* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
55 unpremultiply_data (png_structp png
, png_row_infop row_info
, png_bytep data
)
59 for (i
= 0; i
< row_info
->rowbytes
; i
+= 4) {
60 uint8_t *b
= &data
[i
];
64 memcpy (&pixel
, b
, sizeof (uint32_t));
65 alpha
= (pixel
& 0xff000000) >> 24;
67 b
[0] = b
[1] = b
[2] = b
[3] = 0;
69 b
[0] = (((pixel
& 0xff0000) >> 16) * 255 + alpha
/ 2) / alpha
;
70 b
[1] = (((pixel
& 0x00ff00) >> 8) * 255 + alpha
/ 2) / alpha
;
71 b
[2] = (((pixel
& 0x0000ff) >> 0) * 255 + alpha
/ 2) / alpha
;
77 /* Converts native endian xRGB => RGBx bytes */
79 convert_data_to_bytes (png_structp png
, png_row_infop row_info
, png_bytep data
)
83 for (i
= 0; i
< row_info
->rowbytes
; i
+= 4) {
84 uint8_t *b
= &data
[i
];
87 memcpy (&pixel
, b
, sizeof (uint32_t));
89 b
[0] = (pixel
& 0xff0000) >> 16;
90 b
[1] = (pixel
& 0x00ff00) >> 8;
91 b
[2] = (pixel
& 0x0000ff) >> 0;
96 /* Use a couple of simple error callbacks that do not print anything to
97 * stderr and rely on the user to check for errors via the #cairo_status_t
101 png_simple_error_callback (png_structp png
,
102 png_const_charp error_msg
)
104 cairo_status_t
*error
= png_get_error_ptr (png
);
106 /* default to the most likely error */
107 if (*error
== CAIRO_STATUS_SUCCESS
)
108 *error
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
110 #ifdef PNG_SETJMP_SUPPORTED
111 longjmp (png_jmpbuf (png
), 1);
114 /* if we get here, then we have to choice but to abort ... */
118 png_simple_warning_callback (png_structp png
,
119 png_const_charp error_msg
)
121 cairo_status_t
*error
= png_get_error_ptr (png
);
123 /* default to the most likely error */
124 if (*error
== CAIRO_STATUS_SUCCESS
)
125 *error
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
127 /* png does not expect to abort and will try to tidy up after a warning */
131 /* Starting with libpng-1.2.30, we must explicitly specify an output_flush_fn.
132 * Otherwise, we will segfault if we are writing to a stream. */
134 png_simple_output_flush_fn (png_structp png_ptr
)
138 static cairo_status_t
139 write_png (cairo_surface_t
*surface
,
140 png_rw_ptr write_func
,
144 cairo_status_t status
;
145 cairo_image_surface_t
*image
;
146 cairo_image_surface_t
* volatile clone
;
150 png_byte
**volatile rows
= NULL
;
155 status
= _cairo_surface_acquire_source_image (surface
,
159 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
)
160 return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
161 else if (unlikely (status
))
164 /* PNG complains about "Image width or height is zero in IHDR" */
165 if (image
->width
== 0 || image
->height
== 0) {
166 status
= _cairo_error (CAIRO_STATUS_WRITE_ERROR
);
170 /* Handle the various fallback formats (e.g. low bit-depth XServers)
171 * by coercing them to a simpler format using pixman.
173 if (image
->format
== CAIRO_FORMAT_INVALID
) {
174 clone
= _cairo_image_surface_coerce (image
,
175 _cairo_format_from_content (image
->base
.content
));
176 status
= clone
->base
.status
;
177 if (unlikely (status
))
182 rows
= _cairo_malloc_ab (clone
->height
, sizeof (png_byte
*));
183 if (unlikely (rows
== NULL
)) {
184 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
188 for (i
= 0; i
< clone
->height
; i
++)
189 rows
[i
] = (png_byte
*) clone
->data
+ i
* clone
->stride
;
191 png
= png_create_write_struct (PNG_LIBPNG_VER_STRING
, &status
,
192 png_simple_error_callback
,
193 png_simple_warning_callback
);
194 if (unlikely (png
== NULL
)) {
195 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
199 info
= png_create_info_struct (png
);
200 if (unlikely (info
== NULL
)) {
201 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
205 #ifdef PNG_SETJMP_SUPPORTED
206 if (setjmp (png_jmpbuf (png
)))
210 png_set_write_fn (png
, closure
, write_func
, png_simple_output_flush_fn
);
212 switch (clone
->format
) {
213 case CAIRO_FORMAT_ARGB32
:
215 if (_cairo_image_analyze_transparency (clone
) == CAIRO_IMAGE_IS_OPAQUE
)
216 png_color_type
= PNG_COLOR_TYPE_RGB
;
218 png_color_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
220 case CAIRO_FORMAT_RGB24
:
222 png_color_type
= PNG_COLOR_TYPE_RGB
;
224 case CAIRO_FORMAT_A8
:
226 png_color_type
= PNG_COLOR_TYPE_GRAY
;
228 case CAIRO_FORMAT_A1
:
230 png_color_type
= PNG_COLOR_TYPE_GRAY
;
231 #ifndef WORDS_BIGENDIAN
232 png_set_packswap (png
);
236 status
= _cairo_error (CAIRO_STATUS_INVALID_FORMAT
);
240 png_set_IHDR (png
, info
,
242 clone
->height
, depth
,
245 PNG_COMPRESSION_TYPE_DEFAULT
,
246 PNG_FILTER_TYPE_DEFAULT
);
248 white
.gray
= (1 << depth
) - 1;
249 white
.red
= white
.blue
= white
.green
= white
.gray
;
250 png_set_bKGD (png
, info
, &white
);
252 if (0) { /* XXX extract meta-data from surface (i.e. creation date) */
255 png_convert_from_time_t (&pt
, time (NULL
));
256 png_set_tIME (png
, info
, &pt
);
259 /* We have to call png_write_info() before setting up the write
260 * transformation, since it stores data internally in 'png'
261 * that is needed for the write transformation functions to work.
263 png_write_info (png
, info
);
265 if (png_color_type
== PNG_COLOR_TYPE_RGB_ALPHA
) {
266 png_set_write_user_transform_fn (png
, unpremultiply_data
);
267 } else if (png_color_type
== PNG_COLOR_TYPE_RGB
) {
268 png_set_write_user_transform_fn (png
, convert_data_to_bytes
);
269 png_set_filler (png
, 0, PNG_FILLER_AFTER
);
272 png_write_image (png
, rows
);
273 png_write_end (png
, info
);
276 png_destroy_write_struct (&png
, &info
);
281 cairo_surface_destroy (&clone
->base
);
283 _cairo_surface_release_source_image (surface
, image
, image_extra
);
289 stdio_write_func (png_structp png
, png_bytep data
, png_size_t size
)
293 fp
= png_get_io_ptr (png
);
295 size_t ret
= fwrite (data
, 1, size
, fp
);
298 if (size
&& ferror (fp
)) {
299 cairo_status_t
*error
= png_get_error_ptr (png
);
300 if (*error
== CAIRO_STATUS_SUCCESS
)
301 *error
= _cairo_error (CAIRO_STATUS_WRITE_ERROR
);
302 png_error (png
, NULL
);
308 * cairo_surface_write_to_png:
309 * @surface: a #cairo_surface_t with pixel contents
310 * @filename: the name of a file to write to
312 * Writes the contents of @surface to a new file @filename as a PNG
315 * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
316 * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY if memory could not
317 * be allocated for the operation or
318 * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
319 * pixel contents, or %CAIRO_STATUS_WRITE_ERROR if an I/O error occurs
320 * while attempting to write the file.
323 cairo_surface_write_to_png (cairo_surface_t
*surface
,
324 const char *filename
)
327 cairo_status_t status
;
330 return surface
->status
;
332 if (surface
->finished
)
333 return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED
);
335 fp
= fopen (filename
, "wb");
339 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
341 return _cairo_error (CAIRO_STATUS_WRITE_ERROR
);
345 status
= write_png (surface
, stdio_write_func
, fp
);
347 if (fclose (fp
) && status
== CAIRO_STATUS_SUCCESS
)
348 status
= _cairo_error (CAIRO_STATUS_WRITE_ERROR
);
353 struct png_write_closure_t
{
354 cairo_write_func_t write_func
;
359 stream_write_func (png_structp png
, png_bytep data
, png_size_t size
)
361 cairo_status_t status
;
362 struct png_write_closure_t
*png_closure
;
364 png_closure
= png_get_io_ptr (png
);
365 status
= png_closure
->write_func (png_closure
->closure
, data
, size
);
366 if (unlikely (status
)) {
367 cairo_status_t
*error
= png_get_error_ptr (png
);
368 if (*error
== CAIRO_STATUS_SUCCESS
)
370 png_error (png
, NULL
);
375 * cairo_surface_write_to_png_stream:
376 * @surface: a #cairo_surface_t with pixel contents
377 * @write_func: a #cairo_write_func_t
378 * @closure: closure data for the write function
380 * Writes the image surface to the write function.
382 * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
383 * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if
384 * memory could not be allocated for the operation,
385 * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
389 cairo_surface_write_to_png_stream (cairo_surface_t
*surface
,
390 cairo_write_func_t write_func
,
393 struct png_write_closure_t png_closure
;
396 return surface
->status
;
398 if (surface
->finished
)
399 return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED
);
401 png_closure
.write_func
= write_func
;
402 png_closure
.closure
= closure
;
404 return write_png (surface
, stream_write_func
, &png_closure
);
406 slim_hidden_def (cairo_surface_write_to_png_stream
);
409 multiply_alpha (int alpha
, int color
)
411 int temp
= (alpha
* color
) + 0x80;
412 return ((temp
+ (temp
>> 8)) >> 8);
415 /* Premultiplies data and converts RGBA bytes => native endian */
417 premultiply_data (png_structp png
,
418 png_row_infop row_info
,
423 for (i
= 0; i
< row_info
->rowbytes
; i
+= 4) {
424 uint8_t *base
= &data
[i
];
425 uint8_t alpha
= base
[3];
431 uint8_t red
= base
[0];
432 uint8_t green
= base
[1];
433 uint8_t blue
= base
[2];
436 red
= multiply_alpha (alpha
, red
);
437 green
= multiply_alpha (alpha
, green
);
438 blue
= multiply_alpha (alpha
, blue
);
440 p
= (alpha
<< 24) | (red
<< 16) | (green
<< 8) | (blue
<< 0);
442 memcpy (base
, &p
, sizeof (uint32_t));
446 /* Converts RGBx bytes to native endian xRGB */
448 convert_bytes_to_data (png_structp png
, png_row_infop row_info
, png_bytep data
)
452 for (i
= 0; i
< row_info
->rowbytes
; i
+= 4) {
453 uint8_t *base
= &data
[i
];
454 uint8_t red
= base
[0];
455 uint8_t green
= base
[1];
456 uint8_t blue
= base
[2];
459 pixel
= (0xff << 24) | (red
<< 16) | (green
<< 8) | (blue
<< 0);
460 memcpy (base
, &pixel
, sizeof (uint32_t));
464 static cairo_status_t
465 stdio_read_func (void *closure
, unsigned char *data
, unsigned int size
)
467 FILE *file
= closure
;
472 ret
= fread (data
, 1, size
, file
);
476 if (size
&& (feof (file
) || ferror (file
)))
477 return _cairo_error (CAIRO_STATUS_READ_ERROR
);
480 return CAIRO_STATUS_SUCCESS
;
484 stream_read_func (png_structp png
, png_bytep data
, png_size_t size
)
486 cairo_status_t status
;
487 struct png_read_closure_t
*png_closure
;
489 png_closure
= png_get_io_ptr (png
);
490 status
= png_closure
->read_func (png_closure
->closure
, data
, size
);
491 if (unlikely (status
)) {
492 cairo_status_t
*error
= png_get_error_ptr (png
);
493 if (*error
== CAIRO_STATUS_SUCCESS
)
495 png_error (png
, NULL
);
498 _cairo_output_stream_write (png_closure
->png_data
, data
, size
);
501 static cairo_surface_t
*
502 read_png (struct png_read_closure_t
*png_closure
)
504 cairo_surface_t
*surface
;
505 png_struct
*png
= NULL
;
507 png_byte
*data
= NULL
;
508 png_byte
**row_pointers
= NULL
;
509 png_uint_32 png_width
, png_height
;
510 int depth
, color_type
, interlace
, stride
;
512 cairo_format_t format
;
513 cairo_status_t status
;
514 unsigned char *mime_data
;
515 unsigned int mime_data_length
;
517 png_closure
->png_data
= _cairo_memory_stream_create ();
519 /* XXX: Perhaps we'll want some other error handlers? */
520 png
= png_create_read_struct (PNG_LIBPNG_VER_STRING
,
522 png_simple_error_callback
,
523 png_simple_warning_callback
);
524 if (unlikely (png
== NULL
)) {
525 surface
= _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
529 info
= png_create_info_struct (png
);
530 if (unlikely (info
== NULL
)) {
531 surface
= _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
535 png_set_read_fn (png
, png_closure
, stream_read_func
);
537 status
= CAIRO_STATUS_SUCCESS
;
538 #ifdef PNG_SETJMP_SUPPORTED
539 if (setjmp (png_jmpbuf (png
))) {
540 surface
= _cairo_surface_create_in_error (status
);
545 png_read_info (png
, info
);
547 png_get_IHDR (png
, info
,
548 &png_width
, &png_height
, &depth
,
549 &color_type
, &interlace
, NULL
, NULL
);
550 if (unlikely (status
)) { /* catch any early warnings */
551 surface
= _cairo_surface_create_in_error (status
);
555 /* convert palette/gray image to rgb */
556 if (color_type
== PNG_COLOR_TYPE_PALETTE
)
557 png_set_palette_to_rgb (png
);
559 /* expand gray bit depth if needed */
560 if (color_type
== PNG_COLOR_TYPE_GRAY
) {
561 #if PNG_LIBPNG_VER >= 10209
562 png_set_expand_gray_1_2_4_to_8 (png
);
564 png_set_gray_1_2_4_to_8 (png
);
568 /* transform transparency to alpha */
569 if (png_get_valid (png
, info
, PNG_INFO_tRNS
))
570 png_set_tRNS_to_alpha (png
);
573 png_set_strip_16 (png
);
576 png_set_packing (png
);
578 /* convert grayscale to RGB */
579 if (color_type
== PNG_COLOR_TYPE_GRAY
||
580 color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
582 png_set_gray_to_rgb (png
);
585 if (interlace
!= PNG_INTERLACE_NONE
)
586 png_set_interlace_handling (png
);
588 png_set_filler (png
, 0xff, PNG_FILLER_AFTER
);
590 /* recheck header after setting EXPAND options */
591 png_read_update_info (png
, info
);
592 png_get_IHDR (png
, info
,
593 &png_width
, &png_height
, &depth
,
594 &color_type
, &interlace
, NULL
, NULL
);
596 ! (color_type
== PNG_COLOR_TYPE_RGB
||
597 color_type
== PNG_COLOR_TYPE_RGB_ALPHA
))
599 surface
= _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_READ_ERROR
));
603 switch (color_type
) {
606 /* fall-through just in case ;-) */
608 case PNG_COLOR_TYPE_RGB_ALPHA
:
609 format
= CAIRO_FORMAT_ARGB32
;
610 png_set_read_user_transform_fn (png
, premultiply_data
);
613 case PNG_COLOR_TYPE_RGB
:
614 format
= CAIRO_FORMAT_RGB24
;
615 png_set_read_user_transform_fn (png
, convert_bytes_to_data
);
619 stride
= cairo_format_stride_for_width (format
, png_width
);
621 surface
= _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE
));
625 data
= _cairo_malloc_ab (png_height
, stride
);
626 if (unlikely (data
== NULL
)) {
627 surface
= _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
631 row_pointers
= _cairo_malloc_ab (png_height
, sizeof (char *));
632 if (unlikely (row_pointers
== NULL
)) {
633 surface
= _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
637 for (i
= 0; i
< png_height
; i
++)
638 row_pointers
[i
] = &data
[i
* stride
];
640 png_read_image (png
, row_pointers
);
641 png_read_end (png
, info
);
643 if (unlikely (status
)) { /* catch any late warnings - probably hit an error already */
644 surface
= _cairo_surface_create_in_error (status
);
648 surface
= cairo_image_surface_create_for_data (data
, format
,
649 png_width
, png_height
,
654 _cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t
*)surface
);
657 _cairo_debug_check_image_surface_is_defined (surface
);
659 status
= _cairo_memory_stream_destroy (png_closure
->png_data
,
662 png_closure
->png_data
= NULL
;
663 if (unlikely (status
)) {
664 cairo_surface_destroy (surface
);
665 surface
= _cairo_surface_create_in_error (status
);
669 status
= cairo_surface_set_mime_data (surface
,
675 if (unlikely (status
)) {
677 cairo_surface_destroy (surface
);
678 surface
= _cairo_surface_create_in_error (status
);
683 if (row_pointers
!= NULL
)
688 png_destroy_read_struct (&png
, &info
, NULL
);
689 if (png_closure
->png_data
!= NULL
) {
690 cairo_status_t status_ignored
;
692 status_ignored
= _cairo_output_stream_destroy (png_closure
->png_data
);
699 * cairo_image_surface_create_from_png:
700 * @filename: name of PNG file to load
702 * Creates a new image surface and initializes the contents to the
705 * Return value: a new #cairo_surface_t initialized with the contents
706 * of the PNG file, or a "nil" surface if any error occurred. A nil
707 * surface can be checked for with cairo_surface_status(surface) which
708 * may return one of the following values:
710 * %CAIRO_STATUS_NO_MEMORY
711 * %CAIRO_STATUS_FILE_NOT_FOUND
712 * %CAIRO_STATUS_READ_ERROR
714 * Alternatively, you can allow errors to propagate through the drawing
715 * operations and check the status on the context upon completion
716 * using cairo_status().
719 cairo_image_surface_create_from_png (const char *filename
)
721 struct png_read_closure_t png_closure
;
722 cairo_surface_t
*surface
;
724 png_closure
.closure
= fopen (filename
, "rb");
725 if (png_closure
.closure
== NULL
) {
726 cairo_status_t status
;
729 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
732 status
= _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND
);
735 status
= _cairo_error (CAIRO_STATUS_READ_ERROR
);
738 return _cairo_surface_create_in_error (status
);
741 png_closure
.read_func
= stdio_read_func
;
743 surface
= read_png (&png_closure
);
745 fclose (png_closure
.closure
);
751 * cairo_image_surface_create_from_png_stream:
752 * @read_func: function called to read the data of the file
753 * @closure: data to pass to @read_func.
755 * Creates a new image surface from PNG data read incrementally
756 * via the @read_func function.
758 * Return value: a new #cairo_surface_t initialized with the contents
759 * of the PNG file or a "nil" surface if the data read is not a valid PNG image
760 * or memory could not be allocated for the operation. A nil
761 * surface can be checked for with cairo_surface_status(surface) which
762 * may return one of the following values:
764 * %CAIRO_STATUS_NO_MEMORY
765 * %CAIRO_STATUS_READ_ERROR
767 * Alternatively, you can allow errors to propagate through the drawing
768 * operations and check the status on the context upon completion
769 * using cairo_status().
772 cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func
,
775 struct png_read_closure_t png_closure
;
777 png_closure
.read_func
= read_func
;
778 png_closure
.closure
= closure
;
780 return read_png (&png_closure
);