aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/savers/png/evas_image_save_png.c
diff options
context:
space:
mode:
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.c193
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
24static int evas_image_save_file_png(RGBA_Image *im, const char *file, const char *key, int quality, int compress);
25
26static Evas_Image_Save_Func evas_image_save_png_func =
27{
28 evas_image_save_file_png
29};
30
31static int
32save_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
158static int
159evas_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
164static int
165module_open(Evas_Module *em)
166{
167 if (!em) return 0;
168 em->functions = (void *)(&evas_image_save_png_func);
169 return 1;
170}
171
172static void
173module_close(Evas_Module *em __UNUSED__)
174{
175}
176
177static 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
188EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_SAVER, image_saver, png);
189
190#ifndef EVAS_STATIC_BUILD_PNG
191EVAS_EINA_MODULE_DEFINE(image_saver, png);
192#endif
193