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>
44
/* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
46
unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
50
for (i = 0; i < row_info->rowbytes; i += 4) {
51
uint8_t *b = &data[i];
55
memcpy (&pixel, b, sizeof (uint32_t));
56
alpha = (pixel & 0xff000000) >> 24;
58
b[0] = b[1] = b[2] = b[3] = 0;
60
b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
61
b[1] = (((pixel & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
62
b[2] = (((pixel & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
68
/* Converts native endian xRGB => RGBx bytes */
70
convert_data_to_bytes (png_structp png, png_row_infop row_info, png_bytep data)
74
for (i = 0; i < row_info->rowbytes; i += 4) {
75
uint8_t *b = &data[i];
78
memcpy (&pixel, b, sizeof (uint32_t));
80
b[0] = (pixel & 0xff0000) >> 16;
81
b[1] = (pixel & 0x00ff00) >> 8;
82
b[2] = (pixel & 0x0000ff) >> 0;
87
/* Use a couple of simple error callbacks that do not print anything to
88
* stderr and rely on the user to check for errors via the #cairo_status_t
92
png_simple_error_callback (png_structp png,
93
png_const_charp error_msg)
95
cairo_status_t *error = png_get_error_ptr (png);
97
/* default to the most likely error */
98
if (*error == CAIRO_STATUS_SUCCESS)
99
*error = _cairo_error (CAIRO_STATUS_NO_MEMORY);
101
#ifdef PNG_SETJMP_SUPPORTED
102
longjmp (png_jmpbuf (png), 1);
105
/* if we get here, then we have to choice but to abort ... */
109
png_simple_warning_callback (png_structp png,
110
png_const_charp error_msg)
112
cairo_status_t *error = png_get_error_ptr (png);
114
/* default to the most likely error */
115
if (*error == CAIRO_STATUS_SUCCESS)
116
*error = _cairo_error (CAIRO_STATUS_NO_MEMORY);
118
/* png does not expect to abort and will try to tidy up after a warning */
122
/* Starting with libpng-1.2.30, we must explicitly specify an output_flush_fn.
123
* Otherwise, we will segfault if we are writing to a stream. */
125
png_simple_output_flush_fn (png_structp png_ptr)
129
static cairo_status_t
130
write_png (cairo_surface_t *surface,
131
png_rw_ptr write_func,
135
cairo_status_t status;
136
cairo_image_surface_t *image;
140
png_byte **volatile rows = NULL;
145
status = _cairo_surface_acquire_source_image (surface,
149
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
150
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
154
/* PNG complains about "Image width or height is zero in IHDR" */
155
if (image->width == 0 || image->height == 0) {
156
status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
160
rows = _cairo_malloc_ab (image->height, sizeof (png_byte*));
162
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
166
for (i = 0; i < image->height; i++)
167
rows[i] = (png_byte *) image->data + i * image->stride;
169
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, &status,
170
png_simple_error_callback,
171
png_simple_warning_callback);
173
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
177
info = png_create_info_struct (png);
179
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
183
#ifdef PNG_SETJMP_SUPPORTED
184
if (setjmp (png_jmpbuf (png)))
188
png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn);
190
switch (image->format) {
191
case CAIRO_FORMAT_ARGB32:
193
png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
195
case CAIRO_FORMAT_RGB24:
197
png_color_type = PNG_COLOR_TYPE_RGB;
199
case CAIRO_FORMAT_A8:
201
png_color_type = PNG_COLOR_TYPE_GRAY;
203
case CAIRO_FORMAT_A1:
205
png_color_type = PNG_COLOR_TYPE_GRAY;
206
#ifndef WORDS_BIGENDIAN
207
png_set_packswap (png);
211
status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
215
png_set_IHDR (png, info,
217
image->height, depth,
220
PNG_COMPRESSION_TYPE_DEFAULT,
221
PNG_FILTER_TYPE_DEFAULT);
223
white.gray = (1 << depth) - 1;
224
white.red = white.blue = white.green = white.gray;
225
png_set_bKGD (png, info, &white);
227
if (0) { /* XXX extract meta-data from surface (i.e. creation date) */
230
png_convert_from_time_t (&pt, time (NULL));
231
png_set_tIME (png, info, &pt);
234
/* We have to call png_write_info() before setting up the write
235
* transformation, since it stores data internally in 'png'
236
* that is needed for the write transformation functions to work.
238
png_write_info (png, info);
240
if (image->format == CAIRO_FORMAT_ARGB32)
241
png_set_write_user_transform_fn (png, unpremultiply_data);
242
else if (image->format == CAIRO_FORMAT_RGB24)
243
png_set_write_user_transform_fn (png, convert_data_to_bytes);
244
if (image->format == CAIRO_FORMAT_RGB24)
245
png_set_filler (png, 0, PNG_FILLER_AFTER);
247
png_write_image (png, rows);
248
png_write_end (png, info);
251
png_destroy_write_struct (&png, &info);
255
_cairo_surface_release_source_image (surface, image, image_extra);
261
stdio_write_func (png_structp png, png_bytep data, png_size_t size)
265
fp = png_get_io_ptr (png);
267
size_t ret = fwrite (data, 1, size, fp);
270
if (size && ferror (fp)) {
271
cairo_status_t *error = png_get_error_ptr (png);
272
if (*error == CAIRO_STATUS_SUCCESS)
273
*error = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
274
png_error (png, NULL);
280
* cairo_surface_write_to_png:
281
* @surface: a #cairo_surface_t with pixel contents
282
* @filename: the name of a file to write to
284
* Writes the contents of @surface to a new file @filename as a PNG
287
* Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
288
* successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY if memory could not
289
* be allocated for the operation or
290
* %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
291
* pixel contents, or %CAIRO_STATUS_WRITE_ERROR if an I/O error occurs
292
* while attempting to write the file.
295
cairo_surface_write_to_png (cairo_surface_t *surface,
296
const char *filename)
299
cairo_status_t status;
302
return surface->status;
304
if (surface->finished)
305
return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
307
fp = fopen (filename, "wb");
311
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
313
return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
317
status = write_png (surface, stdio_write_func, fp);
319
if (fclose (fp) && status == CAIRO_STATUS_SUCCESS)
320
status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
325
struct png_write_closure_t {
326
cairo_write_func_t write_func;
331
stream_write_func (png_structp png, png_bytep data, png_size_t size)
333
cairo_status_t status;
334
struct png_write_closure_t *png_closure;
336
png_closure = png_get_io_ptr (png);
337
status = png_closure->write_func (png_closure->closure, data, size);
339
cairo_status_t *error = png_get_error_ptr (png);
340
if (*error == CAIRO_STATUS_SUCCESS)
342
png_error (png, NULL);
347
* cairo_surface_write_to_png_stream:
348
* @surface: a #cairo_surface_t with pixel contents
349
* @write_func: a #cairo_write_func_t
350
* @closure: closure data for the write function
352
* Writes the image surface to the write function.
354
* Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
355
* successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if
356
* memory could not be allocated for the operation,
357
* %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
361
cairo_surface_write_to_png_stream (cairo_surface_t *surface,
362
cairo_write_func_t write_func,
365
struct png_write_closure_t png_closure;
368
return surface->status;
370
if (surface->finished)
371
return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
373
png_closure.write_func = write_func;
374
png_closure.closure = closure;
376
return write_png (surface, stream_write_func, &png_closure);
378
slim_hidden_def (cairo_surface_write_to_png_stream);
381
multiply_alpha (int alpha, int color)
383
int temp = (alpha * color) + 0x80;
384
return ((temp + (temp >> 8)) >> 8);
387
/* Premultiplies data and converts RGBA bytes => native endian */
389
premultiply_data (png_structp png,
390
png_row_infop row_info,
395
for (i = 0; i < row_info->rowbytes; i += 4) {
396
uint8_t *base = &data[i];
397
uint8_t alpha = base[3];
403
uint8_t red = base[0];
404
uint8_t green = base[1];
405
uint8_t blue = base[2];
408
red = multiply_alpha (alpha, red);
409
green = multiply_alpha (alpha, green);
410
blue = multiply_alpha (alpha, blue);
412
p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
414
memcpy (base, &p, sizeof (uint32_t));
418
/* Converts RGBx bytes to native endian xRGB */
420
convert_bytes_to_data (png_structp png, png_row_infop row_info, png_bytep data)
424
for (i = 0; i < row_info->rowbytes; i += 4) {
425
uint8_t *base = &data[i];
426
uint8_t red = base[0];
427
uint8_t green = base[1];
428
uint8_t blue = base[2];
431
pixel = (0xff << 24) | (red << 16) | (green << 8) | (blue << 0);
432
memcpy (base, &pixel, sizeof (uint32_t));
436
static cairo_surface_t *
437
read_png (png_rw_ptr read_func,
440
cairo_surface_t *surface;
441
png_struct *png = NULL;
443
png_byte *data = NULL;
444
png_byte **row_pointers = NULL;
445
png_uint_32 png_width, png_height;
446
int depth, color_type, interlace, stride;
448
cairo_format_t format;
449
cairo_status_t status;
451
/* XXX: Perhaps we'll want some other error handlers? */
452
png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
454
png_simple_error_callback,
455
png_simple_warning_callback);
457
surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
461
info = png_create_info_struct (png);
463
surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
467
png_set_read_fn (png, closure, read_func);
469
status = CAIRO_STATUS_SUCCESS;
470
#ifdef PNG_SETJMP_SUPPORTED
471
if (setjmp (png_jmpbuf (png))) {
472
surface = _cairo_surface_create_in_error (status);
477
png_read_info (png, info);
479
png_get_IHDR (png, info,
480
&png_width, &png_height, &depth,
481
&color_type, &interlace, NULL, NULL);
482
if (status) { /* catch any early warnings */
483
surface = _cairo_surface_create_in_error (status);
487
/* convert palette/gray image to rgb */
488
if (color_type == PNG_COLOR_TYPE_PALETTE)
489
png_set_palette_to_rgb (png);
491
/* expand gray bit depth if needed */
492
if (color_type == PNG_COLOR_TYPE_GRAY) {
493
#if PNG_LIBPNG_VER >= 10209
494
png_set_expand_gray_1_2_4_to_8 (png);
496
png_set_gray_1_2_4_to_8 (png);
500
/* transform transparency to alpha */
501
if (png_get_valid (png, info, PNG_INFO_tRNS))
502
png_set_tRNS_to_alpha (png);
505
png_set_strip_16 (png);
508
png_set_packing (png);
510
/* convert grayscale to RGB */
511
if (color_type == PNG_COLOR_TYPE_GRAY ||
512
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
514
png_set_gray_to_rgb (png);
517
if (interlace != PNG_INTERLACE_NONE)
518
png_set_interlace_handling (png);
520
png_set_filler (png, 0xff, PNG_FILLER_AFTER);
522
/* recheck header after setting EXPAND options */
523
png_read_update_info (png, info);
524
png_get_IHDR (png, info,
525
&png_width, &png_height, &depth,
526
&color_type, &interlace, NULL, NULL);
528
! (color_type == PNG_COLOR_TYPE_RGB ||
529
color_type == PNG_COLOR_TYPE_RGB_ALPHA))
531
surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_READ_ERROR));
535
switch (color_type) {
538
/* fall-through just in case ;-) */
540
case PNG_COLOR_TYPE_RGB_ALPHA:
541
format = CAIRO_FORMAT_ARGB32;
542
png_set_read_user_transform_fn (png, premultiply_data);
545
case PNG_COLOR_TYPE_RGB:
546
format = CAIRO_FORMAT_RGB24;
547
png_set_read_user_transform_fn (png, convert_bytes_to_data);
551
stride = cairo_format_stride_for_width (format, png_width);
553
surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
557
data = _cairo_malloc_ab (png_height, stride);
559
surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
563
row_pointers = _cairo_malloc_ab (png_height, sizeof (char *));
564
if (row_pointers == NULL) {
565
surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
569
for (i = 0; i < png_height; i++)
570
row_pointers[i] = &data[i * stride];
572
png_read_image (png, row_pointers);
573
png_read_end (png, info);
575
if (status) { /* catch any late warnings - probably hit an error already */
576
surface = _cairo_surface_create_in_error (status);
580
surface = cairo_image_surface_create_for_data (data, format,
581
png_width, png_height,
586
_cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t*)surface);
595
png_destroy_read_struct (&png, &info, NULL);
601
stdio_read_func (png_structp png, png_bytep data, png_size_t size)
605
fp = png_get_io_ptr (png);
607
size_t ret = fread (data, 1, size, fp);
610
if (size && (feof (fp) || ferror (fp))) {
611
cairo_status_t *error = png_get_error_ptr (png);
612
if (*error == CAIRO_STATUS_SUCCESS)
613
*error = _cairo_error (CAIRO_STATUS_READ_ERROR);
614
png_error (png, NULL);
620
* cairo_image_surface_create_from_png:
621
* @filename: name of PNG file to load
623
* Creates a new image surface and initializes the contents to the
626
* Return value: a new #cairo_surface_t initialized with the contents
627
* of the PNG file, or a "nil" surface if any error occurred. A nil
628
* surface can be checked for with cairo_surface_status(surface) which
629
* may return one of the following values:
631
* %CAIRO_STATUS_NO_MEMORY
632
* %CAIRO_STATUS_FILE_NOT_FOUND
633
* %CAIRO_STATUS_READ_ERROR
636
cairo_image_surface_create_from_png (const char *filename)
639
cairo_surface_t *surface;
641
fp = fopen (filename, "rb");
643
cairo_status_t status;
646
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
649
status = _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND);
652
status = _cairo_error (CAIRO_STATUS_READ_ERROR);
655
return _cairo_surface_create_in_error (status);
658
surface = read_png (stdio_read_func, fp);
665
struct png_read_closure_t {
666
cairo_read_func_t read_func;
671
stream_read_func (png_structp png, png_bytep data, png_size_t size)
673
cairo_status_t status;
674
struct png_read_closure_t *png_closure;
676
png_closure = png_get_io_ptr (png);
677
status = png_closure->read_func (png_closure->closure, data, size);
679
cairo_status_t *error = png_get_error_ptr (png);
680
if (*error == CAIRO_STATUS_SUCCESS)
682
png_error (png, NULL);
687
* cairo_image_surface_create_from_png_stream:
688
* @read_func: function called to read the data of the file
689
* @closure: data to pass to @read_func.
691
* Creates a new image surface from PNG data read incrementally
692
* via the @read_func function.
694
* Return value: a new #cairo_surface_t initialized with the contents
695
* of the PNG file or %NULL if the data read is not a valid PNG image or
696
* memory could not be allocated for the operation.
699
cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
702
struct png_read_closure_t png_closure;
704
png_closure.read_func = read_func;
705
png_closure.closure = closure;
707
return read_png (stream_read_func, &png_closure);