diff options
Diffstat (limited to 'libraries/evas/src/modules/loaders/png/evas_image_load_png.c')
-rw-r--r-- | libraries/evas/src/modules/loaders/png/evas_image_load_png.c | 329 |
1 files changed, 0 insertions, 329 deletions
diff --git a/libraries/evas/src/modules/loaders/png/evas_image_load_png.c b/libraries/evas/src/modules/loaders/png/evas_image_load_png.c deleted file mode 100644 index 3007a57..0000000 --- a/libraries/evas/src/modules/loaders/png/evas_image_load_png.c +++ /dev/null | |||
@@ -1,329 +0,0 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif | ||
4 | |||
5 | #include <stdio.h> | ||
6 | #include <png.h> | ||
7 | #include <setjmp.h> | ||
8 | |||
9 | #ifdef HAVE_EVIL | ||
10 | # include <Evil.h> | ||
11 | #endif | ||
12 | |||
13 | #ifdef _WIN32_WCE | ||
14 | # define E_FOPEN(file, mode) evil_fopen_native((file), (mode)) | ||
15 | # define E_FREAD(buffer, size, count, stream) evil_fread_native(buffer, size, count, stream) | ||
16 | # define E_FCLOSE(stream) evil_fclose_native(stream) | ||
17 | #else | ||
18 | # define E_FOPEN(file, mode) fopen((file), (mode)) | ||
19 | # define E_FREAD(buffer, size, count, stream) fread(buffer, size, count, stream) | ||
20 | # define E_FCLOSE(stream) fclose(stream) | ||
21 | #endif | ||
22 | |||
23 | #include "evas_common.h" | ||
24 | #include "evas_private.h" | ||
25 | |||
26 | |||
27 | #define PNG_BYTES_TO_CHECK 4 | ||
28 | |||
29 | |||
30 | static Eina_Bool evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4); | ||
31 | static Eina_Bool evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4); | ||
32 | |||
33 | static Evas_Image_Load_Func evas_image_load_png_func = | ||
34 | { | ||
35 | EINA_TRUE, | ||
36 | evas_image_load_file_head_png, | ||
37 | evas_image_load_file_data_png, | ||
38 | NULL, | ||
39 | EINA_FALSE | ||
40 | }; | ||
41 | |||
42 | static Eina_Bool | ||
43 | evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error) | ||
44 | { | ||
45 | png_uint_32 w32, h32; | ||
46 | FILE *f; | ||
47 | png_structp png_ptr = NULL; | ||
48 | png_infop info_ptr = NULL; | ||
49 | int bit_depth, color_type, interlace_type; | ||
50 | unsigned char buf[PNG_BYTES_TO_CHECK]; | ||
51 | char hasa; | ||
52 | |||
53 | hasa = 0; | ||
54 | f = E_FOPEN(file, "rb"); | ||
55 | if (!f) | ||
56 | { | ||
57 | ERR("File: '%s' does not exist\n", file); | ||
58 | *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; | ||
59 | return EINA_FALSE; | ||
60 | } | ||
61 | |||
62 | /* if we havent read the header before, set the header data */ | ||
63 | if (E_FREAD(buf, PNG_BYTES_TO_CHECK, 1, f) != 1) | ||
64 | { | ||
65 | *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; | ||
66 | goto close_file; | ||
67 | } | ||
68 | |||
69 | if (png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK)) | ||
70 | { | ||
71 | *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; | ||
72 | goto close_file; | ||
73 | } | ||
74 | |||
75 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | ||
76 | if (!png_ptr) | ||
77 | { | ||
78 | *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; | ||
79 | goto close_file; | ||
80 | } | ||
81 | |||
82 | info_ptr = png_create_info_struct(png_ptr); | ||
83 | if (!info_ptr) | ||
84 | { | ||
85 | png_destroy_read_struct(&png_ptr, NULL, NULL); | ||
86 | *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; | ||
87 | goto close_file; | ||
88 | } | ||
89 | if (setjmp(png_jmpbuf(png_ptr))) | ||
90 | { | ||
91 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
92 | *error = EVAS_LOAD_ERROR_CORRUPT_FILE; | ||
93 | goto close_file; | ||
94 | } | ||
95 | png_init_io(png_ptr, f); | ||
96 | png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); | ||
97 | png_read_info(png_ptr, info_ptr); | ||
98 | png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32), | ||
99 | (png_uint_32 *) (&h32), &bit_depth, &color_type, | ||
100 | &interlace_type, NULL, NULL); | ||
101 | if ((w32 < 1) || (h32 < 1) || (w32 > IMG_MAX_SIZE) || (h32 > IMG_MAX_SIZE) || | ||
102 | IMG_TOO_BIG(w32, h32)) | ||
103 | { | ||
104 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
105 | if (IMG_TOO_BIG(w32, h32)) | ||
106 | *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; | ||
107 | else | ||
108 | *error = EVAS_LOAD_ERROR_GENERIC; | ||
109 | goto close_file; | ||
110 | } | ||
111 | if (ie->load_opts.scale_down_by > 1) | ||
112 | { | ||
113 | ie->w = (int) w32 / ie->load_opts.scale_down_by; | ||
114 | ie->h = (int) h32 / ie->load_opts.scale_down_by; | ||
115 | if ((ie->w < 1) || (ie->h < 1)) | ||
116 | { | ||
117 | *error = EVAS_LOAD_ERROR_GENERIC; | ||
118 | goto close_file; | ||
119 | } | ||
120 | } | ||
121 | else | ||
122 | { | ||
123 | ie->w = (int) w32; | ||
124 | ie->h = (int) h32; | ||
125 | } | ||
126 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) hasa = 1; | ||
127 | if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) hasa = 1; | ||
128 | if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) hasa = 1; | ||
129 | if (hasa) ie->flags.alpha = 1; | ||
130 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
131 | E_FCLOSE(f); | ||
132 | |||
133 | *error = EVAS_LOAD_ERROR_NONE; | ||
134 | return EINA_TRUE; | ||
135 | |||
136 | close_file: | ||
137 | E_FCLOSE(f); | ||
138 | return EINA_FALSE; | ||
139 | } | ||
140 | |||
141 | static Eina_Bool | ||
142 | evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error) | ||
143 | { | ||
144 | unsigned char *surface; | ||
145 | png_uint_32 w32, h32; | ||
146 | int w, h; | ||
147 | FILE *f; | ||
148 | png_structp png_ptr = NULL; | ||
149 | png_infop info_ptr = NULL; | ||
150 | int bit_depth, color_type, interlace_type; | ||
151 | unsigned char buf[PNG_BYTES_TO_CHECK]; | ||
152 | unsigned char **lines; | ||
153 | char hasa; | ||
154 | int i, j; | ||
155 | int scale_ratio = 1, image_w = 0; | ||
156 | unsigned char *tmp_line; | ||
157 | DATA32 *src_ptr, *dst_ptr; | ||
158 | |||
159 | hasa = 0; | ||
160 | f = E_FOPEN(file, "rb"); | ||
161 | if (!f) | ||
162 | { | ||
163 | *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; | ||
164 | return EINA_FALSE; | ||
165 | } | ||
166 | |||
167 | /* if we havent read the header before, set the header data */ | ||
168 | if (E_FREAD(buf, PNG_BYTES_TO_CHECK, 1, f) != 1) | ||
169 | { | ||
170 | *error = EVAS_LOAD_ERROR_CORRUPT_FILE; | ||
171 | goto close_file; | ||
172 | } | ||
173 | if (png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK)) | ||
174 | { | ||
175 | *error = EVAS_LOAD_ERROR_CORRUPT_FILE; | ||
176 | goto close_file; | ||
177 | } | ||
178 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | ||
179 | if (!png_ptr) | ||
180 | { | ||
181 | *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; | ||
182 | goto close_file; | ||
183 | } | ||
184 | |||
185 | info_ptr = png_create_info_struct(png_ptr); | ||
186 | if (!info_ptr) | ||
187 | { | ||
188 | png_destroy_read_struct(&png_ptr, NULL, NULL); | ||
189 | *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; | ||
190 | goto close_file; | ||
191 | } | ||
192 | if (setjmp(png_jmpbuf(png_ptr))) | ||
193 | { | ||
194 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
195 | *error = EVAS_LOAD_ERROR_CORRUPT_FILE; | ||
196 | goto close_file; | ||
197 | } | ||
198 | png_init_io(png_ptr, f); | ||
199 | png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); | ||
200 | png_read_info(png_ptr, info_ptr); | ||
201 | png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32), | ||
202 | (png_uint_32 *) (&h32), &bit_depth, &color_type, | ||
203 | &interlace_type, NULL, NULL); | ||
204 | image_w = w32; | ||
205 | if (ie->load_opts.scale_down_by > 1) | ||
206 | { | ||
207 | scale_ratio = ie->load_opts.scale_down_by; | ||
208 | w32 /= scale_ratio; | ||
209 | h32 /= scale_ratio; | ||
210 | } | ||
211 | evas_cache_image_surface_alloc(ie, w32, h32); | ||
212 | surface = (unsigned char *) evas_cache_image_pixels(ie); | ||
213 | if (!surface) | ||
214 | { | ||
215 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
216 | *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; | ||
217 | goto close_file; | ||
218 | } | ||
219 | if ((w32 != ie->w) || (h32 != ie->h)) | ||
220 | { | ||
221 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
222 | *error = EVAS_LOAD_ERROR_GENERIC; | ||
223 | goto close_file; | ||
224 | } | ||
225 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) hasa = 1; | ||
226 | if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) hasa = 1; | ||
227 | if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) hasa = 1; | ||
228 | if (hasa) ie->flags.alpha = 1; | ||
229 | |||
230 | /* Prep for transformations... ultimately we want ARGB */ | ||
231 | /* expand palette -> RGB if necessary */ | ||
232 | if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); | ||
233 | /* expand gray (w/reduced bits) -> 8-bit RGB if necessary */ | ||
234 | if ((color_type == PNG_COLOR_TYPE_GRAY) || | ||
235 | (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) | ||
236 | { | ||
237 | png_set_gray_to_rgb(png_ptr); | ||
238 | if (bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); | ||
239 | } | ||
240 | /* expand transparency entry -> alpha channel if present */ | ||
241 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) | ||
242 | png_set_tRNS_to_alpha(png_ptr); | ||
243 | /* reduce 16bit color -> 8bit color if necessary */ | ||
244 | if (bit_depth > 8) png_set_strip_16(png_ptr); | ||
245 | /* pack all pixels to byte boundaries */ | ||
246 | png_set_packing(png_ptr); | ||
247 | |||
248 | w = ie->w; | ||
249 | h = ie->h; | ||
250 | /* we want ARGB */ | ||
251 | #ifdef WORDS_BIGENDIAN | ||
252 | png_set_swap_alpha(png_ptr); | ||
253 | if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE); | ||
254 | #else | ||
255 | png_set_bgr(png_ptr); | ||
256 | if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); | ||
257 | #endif | ||
258 | |||
259 | /* we read image line by line if scale down was set */ | ||
260 | if (scale_ratio == 1) | ||
261 | { | ||
262 | lines = (unsigned char **) alloca(h * sizeof(unsigned char *)); | ||
263 | for (i = 0; i < h; i++) | ||
264 | lines[i] = surface + (i * w * sizeof(DATA32)); | ||
265 | png_read_image(png_ptr, lines); | ||
266 | png_read_end(png_ptr, info_ptr); | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | tmp_line = (unsigned char *) alloca(image_w * sizeof(DATA32)); | ||
271 | dst_ptr = (DATA32 *)surface; | ||
272 | for (i = 0; i < h; i++) | ||
273 | { | ||
274 | png_read_row(png_ptr, tmp_line, NULL); | ||
275 | src_ptr = (DATA32 *)tmp_line; | ||
276 | for (j = 0; j < w; j++) | ||
277 | { | ||
278 | *dst_ptr = *src_ptr; | ||
279 | dst_ptr++; | ||
280 | src_ptr += scale_ratio; | ||
281 | } | ||
282 | for (j = 0; j < (scale_ratio - 1); j++) | ||
283 | { | ||
284 | png_read_row(png_ptr, tmp_line, NULL); | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | |||
289 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
290 | E_FCLOSE(f); | ||
291 | evas_common_image_premul(ie); | ||
292 | |||
293 | *error = EVAS_LOAD_ERROR_NONE; | ||
294 | return EINA_TRUE; | ||
295 | |||
296 | close_file: | ||
297 | E_FCLOSE(f); | ||
298 | return EINA_FALSE; | ||
299 | } | ||
300 | |||
301 | static int | ||
302 | module_open(Evas_Module *em) | ||
303 | { | ||
304 | if (!em) return 0; | ||
305 | em->functions = (void *)(&evas_image_load_png_func); | ||
306 | return 1; | ||
307 | } | ||
308 | |||
309 | static void | ||
310 | module_close(Evas_Module *em __UNUSED__) | ||
311 | { | ||
312 | } | ||
313 | |||
314 | static Evas_Module_Api evas_modapi = | ||
315 | { | ||
316 | EVAS_MODULE_API_VERSION, | ||
317 | "png", | ||
318 | "none", | ||
319 | { | ||
320 | module_open, | ||
321 | module_close | ||
322 | } | ||
323 | }; | ||
324 | |||
325 | EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, png); | ||
326 | |||
327 | #ifndef EVAS_STATIC_BUILD_PNG | ||
328 | EVAS_EINA_MODULE_DEFINE(image_loader, png); | ||
329 | #endif | ||