summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2017-08-08 11:32:47 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2017-08-08 11:46:35 +0900
commitdb29ee1cd686f4d58f1a13eb8eb0177d5ddd8be8 (patch)
tree383ba3af7b59a129a3168c9b2c439a6ba395ae81
parentd5ad85abaed3170b86c7915e9ba2ef2e6dae643b (diff)
Evas Jpeg2000 loader: port it to openjpeg 2.*
Test Plan: files in https://github.com/uclouvain/openjpeg-data/tree/master/baseline/nonregression Reviewers: jpeg, raster, cedric Differential Revision: https://phab.enlightenment.org/D5033
-rw-r--r--m4/evas_check_loader.m416
-rw-r--r--src/modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c306
2 files changed, 208 insertions, 114 deletions
diff --git a/m4/evas_check_loader.m4 b/m4/evas_check_loader.m4
index b574931..3ac4d59 100644
--- a/m4/evas_check_loader.m4
+++ b/m4/evas_check_loader.m4
@@ -273,7 +273,7 @@ AC_CHECK_HEADER([openjpeg.h], [have_dep="yes"])
273 273
274if test "x${have_dep}" = "xyes" ; then 274if test "x${have_dep}" = "xyes" ; then
275 AC_CHECK_LIB([openjp2], 275 AC_CHECK_LIB([openjp2],
276 [opj_cio_open], 276 [opj_stream_create],
277 [ 277 [
278 evas_image_loader_[]$1[]_libs="-lopenjp2" 278 evas_image_loader_[]$1[]_libs="-lopenjp2"
279 have_dep="yes" 279 have_dep="yes"
@@ -282,21 +282,11 @@ if test "x${have_dep}" = "xyes" ; then
282fi 282fi
283 283
284if test "x${have_dep}" = "xno" ; then 284if test "x${have_dep}" = "xno" ; then
285 PKG_CHECK_EXISTS([libopenjpeg1 >= 1.5], 285 PKG_CHECK_EXISTS([libopenjp2 >= 2.0],
286 [ 286 [
287 have_dep="yes" 287 have_dep="yes"
288 have_dep_pc="yes" 288 have_dep_pc="yes"
289 requirement="libopenjpeg1 >= 1.5" 289 requirement="libopenjp2 >= 2.0"
290 ],
291 [have_dep="no"])
292fi
293
294if test "x${have_dep}" = "xno" ; then
295 PKG_CHECK_EXISTS([libopenjpeg >= 1.5],
296 [
297 have_dep="yes"
298 have_dep_pc="yes"
299 requirement="libopenjpeg >= 1.5"
300 ], 290 ],
301 [have_dep="no"]) 291 [have_dep="no"])
302fi 292fi
diff --git a/src/modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c b/src/modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c
index a4ed273..fb3fdff 100644
--- a/src/modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c
+++ b/src/modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c
@@ -29,148 +29,257 @@ static int _evas_loader_jp2k_log_dom = -1;
29#endif 29#endif
30#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_jp2k_log_dom, __VA_ARGS__) 30#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_jp2k_log_dom, __VA_ARGS__)
31 31
32#define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
33#define JP2_MAGIC "\x0d\x0a\x87\x0a"
34#define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
35
36typedef struct
37{
38 unsigned char *base;
39 size_t length;
40 size_t idx;
41} Map_St;
42
32typedef struct _Evas_Loader_Internal Evas_Loader_Internal; 43typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
33struct _Evas_Loader_Internal 44struct _Evas_Loader_Internal
34{ 45{
35 Eina_File *f; 46 Eina_File *f;
36 Evas_Image_Load_Opts *opts; 47 Evas_Image_Load_Opts *opts;
37}; 48};
38 49
39static void 50static void
40_jp2k_error_cb(const char *msg EINA_UNUSED, void *data EINA_UNUSED) 51_jp2k_quiet_callback(const char *msg, void *client_data)
41{ 52{
42// ERR("OpenJPEG internal error: '%s'.", msg); 53 (void)msg;
54 (void)client_data;
43} 55}
44 56
45static void 57static OPJ_SIZE_T
46_jp2k_warning_cb(const char *msg EINA_UNUSED, void *data EINA_UNUSED) 58_jp2k_read_fn(void *buf, OPJ_SIZE_T size, void *data)
47{ 59{
48// WRN("OpenJPEG internal warning: '%s'.", msg); 60 Map_St *map = data;
61 OPJ_SIZE_T offset;
62
63 offset = map->length - map->idx;
64 if (offset == 0)
65 return (OPJ_SIZE_T)-1;
66 if (offset > size)
67 offset = size;
68 memcpy(buf, map->base + map->idx, offset);
69 map->idx += offset;
70
71 return offset;
49} 72}
50 73
51static void 74static OPJ_OFF_T
52_jp2k_info_cb(const char *msg EINA_UNUSED, void *data EINA_UNUSED) 75_jp2k_seek_cur_fn(OPJ_OFF_T size, void *data)
53{ 76{
54// INF("OpenJPEG internal information: '%s'.", msg); 77 Map_St *map = data;
78
79 if (size > (OPJ_OFF_T)(map->length - map->idx))
80 size = (OPJ_OFF_T)(map->length - map->idx);
81
82 map->idx += size;
83
84 return map->idx;
85}
86
87static OPJ_BOOL
88_jp2k_seek_set_fn(OPJ_OFF_T size, void *data)
89{
90 Map_St *map = data;
91
92 if (size > (OPJ_OFF_T)map->length)
93 return OPJ_FALSE;
94
95 map->idx = size;
96
97 return OPJ_TRUE;
55} 98}
56 99
57static Eina_Bool 100static Eina_Bool
58evas_image_load_file_head_jp2k_internal(unsigned int *w, unsigned int *h, 101evas_image_load_file_head_jp2k_internal(unsigned int *w, unsigned int *h,
59 unsigned char *alpha, 102 unsigned char *alpha,
60 Evas_Image_Load_Opts *opts EINA_UNUSED,
61 void *map, size_t length, 103 void *map, size_t length,
62 int *error) 104 int *error)
63{ 105{
64 opj_event_mgr_t event_mgr; 106 Map_St map_st;
65 opj_dparameters_t params; 107 opj_dparameters_t core;
66 opj_dinfo_t *info; 108 opj_codec_t *codec;
67 opj_cio_t *cio; 109 opj_stream_t *st;
68 opj_image_t *image; 110 opj_image_t* image;
69 int format; 111 OPJ_CODEC_FORMAT cfmt;
70 int k; 112
71 const unsigned char sig_j2k[2] = 113 map_st.base = map;
72 { 0xff, 0x4f }; 114 map_st.length = length;
73 const unsigned char sig_jp2[10] = 115 map_st.idx = 0;
74 { 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a }; 116
75 117 /* default parameters */
76 if (length < 2) 118 memset(&core, 0, sizeof(opj_dparameters_t));
119 opj_set_default_decoder_parameters(&core);
120
121 /* magic check */
122 cfmt = OPJ_CODEC_UNKNOWN;
123 if (map_st.length >= 4)
77 { 124 {
125 if (memcmp(map_st.base, J2K_CODESTREAM_MAGIC, 4) == 0)
126 cfmt = OPJ_CODEC_J2K;
127 else if ((memcmp(map_st.base, JP2_MAGIC, 4) == 0) ||
128 ((map_st.length >= 12) && (memcmp(map_st.base, JP2_RFC3745_MAGIC, 12) == 0)))
129 cfmt = OPJ_CODEC_JP2;
130 }
131
132 if (cfmt == OPJ_CODEC_UNKNOWN)
133 {
134 ERR("jpeg200 file format invalid");
78 *error = EVAS_LOAD_ERROR_GENERIC; 135 *error = EVAS_LOAD_ERROR_GENERIC;
79 return EINA_FALSE; 136 return EINA_FALSE;
80 } 137 }
81 138
82 if ((length >= 2) && (!memcmp(map, sig_j2k, 2))) format = CODEC_J2K; 139 /* codec */
83 else if ((length >= 10) && (!memcmp(map, sig_jp2, 10))) format = CODEC_JP2; 140 codec = opj_create_decompress(cfmt);
84 else return EINA_FALSE; 141 if (!codec)
85
86 memset(&event_mgr, 0, sizeof(event_mgr));
87 event_mgr.error_handler = _jp2k_error_cb;
88 event_mgr.warning_handler = _jp2k_warning_cb;
89 event_mgr.info_handler = _jp2k_info_cb;
90
91 opj_set_default_decoder_parameters(&params);
92 info = opj_create_decompress(format);
93 if (!info)
94 { 142 {
143 ERR("can't create codec");
95 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; 144 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
96 return EINA_FALSE; 145 return EINA_FALSE;
97 } 146 }
98 opj_set_event_mgr((opj_common_ptr)info, &event_mgr, NULL); 147 opj_set_info_handler(codec, _jp2k_quiet_callback, NULL);
99 opj_setup_decoder(info, &params); 148 opj_set_warning_handler(codec, _jp2k_quiet_callback, NULL);
100 149 opj_set_error_handler(codec, _jp2k_quiet_callback, NULL);
101 cio = opj_cio_open((opj_common_ptr)info, map, length); 150 if (!opj_setup_decoder(codec, &core))
102 if (!cio)
103 { 151 {
152 ERR("can't setup decoder");
153 opj_destroy_codec(codec);
104 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; 154 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
105 return EINA_FALSE; 155 return EINA_FALSE;
106 } 156 }
157 //opj_codec_set_threads(codec, 0)
107 158
108 image = opj_decode(info, cio); 159 /* stream */
109 if (!image) 160 st = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, OPJ_TRUE);
161 if (!st)
110 { 162 {
163 ERR("can't create stream");
164 opj_destroy_codec(codec);
111 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; 165 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
112 return EINA_FALSE; 166 return EINA_FALSE;
113 } 167 }
114 168
115 for (k = 1; k < image->numcomps; k++) 169 opj_stream_set_user_data(st, &map_st, NULL);
116 { 170 opj_stream_set_user_data_length(st, map_st.length);
117 if (image->comps[k].w != image->comps[0].w) 171 opj_stream_set_read_function(st, _jp2k_read_fn);
118 goto free_image; 172 opj_stream_set_skip_function(st, _jp2k_seek_cur_fn);
119 if (image->comps[k].h != image->comps[0].h) 173 opj_stream_set_seek_function(st, _jp2k_seek_set_fn);
120 goto free_image; 174
121 if (image->comps[k].prec > 8) 175 opj_read_header(st, codec, &image);
122 goto free_image; 176 *w = image->x1 - image->x0;
123 } 177 *h = image->y1 - image->y0;
124
125 *w = image->comps[0].w;
126 *h = image->comps[0].h;
127 *alpha = ((image->numcomps == 4) || (image->numcomps == 2)) ? 1 : 0; 178 *alpha = ((image->numcomps == 4) || (image->numcomps == 2)) ? 1 : 0;
128 *error = EVAS_LOAD_ERROR_NONE; 179 *error = EVAS_LOAD_ERROR_NONE;
129 180
130 opj_image_destroy(image); 181 opj_image_destroy(image);
131 opj_cio_close(cio); 182 opj_stream_destroy(st);
132 opj_destroy_decompress(info); 183 opj_destroy_codec(codec);
133 184
134 return EINA_TRUE; 185 return EINA_TRUE;
135
136 free_image:
137 *error = EVAS_LOAD_ERROR_GENERIC;
138 opj_image_destroy(image);
139 opj_cio_close(cio);
140 opj_destroy_decompress(info);
141
142 return EINA_FALSE;
143} 186}
144 187
145static Eina_Bool 188static Eina_Bool
146evas_image_load_file_data_jp2k_internal(Evas_Image_Load_Opts *opts EINA_UNUSED, 189evas_image_load_file_data_jp2k_internal(void *pixels,
147 Evas_Image_Property *prop EINA_UNUSED,
148 void *pixels,
149 void *map, size_t length, 190 void *map, size_t length,
150 int *error) 191 int *error)
151{ 192{
152 opj_dparameters_t params; 193 Map_St map_st;
153 opj_dinfo_t *info; 194 opj_dparameters_t core;
154 opj_cio_t *cio; 195 opj_codec_t *codec;
155 opj_image_t *image; 196 opj_stream_t *st;
197 opj_image_t* image;
156 unsigned int *iter; 198 unsigned int *iter;
157 int format; 199 OPJ_CODEC_FORMAT cfmt;
158 int idx; 200 int idx;
159 const unsigned char sig_j2k[2] = 201
160 { 0xff, 0x4f }; 202 map_st.base = map;
161 const unsigned char sig_jp2[10] = 203 map_st.length = length;
162 { 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a }; 204 map_st.idx = 0;
163 205
164 if ((length >= 2) && (!memcmp(map, sig_j2k, 2))) format = CODEC_J2K; 206 /* default parameters */
165 else if ((length >= 10) && (!memcmp(map, sig_jp2, 10))) format = CODEC_JP2; 207 memset(&core, 0, sizeof(opj_dparameters_t));
166 else return EINA_FALSE; 208 opj_set_default_decoder_parameters(&core);
167 209 core.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
168 opj_set_default_decoder_parameters(&params); 210
169 info = opj_create_decompress(format); 211 /* magic check */
170 opj_set_event_mgr((opj_common_ptr)info, NULL, NULL); 212 cfmt = OPJ_CODEC_UNKNOWN;
171 opj_setup_decoder(info, &params); 213 if (map_st.length >= 4)
172 cio = opj_cio_open((opj_common_ptr)info, map, length); 214 {
173 image = opj_decode(info, cio); 215 if (memcmp(map_st.base, J2K_CODESTREAM_MAGIC, 4) == 0)
216 cfmt = OPJ_CODEC_J2K;
217 else if ((memcmp(map_st.base, JP2_MAGIC, 4) == 0) ||
218 ((map_st.length >= 12) && (memcmp(map_st.base, JP2_RFC3745_MAGIC, 12) == 0)))
219 cfmt = OPJ_CODEC_JP2;
220 }
221
222 if (cfmt == OPJ_CODEC_UNKNOWN)
223 {
224 ERR("jpeg200 file format invalid\n");
225 *error = EVAS_LOAD_ERROR_GENERIC;
226 return EINA_FALSE;
227 }
228
229 /* codec */
230 codec = opj_create_decompress(cfmt);
231 if (!codec)
232 {
233 ERR("can't create codec\n");
234 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
235 return EINA_FALSE;
236 }
237 opj_set_info_handler(codec, _jp2k_quiet_callback, NULL);
238 opj_set_warning_handler(codec, _jp2k_quiet_callback, NULL);
239 opj_set_error_handler(codec, _jp2k_quiet_callback, NULL);
240 if (!opj_setup_decoder(codec, &core))
241 {
242 ERR("can't setup decoder\n");
243 opj_destroy_codec(codec);
244 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
245 return EINA_FALSE;
246 }
247 //opj_codec_set_threads(codec, 0)
248
249 /* stream */
250 st = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, OPJ_TRUE);
251 if (!st)
252 {
253 ERR("can't create stream\n");
254 opj_destroy_codec(codec);
255 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
256 return EINA_FALSE;
257 }
258
259 opj_stream_set_user_data(st, &map_st, NULL);
260 opj_stream_set_user_data_length(st, map_st.length);
261 opj_stream_set_read_function(st, _jp2k_read_fn);
262 opj_stream_set_skip_function(st, _jp2k_seek_cur_fn);
263 opj_stream_set_seek_function(st, _jp2k_seek_set_fn);
264
265 if (!opj_read_header(st, codec, &image))
266 {
267 ERR("can not read image header\n");
268 opj_stream_destroy(st);
269 opj_destroy_codec(codec);
270 *error = EVAS_LOAD_ERROR_GENERIC;
271 return EINA_FALSE;
272 }
273
274 if (!(opj_decode(codec, st, image) && opj_end_decompress(codec, st)))
275 {
276 ERR("can not decode image\n");
277 opj_image_destroy(image);
278 opj_stream_destroy(st);
279 opj_destroy_codec(codec);
280 *error = EVAS_LOAD_ERROR_GENERIC;
281 return EINA_FALSE;
282 }
174 283
175 iter = pixels; 284 iter = pixels;
176 idx = 0; 285 idx = 0;
@@ -190,8 +299,8 @@ evas_image_load_file_data_jp2k_internal(Evas_Image_Load_Opts *opts EINA_UNUSED,
190 int r; 299 int r;
191 int g; 300 int g;
192 int b; 301 int b;
193 int i; 302 unsigned int i;
194 int j; 303 unsigned int j;
195 304
196 for (j = 0; j < image->comps[0].h; j++) 305 for (j = 0; j < image->comps[0].h; j++)
197 { 306 {
@@ -235,8 +344,8 @@ evas_image_load_file_data_jp2k_internal(Evas_Image_Load_Opts *opts EINA_UNUSED,
235 { 344 {
236 int a; 345 int a;
237 int g; 346 int g;
238 int i; 347 unsigned int i;
239 int j; 348 unsigned int j;
240 349
241 for (j = 0; j < image->comps[0].h; j++) 350 for (j = 0; j < image->comps[0].h; j++)
242 { 351 {
@@ -263,8 +372,8 @@ evas_image_load_file_data_jp2k_internal(Evas_Image_Load_Opts *opts EINA_UNUSED,
263 } 372 }
264 373
265 opj_image_destroy(image); 374 opj_image_destroy(image);
266 opj_cio_close(cio); 375 opj_stream_destroy(st);
267 opj_destroy_decompress(info); 376 opj_destroy_codec(codec);
268 377
269 *error = EVAS_LOAD_ERROR_NONE; 378 *error = EVAS_LOAD_ERROR_NONE;
270 return EINA_TRUE; 379 return EINA_TRUE;
@@ -303,12 +412,10 @@ evas_image_load_file_head_jp2k(void *loader_data,
303 int *error) 412 int *error)
304{ 413{
305 Evas_Loader_Internal *loader = loader_data; 414 Evas_Loader_Internal *loader = loader_data;
306 Evas_Image_Load_Opts *opts;
307 Eina_File *f; 415 Eina_File *f;
308 void *map; 416 void *map;
309 Eina_Bool val; 417 Eina_Bool val;
310 418
311 opts = loader->opts;
312 f = loader->f; 419 f = loader->f;
313 420
314 map = eina_file_map_all(f, EINA_FILE_RANDOM); 421 map = eina_file_map_all(f, EINA_FILE_RANDOM);
@@ -320,7 +427,6 @@ evas_image_load_file_head_jp2k(void *loader_data,
320 427
321 val = evas_image_load_file_head_jp2k_internal(&prop->w, &prop->h, 428 val = evas_image_load_file_head_jp2k_internal(&prop->w, &prop->h,
322 &prop->alpha, 429 &prop->alpha,
323 opts,
324 map, eina_file_size_get(f), 430 map, eina_file_size_get(f),
325 error); 431 error);
326 432
@@ -331,18 +437,16 @@ evas_image_load_file_head_jp2k(void *loader_data,
331 437
332static Eina_Bool 438static Eina_Bool
333evas_image_load_file_data_jp2k(void *loader_data, 439evas_image_load_file_data_jp2k(void *loader_data,
334 Evas_Image_Property *prop, 440 Evas_Image_Property *prop EINA_UNUSED,
335 void *pixels, 441 void *pixels,
336 int *error) 442 int *error)
337{ 443{
338 Evas_Loader_Internal *loader = loader_data; 444 Evas_Loader_Internal *loader = loader_data;
339 Evas_Image_Load_Opts *opts;
340 Eina_File *f; 445 Eina_File *f;
341 void *map; 446 void *map;
342 Eina_Bool val = EINA_FALSE; 447 Eina_Bool val = EINA_FALSE;
343 448
344 f = loader->f; 449 f = loader->f;
345 opts = loader->opts;
346 450
347 map = eina_file_map_all(f, EINA_FILE_WILLNEED); 451 map = eina_file_map_all(f, EINA_FILE_WILLNEED);
348 if (!map) 452 if (!map)
@@ -351,7 +455,7 @@ evas_image_load_file_data_jp2k(void *loader_data,
351 goto on_error; 455 goto on_error;
352 } 456 }
353 457
354 val = evas_image_load_file_data_jp2k_internal(opts, prop, pixels, 458 val = evas_image_load_file_data_jp2k_internal(pixels,
355 map, eina_file_size_get(f), 459 map, eina_file_size_get(f),
356 error); 460 error);
357 461