Rev 1897 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1897 | Rev 3959 | ||
---|---|---|---|
Line 37... | Line 37... | ||
37 | */ |
37 | */ |
Line 38... | Line 38... | ||
38 | 38 | ||
Line 39... | Line 39... | ||
39 | #include "cairoint.h" |
39 | #include "cairoint.h" |
- | 40 | ||
40 | 41 | #include "cairo-error-private.h" |
|
Line 41... | Line 42... | ||
41 | #include "cairo-error-private.h" |
42 | #include "cairo-image-surface-private.h" |
42 | #include "cairo-output-stream-private.h" |
43 | #include "cairo-output-stream-private.h" |
43 | 44 | ||
Line 51... | Line 52... | ||
51 | * @Short_Description: Reading and writing PNG images |
52 | * @Short_Description: Reading and writing PNG images |
52 | * @See_Also: #cairo_surface_t |
53 | * @See_Also: #cairo_surface_t |
53 | * |
54 | * |
54 | * The PNG functions allow reading PNG images into image surfaces, and writing |
55 | * The PNG functions allow reading PNG images into image surfaces, and writing |
55 | * any surface to a PNG file. |
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. |
|
56 | */ |
65 | **/ |
Line 57... | Line 66... | ||
57 | 66 | ||
58 | /** |
67 | /** |
59 | * CAIRO_HAS_PNG_FUNCTIONS: |
68 | * CAIRO_HAS_PNG_FUNCTIONS: |
60 | * |
69 | * |
61 | * Defined if the PNG functions are available. |
70 | * Defined if the PNG functions are available. |
62 | * This macro can be used to conditionally compile code using the cairo |
71 | * This macro can be used to conditionally compile code using the cairo |
- | 72 | * PNG functions. |
|
- | 73 | * |
|
63 | * PNG functions. |
74 | * Since: 1.0 |
Line 64... | Line 75... | ||
64 | */ |
75 | **/ |
65 | 76 | ||
66 | struct png_read_closure_t { |
77 | struct png_read_closure_t { |
67 | cairo_read_func_t read_func; |
78 | cairo_read_func_t read_func; |
Line 136... | Line 147... | ||
136 | 147 | ||
137 | static void |
148 | static void |
138 | png_simple_warning_callback (png_structp png, |
149 | png_simple_warning_callback (png_structp png, |
139 | png_const_charp error_msg) |
150 | png_const_charp error_msg) |
140 | { |
151 | { |
141 | cairo_status_t *error = png_get_error_ptr (png); |
- | |
142 | 152 | /* png does not expect to abort and will try to tidy up and continue |
|
143 | /* default to the most likely error */ |
153 | * loading the image after a warning. So we also want to return the |
- | 154 | * (incorrect?) surface. |
|
144 | if (*error == CAIRO_STATUS_SUCCESS) |
155 | * |
145 | *error = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
146 | 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. |
|
147 | /* png does not expect to abort and will try to tidy up after a warning */ |
158 | */ |
Line 148... | Line 159... | ||
148 | } |
159 | } |
149 | 160 | ||
Line 159... | Line 170... | ||
159 | write_png (cairo_surface_t *surface, |
170 | write_png (cairo_surface_t *surface, |
160 | png_rw_ptr write_func, |
171 | png_rw_ptr write_func, |
161 | void *closure) |
172 | void *closure) |
162 | { |
173 | { |
163 | int i; |
174 | int i; |
164 | cairo_status_t status; |
175 | cairo_int_status_t status; |
165 | cairo_image_surface_t *image; |
176 | cairo_image_surface_t *image; |
166 | cairo_image_surface_t * volatile clone; |
177 | cairo_image_surface_t * volatile clone; |
167 | void *image_extra; |
178 | void *image_extra; |
168 | png_struct *png; |
179 | png_struct *png; |
169 | png_info *info; |
180 | png_info *info; |
170 | png_byte **volatile rows = NULL; |
181 | png_byte **volatile rows = NULL; |
171 | png_color_16 white; |
182 | png_color_16 white; |
172 | int png_color_type; |
183 | int png_color_type; |
173 | int depth; |
184 | int bpc; |
Line 174... | Line 185... | ||
174 | 185 | ||
175 | status = _cairo_surface_acquire_source_image (surface, |
186 | status = _cairo_surface_acquire_source_image (surface, |
176 | &image, |
187 | &image, |
Line 225... | Line 236... | ||
225 | 236 | ||
Line 226... | Line 237... | ||
226 | png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn); |
237 | png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn); |
227 | 238 | ||
228 | switch (clone->format) { |
239 | switch (clone->format) { |
229 | case CAIRO_FORMAT_ARGB32: |
240 | case CAIRO_FORMAT_ARGB32: |
230 | depth = 8; |
241 | bpc = 8; |
231 | if (_cairo_image_analyze_transparency (clone) == CAIRO_IMAGE_IS_OPAQUE) |
242 | if (_cairo_image_analyze_transparency (clone) == CAIRO_IMAGE_IS_OPAQUE) |
232 | png_color_type = PNG_COLOR_TYPE_RGB; |
243 | png_color_type = PNG_COLOR_TYPE_RGB; |
233 | else |
244 | else |
- | 245 | png_color_type = PNG_COLOR_TYPE_RGB_ALPHA; |
|
- | 246 | break; |
|
- | 247 | case CAIRO_FORMAT_RGB30: |
|
- | 248 | bpc = 10; |
|
234 | png_color_type = PNG_COLOR_TYPE_RGB_ALPHA; |
249 | png_color_type = PNG_COLOR_TYPE_RGB; |
235 | break; |
250 | break; |
236 | case CAIRO_FORMAT_RGB24: |
251 | case CAIRO_FORMAT_RGB24: |
237 | depth = 8; |
252 | bpc = 8; |
238 | png_color_type = PNG_COLOR_TYPE_RGB; |
253 | png_color_type = PNG_COLOR_TYPE_RGB; |
239 | break; |
254 | break; |
240 | case CAIRO_FORMAT_A8: |
255 | case CAIRO_FORMAT_A8: |
241 | depth = 8; |
256 | bpc = 8; |
242 | png_color_type = PNG_COLOR_TYPE_GRAY; |
257 | png_color_type = PNG_COLOR_TYPE_GRAY; |
243 | break; |
258 | break; |
244 | case CAIRO_FORMAT_A1: |
259 | case CAIRO_FORMAT_A1: |
245 | depth = 1; |
260 | bpc = 1; |
246 | png_color_type = PNG_COLOR_TYPE_GRAY; |
261 | png_color_type = PNG_COLOR_TYPE_GRAY; |
247 | #ifndef WORDS_BIGENDIAN |
262 | #ifndef WORDS_BIGENDIAN |
248 | png_set_packswap (png); |
263 | png_set_packswap (png); |
Line 255... | Line 270... | ||
255 | goto BAIL4; |
270 | goto BAIL4; |
256 | } |
271 | } |
Line 257... | Line 272... | ||
257 | 272 | ||
258 | png_set_IHDR (png, info, |
273 | png_set_IHDR (png, info, |
259 | clone->width, |
274 | clone->width, |
260 | clone->height, depth, |
275 | clone->height, bpc, |
261 | png_color_type, |
276 | png_color_type, |
262 | PNG_INTERLACE_NONE, |
277 | PNG_INTERLACE_NONE, |
263 | PNG_COMPRESSION_TYPE_DEFAULT, |
278 | PNG_COMPRESSION_TYPE_DEFAULT, |
Line 264... | Line 279... | ||
264 | PNG_FILTER_TYPE_DEFAULT); |
279 | PNG_FILTER_TYPE_DEFAULT); |
265 | 280 | ||
266 | white.gray = (1 << depth) - 1; |
281 | white.gray = (1 << bpc) - 1; |
Line 267... | Line 282... | ||
267 | white.red = white.blue = white.green = white.gray; |
282 | white.red = white.blue = white.green = white.gray; |
268 | png_set_bKGD (png, info, &white); |
283 | png_set_bKGD (png, info, &white); |
Line 333... | Line 348... | ||
333 | * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY if memory could not |
348 | * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY if memory could not |
334 | * be allocated for the operation or |
349 | * be allocated for the operation or |
335 | * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have |
350 | * %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 |
351 | * pixel contents, or %CAIRO_STATUS_WRITE_ERROR if an I/O error occurs |
337 | * while attempting to write the file. |
352 | * while attempting to write the file. |
- | 353 | * |
|
- | 354 | * Since: 1.0 |
|
338 | **/ |
355 | **/ |
339 | cairo_status_t |
356 | cairo_status_t |
340 | cairo_surface_write_to_png (cairo_surface_t *surface, |
357 | cairo_surface_write_to_png (cairo_surface_t *surface, |
341 | const char *filename) |
358 | const char *filename) |
342 | { |
359 | { |
Line 399... | Line 416... | ||
399 | * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written |
416 | * Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written |
400 | * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if |
417 | * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if |
401 | * memory could not be allocated for the operation, |
418 | * memory could not be allocated for the operation, |
402 | * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have |
419 | * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have |
403 | * pixel contents. |
420 | * pixel contents. |
- | 421 | * |
|
- | 422 | * Since: 1.0 |
|
404 | **/ |
423 | **/ |
405 | cairo_status_t |
424 | cairo_status_t |
406 | cairo_surface_write_to_png_stream (cairo_surface_t *surface, |
425 | cairo_surface_write_to_png_stream (cairo_surface_t *surface, |
407 | cairo_write_func_t write_func, |
426 | cairo_write_func_t write_func, |
408 | void *closure) |
427 | void *closure) |
Line 695... | Line 714... | ||
695 | surface = _cairo_surface_create_in_error (status); |
714 | surface = _cairo_surface_create_in_error (status); |
696 | goto BAIL; |
715 | goto BAIL; |
697 | } |
716 | } |
Line 698... | Line 717... | ||
698 | 717 | ||
699 | BAIL: |
- | |
700 | if (row_pointers != NULL) |
718 | BAIL: |
701 | free (row_pointers); |
- | |
702 | if (data != NULL) |
719 | free (row_pointers); |
703 | free (data); |
720 | free (data); |
704 | if (png != NULL) |
721 | if (png != NULL) |
705 | png_destroy_read_struct (&png, &info, NULL); |
722 | png_destroy_read_struct (&png, &info, NULL); |
706 | if (png_closure->png_data != NULL) { |
723 | if (png_closure->png_data != NULL) { |
Line 729... | Line 746... | ||
729 | * %CAIRO_STATUS_READ_ERROR |
746 | * %CAIRO_STATUS_READ_ERROR |
730 | * |
747 | * |
731 | * Alternatively, you can allow errors to propagate through the drawing |
748 | * Alternatively, you can allow errors to propagate through the drawing |
732 | * operations and check the status on the context upon completion |
749 | * operations and check the status on the context upon completion |
733 | * using cairo_status(). |
750 | * using cairo_status(). |
- | 751 | * |
|
- | 752 | * Since: 1.0 |
|
734 | **/ |
753 | **/ |
735 | cairo_surface_t * |
754 | cairo_surface_t * |
736 | cairo_image_surface_create_from_png (const char *filename) |
755 | cairo_image_surface_create_from_png (const char *filename) |
737 | { |
756 | { |
738 | struct png_read_closure_t png_closure; |
757 | struct png_read_closure_t png_closure; |
Line 782... | Line 801... | ||
782 | * %CAIRO_STATUS_READ_ERROR |
801 | * %CAIRO_STATUS_READ_ERROR |
783 | * |
802 | * |
784 | * Alternatively, you can allow errors to propagate through the drawing |
803 | * Alternatively, you can allow errors to propagate through the drawing |
785 | * operations and check the status on the context upon completion |
804 | * operations and check the status on the context upon completion |
786 | * using cairo_status(). |
805 | * using cairo_status(). |
- | 806 | * |
|
- | 807 | * Since: 1.0 |
|
787 | **/ |
808 | **/ |
788 | cairo_surface_t * |
809 | cairo_surface_t * |
789 | cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, |
810 | cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, |
790 | void *closure) |
811 | void *closure) |
791 | { |
812 | { |