summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2013-09-28 14:28:41 +0200
committerCedric Bail <cedric.bail@samsung.com>2013-10-01 16:38:44 +0900
commit3b8b2ac66c10be49a85ec2dad2d54082fe47742f (patch)
tree5eb31d7c7cdb754c1da5d5efa882ab7e15d5d315 /src/modules
parent83eaf14f32e3fb804b97906af6e0af70303bf24b (diff)
evas: add JPEG 2000 loader.
This add finally support for JPEG 2000, but be aware that libopenjpeg is very badly managed. There is currently only version 1.5.x that does provide the right files, is usable by a third party and portable. You can seriously forget any other version.
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/evas/loaders/jp2k/evas_image_load_jp2k.c409
1 files changed, 409 insertions, 0 deletions
diff --git a/src/modules/evas/loaders/jp2k/evas_image_load_jp2k.c b/src/modules/evas/loaders/jp2k/evas_image_load_jp2k.c
new file mode 100644
index 0000000000..28200cee0a
--- /dev/null
+++ b/src/modules/evas/loaders/jp2k/evas_image_load_jp2k.c
@@ -0,0 +1,409 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6
7#ifdef HAVE_EVIL
8# include <Evil.h>
9#endif
10
11#include <openjpeg.h>
12
13#include "Evas_Loader.h"
14
15static int _evas_loader_jp2k_log_dom = -1;
16
17#ifdef ERR
18# undef ERR
19#endif
20#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_jp2k_log_dom, __VA_ARGS__)
21
22#ifdef WRN
23# undef WRN
24#endif
25#define WRN(...) EINA_LOG_DOM_WARN(_evas_loader_jp2k_log_dom, __VA_ARGS__)
26
27#ifdef INF
28# undef INF
29#endif
30#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_jp2k_log_dom, __VA_ARGS__)
31
32typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
33struct _Evas_Loader_Internal
34{
35 Eina_File *f;
36 Evas_Image_Load_Opts *opts;
37};
38
39static void
40_jp2k_error_cb(const char *msg, void *data EINA_UNUSED)
41{
42 ERR("OpenJPEG internal error: '%s'.", msg);
43}
44
45static void
46_jp2k_warning_cb(const char *msg, void *data EINA_UNUSED)
47{
48 WRN("OpenJPEG internal warning: '%s'.", msg);
49}
50
51static void
52_jp2k_info_cb(const char *msg, void *data EINA_UNUSED)
53{
54 INF("OpenJPEG internal information: '%s'.", msg);
55}
56
57static Eina_Bool
58evas_image_load_file_head_jp2k_internal(unsigned int *w, unsigned int *h,
59 unsigned char *alpha,
60 Evas_Image_Load_Opts *opts EINA_UNUSED,
61 void *map, size_t length,
62 int *error)
63{
64 opj_event_mgr_t event_mgr;
65 opj_dparameters_t params;
66 opj_dinfo_t *info;
67 opj_cio_t *cio;
68 opj_image_t *image;
69 int format;
70 int k;
71
72 if (length < 2)
73 {
74 *error = EVAS_LOAD_ERROR_GENERIC;
75 return EINA_FALSE;
76 }
77
78 if (((unsigned char *)map)[0] == 0xFF && ((unsigned char *)map)[1] == 0x4F)
79 format = CODEC_J2K;
80 else
81 format = CODEC_JP2;
82
83 memset(&event_mgr, 0, sizeof(event_mgr));
84 event_mgr.error_handler = _jp2k_error_cb;
85 event_mgr.warning_handler = _jp2k_warning_cb;
86 event_mgr.info_handler = _jp2k_info_cb;
87
88 opj_set_default_decoder_parameters(&params);
89 info = opj_create_decompress(format);
90 if (!info)
91 {
92 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
93 return EINA_FALSE;
94 }
95 opj_set_event_mgr((opj_common_ptr)info, &event_mgr, NULL);
96 opj_setup_decoder(info, &params);
97
98 cio = opj_cio_open((opj_common_ptr)info, map, length);
99 if (!cio)
100 {
101 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
102 return EINA_FALSE;
103 }
104
105 image = opj_decode(info, cio);
106 if (!image)
107 {
108 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
109 return EINA_FALSE;
110 }
111
112 for (k = 1; k < image->numcomps; k++)
113 {
114 if (image->comps[k].w != image->comps[0].w)
115 goto free_image;
116 if (image->comps[k].h != image->comps[0].h)
117 goto free_image;
118 if (image->comps[k].prec > 8)
119 goto free_image;
120 }
121
122 *w = image->comps[0].w;
123 *h = image->comps[0].h;
124 *alpha = ((image->numcomps == 4) || (image->numcomps == 2)) ? 1 : 0;
125 *error = EVAS_LOAD_ERROR_NONE;
126
127 opj_image_destroy(image);
128 opj_cio_close(cio);
129 opj_destroy_decompress(info);
130
131 return EINA_TRUE;
132
133 free_image:
134 *error = EVAS_LOAD_ERROR_GENERIC;
135 opj_image_destroy(image);
136 opj_cio_close(cio);
137 opj_destroy_decompress(info);
138
139 return EINA_FALSE;
140}
141
142static Eina_Bool
143evas_image_load_file_data_jp2k_internal(Evas_Image_Load_Opts *opts EINA_UNUSED,
144 Evas_Image_Property *prop EINA_UNUSED,
145 void *pixels,
146 void *map, size_t length,
147 int *error)
148{
149 opj_dparameters_t params;
150 opj_dinfo_t *info;
151 opj_cio_t *cio;
152 opj_image_t *image;
153 unsigned int *iter;
154 int format;
155 int idx;
156
157 if (((unsigned char *)map)[0] == 0xFF && ((unsigned char *)map)[1] == 0x4F)
158 format = CODEC_J2K;
159 else
160 format = CODEC_JP2;
161
162 opj_set_default_decoder_parameters(&params);
163 info = opj_create_decompress(format);
164 opj_set_event_mgr((opj_common_ptr)info, NULL, NULL);
165 opj_setup_decoder(info, &params);
166 cio = opj_cio_open((opj_common_ptr)info, map, length);
167 image = opj_decode(info, cio);
168
169 iter = pixels;
170 idx = 0;
171
172 /*
173 * FIXME:
174 * image->numcomps == 4, image->color_space == CLRSPC_SYCC : YUV
175 */
176 /* BGR(A) */
177 if ((image->numcomps >= 3) &&
178 (image->comps[0].dx == image->comps[1].dx) &&
179 (image->comps[1].dx == image->comps[2].dx) &&
180 (image->comps[0].dy == image->comps[1].dy) &&
181 (image->comps[1].dy == image->comps[2].dy))
182 {
183 int a;
184 int r;
185 int g;
186 int b;
187 int i;
188 int j;
189
190 for (j = 0; j < image->comps[0].h; j++)
191 {
192 for (i = 0; i < image->comps[0].w; i++, idx++, iter++)
193 {
194 r = image->comps[0].data[idx];
195 r+= (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
196 if (r > 255) r = 255;
197 if (r < 0) r = 0;
198
199 g = image->comps[1].data[idx];
200 g+= (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
201 if (g > 255) g = 255;
202 if (g < 0) g = 0;
203
204 b = image->comps[2].data[idx];
205 b+= (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
206 if (b > 255) b = 255;
207 if (b < 0) b = 0;
208
209 if (image->numcomps == 4)
210 {
211 a = image->comps[3].data[idx];
212 a+= (image->comps[3].sgnd ? 1 << (image->comps[3].prec - 1) : 0);
213 if (a > 255) a = 255;
214 if (a < 0) a = 0;
215 }
216 else
217 a = 255;
218
219 *iter = a << 24 | r << 16 | g << 8 | b;
220 }
221 }
222 }
223 /* *GRAY(A) */
224 else if (((image->numcomps == 1) || (image->numcomps == 2)) &&
225 (image->comps[0].dx == image->comps[1].dx) &&
226 (image->comps[1].dx == image->comps[2].dx) &&
227 (image->comps[0].dy == image->comps[1].dy) &&
228 (image->comps[1].dy == image->comps[2].dy))
229 {
230 int a;
231 int g;
232 int i;
233 int j;
234
235 for (j = 0; j < image->comps[0].h; j++)
236 {
237 for (i = 0; i < image->comps[0].w; i++, idx++, iter++)
238 {
239 g = image->comps[0].data[idx];
240 g+= (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
241 if (g > 255) g = 255;
242 if (g < 0) g = 0;
243
244 if (image->numcomps == 2)
245 {
246 a = image->comps[1].data[idx];
247 a+= (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
248 if (a > 255) a = 255;
249 if (a < 0) a = 0;
250 }
251 else
252 a = 255;
253
254 *iter = a << 24 | g << 16 | g << 8 | g;
255 }
256 }
257 }
258
259 opj_image_destroy(image);
260 opj_cio_close(cio);
261 opj_destroy_decompress(info);
262
263 *error = EVAS_LOAD_ERROR_NONE;
264 return EINA_TRUE;
265}
266
267static void *
268evas_image_load_file_open_jp2k(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
269 Evas_Image_Load_Opts *opts,
270 Evas_Image_Animated *animated EINA_UNUSED,
271 int *error)
272{
273 Evas_Loader_Internal *loader;
274
275 loader = calloc(1, sizeof (Evas_Loader_Internal));
276 if (!loader)
277 {
278 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
279 return NULL;
280 }
281
282 loader->f = f;
283 loader->opts = opts;
284
285 return loader;
286}
287
288static void
289evas_image_load_file_close_jp2k(void *loader_data)
290{
291 free(loader_data);
292}
293
294static Eina_Bool
295evas_image_load_file_head_jp2k(void *loader_data,
296 Evas_Image_Property *prop,
297 int *error)
298{
299 Evas_Loader_Internal *loader = loader_data;
300 Evas_Image_Load_Opts *opts;
301 Eina_File *f;
302 void *map;
303 Eina_Bool val;
304
305 opts = loader->opts;
306 f = loader->f;
307
308 map = eina_file_map_all(f, EINA_FILE_RANDOM);
309 if (!map)
310 {
311 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
312 return EINA_FALSE;
313 }
314
315 val = evas_image_load_file_head_jp2k_internal(&prop->w, &prop->h,
316 &prop->alpha,
317 opts,
318 map, eina_file_size_get(f),
319 error);
320
321 eina_file_map_free(f, map);
322
323 return val;
324}
325
326static Eina_Bool
327evas_image_load_file_data_jp2k(void *loader_data,
328 Evas_Image_Property *prop,
329 void *pixels,
330 int *error)
331{
332 Evas_Loader_Internal *loader = loader_data;
333 Evas_Image_Load_Opts *opts;
334 Eina_File *f;
335 void *map;
336 Eina_Bool val = EINA_FALSE;
337
338 f = loader->f;
339 opts = loader->opts;
340
341 map = eina_file_map_all(f, EINA_FILE_WILLNEED);
342 if (!map)
343 {
344 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
345 goto on_error;
346 }
347
348 val = evas_image_load_file_data_jp2k_internal(opts, prop, pixels,
349 map, eina_file_size_get(f),
350 error);
351
352 eina_file_map_free(f, map);
353
354 on_error:
355 return val;
356}
357
358static Evas_Image_Load_Func evas_image_load_jp2k_func =
359{
360 evas_image_load_file_open_jp2k,
361 evas_image_load_file_close_jp2k,
362 evas_image_load_file_head_jp2k,
363 evas_image_load_file_data_jp2k,
364 NULL,
365 EINA_TRUE,
366 EINA_TRUE
367};
368
369static int
370module_open(Evas_Module *em)
371{
372 if (!em) return 0;
373
374 _evas_loader_jp2k_log_dom = eina_log_domain_register("evas-jp2k", EINA_COLOR_BLUE);
375 if (_evas_loader_jp2k_log_dom < 0)
376 {
377 EINA_LOG_ERR("Can not create a module log domain.");
378 return 0;
379 }
380
381 em->functions = (void *)(&evas_image_load_jp2k_func);
382
383 return 1;
384}
385
386static void
387module_close(Evas_Module *em EINA_UNUSED)
388{
389 eina_log_domain_unregister(_evas_loader_jp2k_log_dom);
390 _evas_loader_jp2k_log_dom = -1;
391}
392
393static Evas_Module_Api evas_modapi =
394{
395 EVAS_MODULE_API_VERSION,
396 "jp2k",
397 "none",
398 {
399 module_open,
400 module_close
401 }
402};
403
404EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, jp2k);
405
406#ifndef EVAS_STATIC_BUILD_JP2K
407EVAS_EINA_MODULE_DEFINE(image_loader, jp2k);
408#endif
409