move around - flatter.
[profile/ivi/evas.git] / src / modules / loaders / png / evas_image_load_png.c
1 #ifndef _GNU_SOURCE
2 #define _GNU_SOURCE
3 #endif
4
5 #include <png.h>
6 #include <setjmp.h>
7
8 #include "evas_common.h"
9 #include "evas_private.h"
10
11
12 #define PNG_BYTES_TO_CHECK 4
13
14
15 int evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key);
16 int evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key);
17
18 Evas_Image_Load_Func evas_image_load_png_func =
19 {
20   evas_image_load_file_head_png,
21   evas_image_load_file_data_png
22 };
23
24
25 int
26 evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key)
27 {
28    png_uint_32 w32, h32;
29    FILE *f;
30    png_structp png_ptr = NULL;
31    png_infop info_ptr = NULL;
32    int bit_depth, color_type, interlace_type;
33    unsigned char buf[PNG_BYTES_TO_CHECK];
34    char hasa;
35
36    if ((!file)) return 0;
37    hasa = 0;
38    f = fopen(file, "rb");
39    if (!f) return 0;
40
41    /* if we havent read the header before, set the header data */
42    if (fread(buf, PNG_BYTES_TO_CHECK, 1, f) != 1)
43      {
44         fclose(f);
45         return 0;
46      }
47    if (!png_check_sig(buf, PNG_BYTES_TO_CHECK))
48      {
49         fclose(f);
50         return 0;
51      }
52    rewind(f);
53    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
54    if (!png_ptr)
55      {
56         fclose(f);
57         return 0;
58      }
59    info_ptr = png_create_info_struct(png_ptr);
60    if (!info_ptr)
61      {
62         png_destroy_read_struct(&png_ptr, NULL, NULL);
63         fclose(f);
64         return 0;
65      }
66    if (setjmp(png_ptr->jmpbuf))
67      {
68         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
69         fclose(f);
70         return 0;
71      }
72    png_init_io(png_ptr, f);
73    png_read_info(png_ptr, info_ptr);
74    png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32),
75                 (png_uint_32 *) (&h32), &bit_depth, &color_type,
76                 &interlace_type, NULL, NULL);
77    if ((w32 < 1) || (h32 < 1) || (w32 > 8192) || (h32 > 8192))
78      {
79         png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
80         fclose(f);
81         return 0;
82      }
83    ie->w = (int) w32;
84    ie->h = (int) h32;
85    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) hasa = 1;
86    if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) hasa = 1;
87    if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) hasa = 1;
88    if (hasa) ie->flags.alpha = 1;
89    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
90    fclose(f);
91    return 1;
92    key = 0;
93 }
94
95 int
96 evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key)
97 {
98    unsigned char *surface;
99    png_uint_32 w32, h32;
100    int w, h;
101    FILE *f;
102    png_structp png_ptr = NULL;
103    png_infop info_ptr = NULL;
104    int bit_depth, color_type, interlace_type;
105    unsigned char buf[PNG_BYTES_TO_CHECK];
106    unsigned char **lines;
107    char hasa;
108    int i;
109
110    if ((!file)) return 0;
111    hasa = 0;
112    f = fopen(file, "rb");
113    if (!f) return 0;
114
115    /* if we havent read the header before, set the header data */
116    fread(buf, 1, PNG_BYTES_TO_CHECK, f);
117    if (!png_check_sig(buf, PNG_BYTES_TO_CHECK))
118      {
119         fclose(f);
120         return 0;
121      }
122    rewind(f);
123    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
124    if (!png_ptr)
125      {
126         fclose(f);
127         return 0;
128      }
129    info_ptr = png_create_info_struct(png_ptr);
130    if (!info_ptr)
131      {
132         png_destroy_read_struct(&png_ptr, NULL, NULL);
133         fclose(f);
134         return 0;
135      }
136    if (setjmp(png_ptr->jmpbuf))
137      {
138         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
139         fclose(f);
140         return 0;
141      }
142    png_init_io(png_ptr, f);
143    png_read_info(png_ptr, info_ptr);
144    png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32),
145                 (png_uint_32 *) (&h32), &bit_depth, &color_type,
146                 &interlace_type, NULL, NULL);
147    evas_cache_image_surface_alloc(ie, w32, h32);
148    surface = (unsigned char *) evas_cache_image_pixels(ie);
149    if (!surface)
150      {
151         png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
152         fclose(f);
153         return 0;
154      }
155    if ((w32 != ie->w) || (h32 != ie->h))
156      {
157         png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
158         fclose(f);
159         return 0;
160      }
161    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) hasa = 1;
162    if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) hasa = 1;
163    if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) hasa = 1;
164    if (hasa) ie->flags.alpha = 1;
165
166    /* Prep for transformations...  ultimately we want ARGB */
167    /* expand palette -> RGB if necessary */
168    if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
169    /* expand gray (w/reduced bits) -> 8-bit RGB if necessary */
170    if ((color_type == PNG_COLOR_TYPE_GRAY) ||
171        (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
172      {
173         png_set_gray_to_rgb(png_ptr);
174         if (bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
175      }
176    /* expand transparency entry -> alpha channel if present */
177    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
178      png_set_tRNS_to_alpha(png_ptr);
179    /* reduce 16bit color -> 8bit color if necessary */
180    if (bit_depth > 8) png_set_strip_16(png_ptr);
181    /* pack all pixels to byte boundaries */
182    png_set_packing(png_ptr);
183
184    w = ie->w;
185    h = ie->h;
186    /* we want ARGB */
187 #ifdef WORDS_BIGENDIAN
188    png_set_swap_alpha(png_ptr);
189    if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
190 #else
191    png_set_bgr(png_ptr);
192    if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
193 #endif
194    lines = (unsigned char **) alloca(h * sizeof(unsigned char *));
195
196    for (i = 0; i < h; i++)
197      lines[i] = surface + (i * w * sizeof(DATA32));
198    png_read_image(png_ptr, lines);
199    png_read_end(png_ptr, info_ptr);
200    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
201    fclose(f);
202    evas_common_image_premul(ie);
203
204    return 1;
205    key = 0;
206 }
207
208 EAPI int
209 module_open(Evas_Module *em)
210 {
211    if (!em) return 0;
212    em->functions = (void *)(&evas_image_load_png_func);
213    return 1;
214 }
215
216 EAPI void
217 module_close(void)
218 {
219    
220 }
221
222 EAPI Evas_Module_Api evas_modapi =
223 {
224    EVAS_MODULE_API_VERSION,
225      EVAS_MODULE_TYPE_IMAGE_LOADER,
226      "png",
227      "none"
228 };