diff options
Diffstat (limited to 'libraries/evas/src/modules/savers/png/evas_image_save_png.c')
-rw-r--r-- | libraries/evas/src/modules/savers/png/evas_image_save_png.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/savers/png/evas_image_save_png.c b/libraries/evas/src/modules/savers/png/evas_image_save_png.c new file mode 100644 index 0000000..734890c --- /dev/null +++ b/libraries/evas/src/modules/savers/png/evas_image_save_png.c | |||
@@ -0,0 +1,193 @@ | |||
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_FCLOSE(stream) evil_fclose_native(stream) | ||
16 | #else | ||
17 | # define E_FOPEN(file, mode) fopen((file), (mode)) | ||
18 | # define E_FCLOSE(stream) fclose(stream) | ||
19 | #endif | ||
20 | |||
21 | #include "evas_common.h" | ||
22 | #include "evas_private.h" | ||
23 | |||
24 | static int evas_image_save_file_png(RGBA_Image *im, const char *file, const char *key, int quality, int compress); | ||
25 | |||
26 | static Evas_Image_Save_Func evas_image_save_png_func = | ||
27 | { | ||
28 | evas_image_save_file_png | ||
29 | }; | ||
30 | |||
31 | static int | ||
32 | save_image_png(RGBA_Image *im, const char *file, int do_compress, int interlace) | ||
33 | { | ||
34 | FILE *f; | ||
35 | png_structp png_ptr; | ||
36 | png_infop info_ptr; | ||
37 | DATA32 *ptr, *data = NULL; | ||
38 | unsigned int x, y, j; | ||
39 | png_bytep row_ptr, png_data = NULL; | ||
40 | png_color_8 sig_bit; | ||
41 | int num_passes = 1, pass; | ||
42 | |||
43 | if (!im || !im->image.data || !file) | ||
44 | return 0; | ||
45 | |||
46 | f = E_FOPEN(file, "wb"); | ||
47 | if (!f) return 0; | ||
48 | |||
49 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | ||
50 | if (!png_ptr) | ||
51 | goto close_file; | ||
52 | |||
53 | info_ptr = png_create_info_struct(png_ptr); | ||
54 | if (!info_ptr) | ||
55 | { | ||
56 | png_destroy_write_struct(&png_ptr, NULL); | ||
57 | goto close_file; | ||
58 | } | ||
59 | if (setjmp(png_jmpbuf(png_ptr))) | ||
60 | { | ||
61 | png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); | ||
62 | png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); | ||
63 | goto close_file; | ||
64 | } | ||
65 | |||
66 | if (interlace) | ||
67 | { | ||
68 | #ifdef PNG_WRITE_INTERLACING_SUPPORTED | ||
69 | interlace = PNG_INTERLACE_ADAM7; | ||
70 | #else | ||
71 | interlace = PNG_INTERLACE_NONE; | ||
72 | #endif | ||
73 | } | ||
74 | else | ||
75 | interlace = PNG_INTERLACE_NONE; | ||
76 | |||
77 | if (im->cache_entry.flags.alpha) | ||
78 | { | ||
79 | data = malloc(im->cache_entry.w * im->cache_entry.h * sizeof(DATA32)); | ||
80 | if (!data) | ||
81 | { | ||
82 | png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); | ||
83 | png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); | ||
84 | goto close_file; | ||
85 | } | ||
86 | memcpy(data, im->image.data, im->cache_entry.w * im->cache_entry.h * sizeof(DATA32)); | ||
87 | evas_common_convert_argb_unpremul(data, im->cache_entry.w * im->cache_entry.h); | ||
88 | png_init_io(png_ptr, f); | ||
89 | png_set_IHDR(png_ptr, info_ptr, im->cache_entry.w, im->cache_entry.h, 8, | ||
90 | PNG_COLOR_TYPE_RGB_ALPHA, interlace, | ||
91 | PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); | ||
92 | #ifdef WORDS_BIGENDIAN | ||
93 | png_set_swap_alpha(png_ptr); | ||
94 | #else | ||
95 | png_set_bgr(png_ptr); | ||
96 | #endif | ||
97 | } | ||
98 | else | ||
99 | { | ||
100 | data = im->image.data; | ||
101 | png_init_io(png_ptr, f); | ||
102 | png_set_IHDR(png_ptr, info_ptr, im->cache_entry.w, im->cache_entry.h, 8, | ||
103 | PNG_COLOR_TYPE_RGB, interlace, | ||
104 | PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); | ||
105 | png_data = alloca(im->cache_entry.w * 3 * sizeof(char)); | ||
106 | } | ||
107 | sig_bit.red = 8; | ||
108 | sig_bit.green = 8; | ||
109 | sig_bit.blue = 8; | ||
110 | sig_bit.alpha = 8; | ||
111 | png_set_sBIT(png_ptr, info_ptr, &sig_bit); | ||
112 | |||
113 | png_set_compression_level(png_ptr, do_compress); | ||
114 | png_write_info(png_ptr, info_ptr); | ||
115 | png_set_shift(png_ptr, &sig_bit); | ||
116 | png_set_packing(png_ptr); | ||
117 | |||
118 | #ifdef PNG_WRITE_INTERLACING_SUPPORTED | ||
119 | num_passes = png_set_interlace_handling(png_ptr); | ||
120 | #endif | ||
121 | |||
122 | for (pass = 0; pass < num_passes; pass++) | ||
123 | { | ||
124 | ptr = data; | ||
125 | |||
126 | for (y = 0; y < im->cache_entry.h; y++) | ||
127 | { | ||
128 | if (im->cache_entry.flags.alpha) | ||
129 | row_ptr = (png_bytep) ptr; | ||
130 | else | ||
131 | { | ||
132 | for (j = 0, x = 0; x < im->cache_entry.w; x++) | ||
133 | { | ||
134 | png_data[j++] = (ptr[x] >> 16) & 0xff; | ||
135 | png_data[j++] = (ptr[x] >> 8) & 0xff; | ||
136 | png_data[j++] = (ptr[x]) & 0xff; | ||
137 | } | ||
138 | row_ptr = (png_bytep) png_data; | ||
139 | } | ||
140 | png_write_rows(png_ptr, &row_ptr, 1); | ||
141 | ptr += im->cache_entry.w; | ||
142 | } | ||
143 | } | ||
144 | png_write_end(png_ptr, info_ptr); | ||
145 | png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); | ||
146 | png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); | ||
147 | |||
148 | if (im->cache_entry.flags.alpha) | ||
149 | free(data); | ||
150 | E_FCLOSE(f); | ||
151 | return 1; | ||
152 | |||
153 | close_file: | ||
154 | E_FCLOSE(f); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int | ||
159 | evas_image_save_file_png(RGBA_Image *im, const char *file, const char *key __UNUSED__, int quality __UNUSED__, int do_compress) | ||
160 | { | ||
161 | return save_image_png(im, file, do_compress, 0); | ||
162 | } | ||
163 | |||
164 | static int | ||
165 | module_open(Evas_Module *em) | ||
166 | { | ||
167 | if (!em) return 0; | ||
168 | em->functions = (void *)(&evas_image_save_png_func); | ||
169 | return 1; | ||
170 | } | ||
171 | |||
172 | static void | ||
173 | module_close(Evas_Module *em __UNUSED__) | ||
174 | { | ||
175 | } | ||
176 | |||
177 | static Evas_Module_Api evas_modapi = | ||
178 | { | ||
179 | EVAS_MODULE_API_VERSION, | ||
180 | "png", | ||
181 | "none", | ||
182 | { | ||
183 | module_open, | ||
184 | module_close | ||
185 | } | ||
186 | }; | ||
187 | |||
188 | EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_SAVER, image_saver, png); | ||
189 | |||
190 | #ifndef EVAS_STATIC_BUILD_PNG | ||
191 | EVAS_EINA_MODULE_DEFINE(image_saver, png); | ||
192 | #endif | ||
193 | |||