aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/loaders/tiff/evas_image_load_tiff.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/loaders/tiff/evas_image_load_tiff.c')
-rw-r--r--libraries/evas/src/modules/loaders/tiff/evas_image_load_tiff.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/loaders/tiff/evas_image_load_tiff.c b/libraries/evas/src/modules/loaders/tiff/evas_image_load_tiff.c
new file mode 100644
index 0000000..b9bea91
--- /dev/null
+++ b/libraries/evas/src/modules/loaders/tiff/evas_image_load_tiff.c
@@ -0,0 +1,324 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <sys/types.h>
6#include <stdio.h>
7#include <unistd.h>
8#include <tiffio.h>
9
10#ifdef HAVE_EVIL
11# include <Evil.h>
12#endif
13
14#include "evas_common.h"
15#include "evas_private.h"
16
17static int _evas_loader_tiff_log_dom = -1;
18
19#ifdef ERR
20# undef ERR
21#endif
22#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_tiff_log_dom, __VA_ARGS__)
23
24#ifdef INF
25# undef INF
26#endif
27#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_tiff_log_dom, __VA_ARGS__)
28
29static Eina_Bool evas_image_load_file_head_tiff(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
30static Eina_Bool evas_image_load_file_data_tiff(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
31
32static Evas_Image_Load_Func evas_image_load_tiff_func =
33{
34 EINA_TRUE,
35 evas_image_load_file_head_tiff,
36 evas_image_load_file_data_tiff,
37 NULL
38};
39
40typedef struct TIFFRGBAImage_Extra TIFFRGBAImage_Extra;
41
42struct TIFFRGBAImage_Extra {
43 TIFFRGBAImage rgba;
44 Image_Entry *image;
45 char pper;
46 uint32 num_pixels;
47 uint32 py;
48};
49
50static Eina_Bool
51evas_image_load_file_head_tiff(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
52{
53 char txt[1024];
54 TIFFRGBAImage tiff_image;
55 TIFF *tif = NULL;
56 FILE *ffile;
57 int fd;
58 uint16 magic_number;
59
60 ffile = fopen(file, "rb");
61 if (!ffile)
62 {
63 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
64 return EINA_FALSE;
65 }
66
67 if (fread(&magic_number, sizeof(uint16), 1, ffile) != 1)
68 {
69 fclose(ffile);
70 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
71 return EINA_FALSE;
72 }
73 /* Apparently rewind(f) isn't sufficient */
74 fseek(ffile, 0, SEEK_SET);
75
76 if ((magic_number != TIFF_BIGENDIAN) /* Checks if actually tiff file */
77 && (magic_number != TIFF_LITTLEENDIAN))
78 {
79 fclose(ffile);
80 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
81 return EINA_FALSE;
82 }
83
84 fd = fileno(ffile);
85 fd = dup(fd);
86 lseek(fd, (long)0, SEEK_SET);
87 fclose(ffile);
88
89 tif = TIFFFdOpen(fd, file, "r");
90 if (!tif)
91 {
92 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
93 return EINA_FALSE;
94 }
95
96 strcpy(txt, "Evas Tiff loader: cannot be processed by libtiff");
97 if (!TIFFRGBAImageOK(tif, txt))
98 {
99 TIFFClose(tif);
100 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
101 return EINA_FALSE;
102 }
103 strcpy(txt, "Evas Tiff loader: cannot begin reading tiff");
104 if (!TIFFRGBAImageBegin(& tiff_image, tif, 1, txt))
105 {
106 TIFFClose(tif);
107 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
108 return EINA_FALSE;
109 }
110
111 if (tiff_image.alpha != EXTRASAMPLE_UNSPECIFIED)
112 ie->flags.alpha = 1;
113 if ((tiff_image.width < 1) || (tiff_image.height < 1) ||
114 (tiff_image.width > IMG_MAX_SIZE) || (tiff_image.height > IMG_MAX_SIZE) ||
115 IMG_TOO_BIG(tiff_image.width, tiff_image.height))
116 {
117 TIFFClose(tif);
118 if (IMG_TOO_BIG(tiff_image.width, tiff_image.height))
119 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
120 else
121 *error = EVAS_LOAD_ERROR_GENERIC;
122 return EINA_FALSE;
123 }
124 ie->w = tiff_image.width;
125 ie->h = tiff_image.height;
126
127 TIFFRGBAImageEnd(&tiff_image);
128 TIFFClose(tif);
129 *error = EVAS_LOAD_ERROR_NONE;
130 return EINA_TRUE;
131}
132
133static Eina_Bool
134evas_image_load_file_data_tiff(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
135{
136 char txt[1024];
137 TIFFRGBAImage_Extra rgba_image;
138 TIFF *tif = NULL;
139 FILE *ffile;
140 uint32 *rast = NULL;
141 uint32 num_pixels;
142 int fd, x, y;
143 uint16 magic_number;
144
145 ffile = fopen(file, "rb");
146 if (!ffile)
147 {
148 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
149 return EINA_FALSE;
150 }
151
152 if (fread(&magic_number, sizeof(uint16), 1, ffile) != 1)
153 {
154 fclose(ffile);
155 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
156 return EINA_FALSE;
157 }
158 /* Apparently rewind(f) isn't sufficient */
159 fseek(ffile, (long)0, SEEK_SET);
160
161 if ((magic_number != TIFF_BIGENDIAN) /* Checks if actually tiff file */
162 && (magic_number != TIFF_LITTLEENDIAN))
163 {
164 fclose(ffile);
165 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
166 return EINA_FALSE;
167 }
168
169 fd = fileno(ffile);
170 fd = dup(fd);
171 lseek(fd, (long)0, SEEK_SET);
172 fclose(ffile);
173
174 tif = TIFFFdOpen(fd, file, "r");
175 if (!tif)
176 {
177 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
178 return EINA_FALSE;
179 }
180
181 strcpy(txt, "Evas Tiff loader: cannot be processed by libtiff");
182 if (!TIFFRGBAImageOK(tif, txt))
183 {
184 TIFFClose(tif);
185 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
186 return EINA_FALSE;
187 }
188 strcpy(txt, "Evas Tiff loader: cannot begin reading tiff");
189 if (!TIFFRGBAImageBegin((TIFFRGBAImage *) & rgba_image, tif, 0, txt))
190 {
191 TIFFClose(tif);
192 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
193 return EINA_FALSE;
194 }
195 rgba_image.image = ie;
196
197 if (rgba_image.rgba.alpha != EXTRASAMPLE_UNSPECIFIED)
198 ie->flags.alpha = 1;
199 if ((rgba_image.rgba.width != ie->w) ||
200 (rgba_image.rgba.height != ie->h))
201 {
202 TIFFClose(tif);
203 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
204 return EINA_FALSE;
205 }
206
207 evas_cache_image_surface_alloc(ie, rgba_image.rgba.width, rgba_image.rgba.height);
208 if (!evas_cache_image_pixels(ie))
209 {
210 TIFFRGBAImageEnd((TIFFRGBAImage *) & rgba_image);
211 TIFFClose(tif);
212 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
213 return EINA_FALSE;
214 }
215
216 rgba_image.num_pixels = num_pixels = ie->w * ie->h;
217
218 rgba_image.pper = rgba_image.py = 0;
219 rast = (uint32 *) _TIFFmalloc(sizeof(uint32) * num_pixels);
220
221 if (!rast)
222 {
223 ERR("Evas Tiff loader: out of memory");
224
225 TIFFRGBAImageEnd((TIFFRGBAImage *) & rgba_image);
226 TIFFClose(tif);
227 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
228 return EINA_FALSE;
229 }
230 if (rgba_image.rgba.bitspersample == 8)
231 {
232 if (!TIFFRGBAImageGet((TIFFRGBAImage *) &rgba_image, rast,
233 rgba_image.rgba.width, rgba_image.rgba.height))
234 {
235 _TIFFfree(rast);
236 TIFFRGBAImageEnd((TIFFRGBAImage *) & rgba_image);
237 TIFFClose(tif);
238 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
239 return EINA_FALSE;
240 }
241 }
242 else
243 {
244 INF("channel bits == %i", (int)rgba_image.rgba.samplesperpixel);
245 }
246 /* process rast -> image rgba. really same as prior code anyway just simpler */
247 for (y = 0; y < (int)ie->h; y++)
248 {
249 DATA32 *pix, *pd;
250 uint32 *ps, pixel;
251 unsigned int a, r, g, b;
252
253 pix = evas_cache_image_pixels(ie);
254 pd = pix + ((ie->h - y - 1) * ie->w);
255 ps = rast + (y * ie->w);
256 for (x = 0; x < (int)ie->w; x++)
257 {
258 pixel = *ps;
259 a = TIFFGetA(pixel);
260 r = TIFFGetR(pixel);
261 g = TIFFGetG(pixel);
262 b = TIFFGetB(pixel);
263 if (!ie->flags.alpha) a = 255;
264 if ((rgba_image.rgba.alpha == EXTRASAMPLE_UNASSALPHA) &&
265 (a < 255))
266 {
267 r = (r * (a + 1)) >> 8;
268 g = (g * (a + 1)) >> 8;
269 b = (b * (a + 1)) >> 8;
270 }
271 *pd = ARGB_JOIN(a, r, g, b);
272 ps++;
273 pd++;
274 }
275 }
276
277 _TIFFfree(rast);
278
279 TIFFRGBAImageEnd((TIFFRGBAImage *) & rgba_image);
280
281 TIFFClose(tif);
282
283 evas_common_image_set_alpha_sparse(ie);
284 *error = EVAS_LOAD_ERROR_NONE;
285 return EINA_TRUE;
286}
287
288static int
289module_open(Evas_Module *em)
290{
291 if (!em) return 0;
292 _evas_loader_tiff_log_dom = eina_log_domain_register
293 ("evas-tiff", EVAS_DEFAULT_LOG_COLOR);
294 if (_evas_loader_tiff_log_dom < 0)
295 {
296 EINA_LOG_ERR("Can not create a module log domain.");
297 return 0;
298 }
299 em->functions = (void *)(&evas_image_load_tiff_func);
300 return 1;
301}
302
303static void
304module_close(Evas_Module *em __UNUSED__)
305{
306 eina_log_domain_unregister(_evas_loader_tiff_log_dom);
307}
308
309static Evas_Module_Api evas_modapi =
310{
311 EVAS_MODULE_API_VERSION,
312 "tiff",
313 "none",
314 {
315 module_open,
316 module_close
317 }
318};
319
320EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, tiff);
321
322#ifndef EVAS_STATIC_BUILD_TIFF
323EVAS_EINA_MODULE_DEFINE(image_loader, tiff);
324#endif