1
+ /*
2
+ * Flickernoise
3
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, version 3 of the License.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ #include <stdio.h>
19
+ #include <stdlib.h>
20
+ #include <setjmp.h>
21
+ #include <png.h>
22
+ #include <zlib.h>
23
+
24
+ #include "pixbuf.h"
25
+ #include "loaders.h"
26
+
27
+ #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
28
+ #warning Floating point PNG is slow
29
+ #endif
30
+
31
+ struct pixbuf * pixbuf_load_png (char * filename )
32
+ {
33
+ struct pixbuf * ret ;
34
+ FILE * fd ;
35
+ unsigned char header [8 ];
36
+ png_structp png_ptr ;
37
+ png_infop info_ptr ;
38
+ unsigned int width , height ;
39
+ png_byte color_type ;
40
+ png_byte bit_depth ;
41
+ png_bytep * row_pointers ;
42
+ size_t rowbytes ;
43
+ int y ;
44
+
45
+ ret = NULL ;
46
+ fd = fopen (filename , "r" );
47
+ if (fd == NULL ) goto free0 ;
48
+ fread (header , 1 , 8 , fd );
49
+ if (png_sig_cmp (header , 0 , 8 )) goto free1 ;
50
+
51
+ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING , NULL , NULL , NULL );
52
+ if (png_ptr == NULL ) goto free1 ;
53
+ info_ptr = png_create_info_struct (png_ptr );
54
+ if (info_ptr == NULL ) goto free2 ;
55
+
56
+ if (setjmp (png_jmpbuf (png_ptr ))) goto free3 ;
57
+ png_init_io (png_ptr , fd );
58
+ png_set_sig_bytes (png_ptr , 8 );
59
+ png_read_info (png_ptr , info_ptr );
60
+
61
+ width = png_get_image_width (png_ptr , info_ptr );
62
+ height = png_get_image_height (png_ptr , info_ptr );
63
+ color_type = png_get_color_type (png_ptr , info_ptr );
64
+ bit_depth = png_get_bit_depth (png_ptr , info_ptr );
65
+
66
+ if (color_type != PNG_COLOR_TYPE_RGB ) goto free3 ;
67
+ if (bit_depth != 8 ) goto free3 ;
68
+
69
+ row_pointers = calloc (sizeof (png_bytep ), height );
70
+ if (row_pointers == NULL ) goto free3 ;
71
+ if (setjmp (png_jmpbuf (png_ptr ))) goto free4 ;
72
+ rowbytes = png_get_rowbytes (png_ptr , info_ptr );
73
+ for (y = 0 ;y < height ;y ++ ) {
74
+ row_pointers [y ] = malloc (rowbytes );
75
+ if (row_pointers [y ] == NULL )
76
+ goto free4 ;
77
+ }
78
+
79
+ png_read_image (png_ptr , row_pointers );
80
+
81
+ ret = pixbuf_new (width , height );
82
+ if (ret == NULL ) goto free4 ;
83
+ ret -> filename = strdup (filename );
84
+ if (!dither (ret -> pixels , row_pointers , width , height )) {
85
+ pixbuf_dec_ref (ret );
86
+ ret = NULL ;
87
+ goto free4 ;
88
+ }
89
+
90
+ free4 :
91
+ for (y = 0 ;y < height ;y ++ )
92
+ free (row_pointers [y ]);
93
+ free (row_pointers );
94
+ free3 :
95
+ png_destroy_info_struct (png_ptr , & info_ptr );
96
+ free2 :
97
+ png_destroy_read_struct (& png_ptr , NULL , NULL );
98
+ free1 :
99
+ fclose (fd );
100
+ free0 :
101
+ return ret ;
102
+ }
0 commit comments