aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/loaders/jpeg/evas_image_load_jpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/loaders/jpeg/evas_image_load_jpeg.c')
-rw-r--r--libraries/evas/src/modules/loaders/jpeg/evas_image_load_jpeg.c1265
1 files changed, 1265 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/loaders/jpeg/evas_image_load_jpeg.c b/libraries/evas/src/modules/loaders/jpeg/evas_image_load_jpeg.c
new file mode 100644
index 0000000..0dbabab
--- /dev/null
+++ b/libraries/evas/src/modules/loaders/jpeg/evas_image_load_jpeg.c
@@ -0,0 +1,1265 @@
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 <setjmp.h>
12#include <jpeglib.h>
13
14#include "evas_common.h"
15#include "evas_private.h"
16
17
18typedef struct _JPEG_error_mgr *emptr;
19struct _JPEG_error_mgr
20{
21 struct jpeg_error_mgr pub;
22 jmp_buf setjmp_buffer;
23};
24
25static void _JPEGFatalErrorHandler(j_common_ptr cinfo);
26static void _JPEGErrorHandler(j_common_ptr cinfo);
27static void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
28
29static Eina_Bool evas_image_load_file_head_jpeg_internal(Image_Entry *ie,
30 void *map,
31 size_t len,
32 int *error) EINA_ARG_NONNULL(1, 2, 4);
33static Eina_Bool evas_image_load_file_data_jpeg_internal(Image_Entry *ie,
34 void *map,
35 size_t len,
36 int *error) EINA_ARG_NONNULL(1, 2, 4);
37#if 0 /* not used at the moment */
38static int evas_image_load_file_data_jpeg_alpha_internal(Image_Entry *ie, FILE *f) EINA_ARG_NONNULL(1, 2);
39#endif
40
41static Eina_Bool evas_image_load_file_head_jpeg(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
42static Eina_Bool evas_image_load_file_data_jpeg(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
43
44static Evas_Image_Load_Func evas_image_load_jpeg_func =
45{
46 EINA_TRUE,
47 evas_image_load_file_head_jpeg,
48 evas_image_load_file_data_jpeg,
49 NULL
50};
51
52
53static void
54_JPEGFatalErrorHandler(j_common_ptr cinfo)
55{
56 emptr errmgr;
57
58 errmgr = (emptr) cinfo->err;
59 /* cinfo->err->output_message(cinfo);*/
60 longjmp(errmgr->setjmp_buffer, 1);
61 return;
62}
63
64static void
65_JPEGErrorHandler(j_common_ptr cinfo __UNUSED__)
66{
67/* emptr errmgr; */
68
69/* errmgr = (emptr) cinfo->err; */
70 /* cinfo->err->output_message(cinfo);*/
71 /* longjmp(errmgr->setjmp_buffer, 1);*/
72 return;
73}
74
75static void
76_JPEGErrorHandler2(j_common_ptr cinfo __UNUSED__, int msg_level __UNUSED__)
77{
78/* emptr errmgr; */
79
80/* errmgr = (emptr) cinfo->err; */
81 /* cinfo->err->output_message(cinfo);*/
82 /* longjmp(errmgr->setjmp_buffer, 1);*/
83 return;
84}
85
86struct jpeg_membuf_src
87{
88 struct jpeg_source_mgr pub;
89
90 const unsigned char *buf;
91 size_t len;
92 struct jpeg_membuf_src *self;
93};
94
95static void
96_evas_jpeg_membuf_src_init(j_decompress_ptr cinfo __UNUSED__)
97{
98}
99
100static boolean
101_evas_jpeg_membuf_src_fill(j_decompress_ptr cinfo)
102{
103 static const JOCTET jpeg_eoi[2] = { 0xFF, JPEG_EOI };
104 struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
105
106 src->pub.bytes_in_buffer = sizeof(jpeg_eoi);
107 src->pub.next_input_byte = jpeg_eoi;
108
109 return TRUE;
110}
111
112static void
113_evas_jpeg_membuf_src_skip(j_decompress_ptr cinfo,
114 long num_bytes)
115{
116 struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
117
118 if ((((long)src->pub.bytes_in_buffer - (long)src->len) > num_bytes) ||
119 ((long)src->pub.bytes_in_buffer < num_bytes))
120 {
121 (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo));
122 return;
123 }
124 src->pub.bytes_in_buffer -= num_bytes;
125 src->pub.next_input_byte += num_bytes;
126}
127
128static void
129_evas_jpeg_membuf_src_term(j_decompress_ptr cinfo)
130{
131 struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
132 if (!src) return;
133 free(src);
134 cinfo->src = NULL;
135}
136
137static int
138_evas_jpeg_membuf_src(j_decompress_ptr cinfo,
139 void *map, size_t length)
140{
141 struct jpeg_membuf_src *src;
142
143 src = calloc(1, sizeof(*src));
144 if (!src)
145 return -1;
146
147 src->self = src;
148
149 cinfo->src = &src->pub;
150 src->buf = map;
151 src->len = length;
152 src->pub.init_source = _evas_jpeg_membuf_src_init;
153 src->pub.fill_input_buffer = _evas_jpeg_membuf_src_fill;
154 src->pub.skip_input_data = _evas_jpeg_membuf_src_skip;
155 src->pub.resync_to_restart = jpeg_resync_to_restart;
156 src->pub.term_source = _evas_jpeg_membuf_src_term;
157 src->pub.bytes_in_buffer = src->len;
158 src->pub.next_input_byte = src->buf;
159
160 return 0;
161}
162
163/*! Magic number for EXIF header & App1*/
164static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
165static const unsigned char App1[] = {0xff, 0xe1};
166typedef enum {
167 EXIF_BYTE_ALIGN_II,
168 EXIF_BYTE_ALIGN_MM
169} ExifByteAlign;
170
171static int
172_get_orientation(void *map, size_t length)
173{
174 char *buf;
175 char orientation[2];
176 ExifByteAlign byte_align;
177 unsigned int num_directory = 0;
178 unsigned int i, j;
179 int direction;
180
181 /* open file and get 22 byte frome file */
182 if (!map) return 0;
183 /* 1. read 22byte */
184 if (length < 22) return 0;
185 buf = (char *)map;
186
187 /* 2. check 2,3 bypte with APP1(0xFFE1) */
188 if (memcmp(buf + 2, App1, sizeof (App1))) return 0;
189
190 /* 3. check 6~11bype with Exif Header (0x45786966 0000) */
191 if (memcmp(buf + 6, ExifHeader, sizeof (ExifHeader))) return 0;
192
193 /* 4. get 12&13 byte get info of "II(0x4949)" or "MM(0x4d4d)" */
194 /* 5. get [20]&[21] get directory entry # */
195 if (!strncmp(buf + 12, "MM", 2))
196 {
197 byte_align = EXIF_BYTE_ALIGN_MM;
198 num_directory = ((*(buf + 20) << 8) + *(buf + 21));
199 orientation[0] = 0x01;
200 orientation[1] = 0x12;
201 }
202 else if (!strncmp(buf + 12, "II", 2))
203 {
204 byte_align = EXIF_BYTE_ALIGN_II;
205 num_directory = ((*(buf + 21) << 8) + *(buf + 20));
206 orientation[0] = 0x12;
207 orientation[1] = 0x01;
208 }
209 else return 0;
210
211 buf = map + 22;
212
213 if (length < (12 * num_directory + 22)) return 0;
214
215 j = 0;
216
217 for (i = 0; i < num_directory; i++ )
218 {
219 if (!strncmp(buf + j, orientation, 2))
220 {
221 /*get orientation tag */
222 if (byte_align == EXIF_BYTE_ALIGN_MM)
223 direction = *(buf+ j + 11);
224 else direction = *(buf+ j + 8);
225 switch (direction)
226 {
227 case 3:
228 case 4:
229 return 180;
230 case 6:
231 case 7:
232 return 90;
233 case 5:
234 case 8:
235 return 270;
236 default:
237 return 0;
238 }
239 }
240 else
241 j = j + 12;
242 }
243 return 0;
244}
245
246static Eina_Bool
247evas_image_load_file_head_jpeg_internal(Image_Entry *ie,
248 void *map, size_t length,
249 int *error)
250{
251 unsigned int w, h, scalew, scaleh;
252 struct jpeg_decompress_struct cinfo;
253 struct _JPEG_error_mgr jerr;
254
255 /* for rotation decoding */
256 int degree = 0;
257 Eina_Bool change_wh = EINA_FALSE;
258 unsigned int load_opts_w = 0, load_opts_h = 0;
259
260 cinfo.err = jpeg_std_error(&(jerr.pub));
261 jerr.pub.error_exit = _JPEGFatalErrorHandler;
262 jerr.pub.emit_message = _JPEGErrorHandler2;
263 jerr.pub.output_message = _JPEGErrorHandler;
264 if (setjmp(jerr.setjmp_buffer))
265 {
266 jpeg_destroy_decompress(&cinfo);
267 _evas_jpeg_membuf_src_term(&cinfo);
268 if (cinfo.saw_JFIF_marker)
269 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
270 else
271 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
272 return EINA_FALSE;
273 }
274 jpeg_create_decompress(&cinfo);
275
276 if (_evas_jpeg_membuf_src(&cinfo, map, length))
277 {
278 jpeg_destroy_decompress(&cinfo);
279 _evas_jpeg_membuf_src_term(&cinfo);
280 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
281 return EINA_FALSE;
282 }
283
284 jpeg_read_header(&cinfo, TRUE);
285 cinfo.do_fancy_upsampling = FALSE;
286 cinfo.do_block_smoothing = FALSE;
287 cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss)
288 cinfo.dither_mode = JDITHER_ORDERED;
289 jpeg_start_decompress(&cinfo);
290
291 /* rotation decoding */
292 if (ie->load_opts.orientation)
293 {
294 degree = _get_orientation(map, length);
295 if (degree != 0)
296 {
297 ie->load_opts.degree = degree;
298 ie->flags.rotated = EINA_TRUE;
299
300 if (degree == 90 || degree == 270)
301 change_wh = EINA_TRUE;
302 }
303
304 }
305
306 /* head decoding */
307 w = cinfo.output_width;
308 h = cinfo.output_height;
309 if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
310 (IMG_TOO_BIG(w, h)))
311 {
312 jpeg_destroy_decompress(&cinfo);
313 _evas_jpeg_membuf_src_term(&cinfo);
314 if (IMG_TOO_BIG(w, h))
315 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
316 else
317 *error = EVAS_LOAD_ERROR_GENERIC;
318 return EINA_FALSE;
319 }
320 if (ie->load_opts.scale_down_by > 1)
321 {
322 w /= ie->load_opts.scale_down_by;
323 h /= ie->load_opts.scale_down_by;
324 }
325 else if (ie->load_opts.dpi > 0.0)
326 {
327 w = (w * ie->load_opts.dpi) / 90.0;
328 h = (h * ie->load_opts.dpi) / 90.0;
329 }
330 else if ((ie->load_opts.w > 0) && (ie->load_opts.h > 0))
331 {
332 unsigned int w2 = w, h2 = h;
333 /* user set load_opts' w,h on the assumption
334 that image already rotated according to it's orientation info */
335 if (change_wh)
336 {
337 load_opts_w = ie->load_opts.w;
338 load_opts_h = ie->load_opts.h;
339 ie->load_opts.w = load_opts_h;
340 ie->load_opts.h = load_opts_w;
341 }
342
343 if (ie->load_opts.w > 0)
344 {
345 w2 = ie->load_opts.w;
346 h2 = (ie->load_opts.w * h) / w;
347 if ((ie->load_opts.h > 0) && (h2 > ie->load_opts.h))
348 {
349 unsigned int w3;
350 h2 = ie->load_opts.h;
351 w3 = (ie->load_opts.h * w) / h;
352 if (w3 > w2)
353 w2 = w3;
354 }
355 }
356 else if (ie->load_opts.h > 0)
357 {
358 h2 = ie->load_opts.h;
359 w2 = (ie->load_opts.h * w) / h;
360 }
361 w = w2;
362 h = h2;
363 if (change_wh)
364 {
365 ie->load_opts.w = load_opts_w;
366 ie->load_opts.h = load_opts_h;
367 }
368 }
369 if (w < 1) w = 1;
370 if (h < 1) h = 1;
371
372 if ((w != cinfo.output_width) || (h != cinfo.output_height))
373 {
374 scalew = cinfo.output_width / w;
375 scaleh = cinfo.output_height / h;
376
377 ie->scale = scalew;
378 if (scaleh < scalew) ie->scale = scaleh;
379
380 if (ie->scale > 8) ie->scale = 8;
381 else if (ie->scale < 1) ie->scale = 1;
382
383 if (ie->scale == 3) ie->scale = 2;
384 else if (ie->scale == 5) ie->scale = 4;
385 else if (ie->scale == 6) ie->scale = 4;
386 else if (ie->scale == 7) ie->scale = 4;
387 }
388
389 if (ie->scale > 1)
390 {
391 jpeg_destroy_decompress(&cinfo);
392 _evas_jpeg_membuf_src_term(&cinfo);
393 jpeg_create_decompress(&cinfo);
394
395 if (_evas_jpeg_membuf_src(&cinfo, map, length))
396 {
397 jpeg_destroy_decompress(&cinfo);
398 _evas_jpeg_membuf_src_term(&cinfo);
399 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
400 return EINA_FALSE;
401 }
402
403 jpeg_read_header(&cinfo, TRUE);
404 cinfo.do_fancy_upsampling = FALSE;
405 cinfo.do_block_smoothing = FALSE;
406 cinfo.scale_num = 1;
407 cinfo.scale_denom = ie->scale;
408 jpeg_calc_output_dimensions(&(cinfo));
409 jpeg_start_decompress(&cinfo);
410 }
411
412 ie->w = cinfo.output_width;
413 ie->h = cinfo.output_height;
414
415 // be nice and clip region to image. if its totally outside, fail load
416 if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0))
417 {
418 unsigned int load_region_x = 0, load_region_y = 0;
419 unsigned int load_region_w = 0, load_region_h = 0;
420 if (ie->flags.rotated)
421 {
422 load_region_x = ie->load_opts.region.x;
423 load_region_y = ie->load_opts.region.y;
424 load_region_w = ie->load_opts.region.w;
425 load_region_h = ie->load_opts.region.h;
426
427 switch (degree)
428 {
429 case 90:
430 ie->load_opts.region.x = load_region_y;
431 ie->load_opts.region.y = h - (load_region_x + load_region_w);
432 ie->load_opts.region.w = load_region_h;
433 ie->load_opts.region.h = load_region_w;
434 break;
435 case 180:
436 ie->load_opts.region.x = w - (load_region_x+ load_region_w);
437 ie->load_opts.region.y = h - (load_region_y + load_region_h);
438
439 break;
440 case 270:
441 ie->load_opts.region.x = w - (load_region_y + load_region_h);
442 ie->load_opts.region.y = load_region_x;
443 ie->load_opts.region.w = load_region_h;
444 ie->load_opts.region.h = load_region_w;
445 break;
446 default:
447 break;
448 }
449
450 }
451 RECTS_CLIP_TO_RECT(ie->load_opts.region.x, ie->load_opts.region.y,
452 ie->load_opts.region.w, ie->load_opts.region.h,
453 0, 0, ie->w, ie->h);
454 if ((ie->load_opts.region.w <= 0) || (ie->load_opts.region.h <= 0))
455 {
456 jpeg_destroy_decompress(&cinfo);
457 _evas_jpeg_membuf_src_term(&cinfo);
458 *error = EVAS_LOAD_ERROR_GENERIC;
459 return EINA_FALSE;
460 }
461 ie->w = ie->load_opts.region.w;
462 ie->h = ie->load_opts.region.h;
463 if (ie->flags.rotated)
464 {
465 ie->load_opts.region.x = load_region_x;
466 ie->load_opts.region.y = load_region_y;
467 ie->load_opts.region.w = load_region_w;
468 ie->load_opts.region.h = load_region_h;
469 }
470 }
471/* end head decoding */
472
473 if (change_wh)
474 {
475 unsigned int tmp;
476 tmp = ie->w;
477 ie->w = ie->h;
478 ie->h = tmp;
479 }
480 jpeg_destroy_decompress(&cinfo);
481 _evas_jpeg_membuf_src_term(&cinfo);
482 *error = EVAS_LOAD_ERROR_NONE;
483 return EINA_TRUE;
484}
485
486/*
487static double
488get_time(void)
489{
490 struct timeval timev;
491
492 gettimeofday(&timev, NULL);
493 return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
494}
495*/
496
497static Eina_Bool
498evas_image_load_file_data_jpeg_internal(Image_Entry *ie,
499 void *map, size_t size,
500 int *error)
501{
502 unsigned int w, h;
503 struct jpeg_decompress_struct cinfo;
504 struct _JPEG_error_mgr jerr;
505 DATA8 *ptr, *line[16], *data;
506 DATA32 *ptr2, *ptr_rotate = NULL;
507 unsigned int x, y, l, i, scans;
508 int region = 0;
509 /* rotation setting */
510 unsigned int tmp;
511 unsigned int load_region_x = 0, load_region_y = 0;
512 unsigned int load_region_w = 0, load_region_h = 0;
513 int degree = 0;
514 Eina_Bool change_wh = EINA_FALSE;
515 Eina_Bool line_done = EINA_FALSE;
516
517 if (ie->flags.rotated)
518 {
519 degree = ie->load_opts.degree;
520 if (degree == 90 || degree == 270)
521 change_wh = EINA_TRUE;
522 }
523
524 cinfo.err = jpeg_std_error(&(jerr.pub));
525 jerr.pub.error_exit = _JPEGFatalErrorHandler;
526 jerr.pub.emit_message = _JPEGErrorHandler2;
527 jerr.pub.output_message = _JPEGErrorHandler;
528 if (setjmp(jerr.setjmp_buffer))
529 {
530 jpeg_destroy_decompress(&cinfo);
531 _evas_jpeg_membuf_src_term(&cinfo);
532 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
533 return EINA_FALSE;
534 }
535 jpeg_create_decompress(&cinfo);
536
537 if (_evas_jpeg_membuf_src(&cinfo, map, size))
538 {
539 jpeg_destroy_decompress(&cinfo);
540 _evas_jpeg_membuf_src_term(&cinfo);
541 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
542 return 0;
543 }
544
545 jpeg_read_header(&cinfo, TRUE);
546 cinfo.do_fancy_upsampling = FALSE;
547 cinfo.do_block_smoothing = FALSE;
548 cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss)
549 cinfo.dither_mode = JDITHER_ORDERED;
550
551 if (ie->scale > 1)
552 {
553 cinfo.scale_num = 1;
554 cinfo.scale_denom = ie->scale;
555 }
556
557 /* Colorspace conversion options */
558 /* libjpeg can do the following conversions: */
559 /* GRAYSCLAE => RGB YCbCr => RGB and YCCK => CMYK */
560 switch (cinfo.jpeg_color_space)
561 {
562 case JCS_UNKNOWN:
563 break;
564 case JCS_GRAYSCALE:
565 case JCS_RGB:
566 case JCS_YCbCr:
567 cinfo.out_color_space = JCS_RGB;
568 break;
569 case JCS_CMYK:
570 case JCS_YCCK:
571 cinfo.out_color_space = JCS_CMYK;
572 break;
573 }
574
575/* head decoding */
576 jpeg_calc_output_dimensions(&(cinfo));
577 jpeg_start_decompress(&cinfo);
578
579 w = cinfo.output_width;
580 h = cinfo.output_height;
581
582 if (change_wh)
583 {
584 tmp = ie->w;
585 ie->w = ie->h;
586 ie->h = tmp;
587 }
588
589 if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0))
590 {
591 region = 1;
592
593 if (ie->flags.rotated)
594 {
595 load_region_x = ie->load_opts.region.x;
596 load_region_y = ie->load_opts.region.y;
597 load_region_w = ie->load_opts.region.w;
598 load_region_h = ie->load_opts.region.h;
599
600 switch (degree)
601 {
602 case 90:
603 ie->load_opts.region.x = load_region_y;
604 ie->load_opts.region.y = h - (load_region_x + load_region_w);
605 ie->load_opts.region.w = load_region_h;
606 ie->load_opts.region.h = load_region_w;
607 break;
608 case 180:
609 ie->load_opts.region.x = w - (load_region_x+ load_region_w);
610 ie->load_opts.region.y = h - (load_region_y + load_region_h);
611
612 break;
613 case 270:
614 ie->load_opts.region.x = w - (load_region_y + load_region_h);
615 ie->load_opts.region.y = load_region_x;
616 ie->load_opts.region.w = load_region_h;
617 ie->load_opts.region.h = load_region_w;
618 break;
619 default:
620 break;
621 }
622
623 }
624#ifdef BUILD_LOADER_JPEG_REGION
625 cinfo.region_x = ie->load_opts.region.x;
626 cinfo.region_y = ie->load_opts.region.y;
627 cinfo.region_w = ie->load_opts.region.w;
628 cinfo.region_h = ie->load_opts.region.h;
629#endif
630 }
631 if ((!region) && ((w != ie->w) || (h != ie->h)))
632 {
633 // race condition, the file could have change from when we call header
634 // this test will not solve the problem with region code.
635 jpeg_destroy_decompress(&cinfo);
636 _evas_jpeg_membuf_src_term(&cinfo);
637 *error = EVAS_LOAD_ERROR_GENERIC;
638 return EINA_FALSE;
639 }
640 if ((region) &&
641 ((ie->w != ie->load_opts.region.w) || (ie->h != ie->load_opts.region.h)))
642 {
643 ie->w = ie->load_opts.region.w;
644 ie->h = ie->load_opts.region.h;
645 }
646
647 if (!(((cinfo.out_color_space == JCS_RGB) &&
648 ((cinfo.output_components == 3) || (cinfo.output_components == 1))) ||
649 ((cinfo.out_color_space == JCS_CMYK) && (cinfo.output_components == 4))))
650 {
651 jpeg_destroy_decompress(&cinfo);
652 _evas_jpeg_membuf_src_term(&cinfo);
653 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
654 return EINA_FALSE;
655 }
656
657/* end head decoding */
658/* data decoding */
659 if (cinfo.rec_outbuf_height > 16)
660 {
661 jpeg_destroy_decompress(&cinfo);
662 _evas_jpeg_membuf_src_term(&cinfo);
663 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
664 return EINA_FALSE;
665 }
666 data = alloca(w * 16 * cinfo.output_components);
667 evas_cache_image_surface_alloc(ie, ie->w, ie->h);
668 if (ie->flags.loaded)
669 {
670 jpeg_destroy_decompress(&cinfo);
671 _evas_jpeg_membuf_src_term(&cinfo);
672 *error = EVAS_LOAD_ERROR_NONE;
673 if (region && ie->flags.rotated)
674 {
675 ie->load_opts.region.x = load_region_x;
676 ie->load_opts.region.y = load_region_y;
677 ie->load_opts.region.w = load_region_w;
678 ie->load_opts.region.h = load_region_h;
679 }
680 return EINA_TRUE;
681 }
682 if ((ie->flags.rotated) && change_wh)
683 {
684 ptr2 = malloc(ie->w * ie->h * sizeof(DATA32));
685 ptr_rotate = ptr2;
686 }
687 else
688 ptr2 = evas_cache_image_pixels(ie);
689
690 if (!ptr2)
691 {
692 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
693 return EINA_FALSE;
694 }
695
696 /* We handle first CMYK (4 components) */
697 if (cinfo.output_components == 4)
698 {
699 // FIXME: handle region
700 for (i = 0; (int)i < cinfo.rec_outbuf_height; i++)
701 line[i] = data + (i * w * 4);
702 for (l = 0; l < h; l += cinfo.rec_outbuf_height)
703 {
704 jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
705 scans = cinfo.rec_outbuf_height;
706 if ((h - l) < scans) scans = h - l;
707 ptr = data;
708 if (!region)
709 {
710 for (y = 0; y < scans; y++)
711 {
712 if (cinfo.saw_Adobe_marker)
713 {
714 for (x = 0; x < w; x++)
715 {
716 /* According to libjpeg doc, Photoshop inverse the values of C, M, Y and K, */
717 /* that is C is replaces by 255 - C, etc...*/
718 /* See the comment below for the computation of RGB values from CMYK ones. */
719 *ptr2 =
720 (0xff000000) |
721 ((ptr[0] * ptr[3] / 255) << 16) |
722 ((ptr[1] * ptr[3] / 255) << 8) |
723 ((ptr[2] * ptr[3] / 255));
724 ptr += 4;
725 ptr2++;
726 }
727 }
728 else
729 {
730 for (x = 0; x < w; x++)
731 {
732 /* Conversion from CMYK to RGB is done in 2 steps: */
733 /* CMYK => CMY => RGB (see http://www.easyrgb.com/index.php?X=MATH) */
734 /* after computation, if C, M, Y and K are between 0 and 1, we have: */
735 /* R = (1 - C) * (1 - K) * 255 */
736 /* G = (1 - M) * (1 - K) * 255 */
737 /* B = (1 - Y) * (1 - K) * 255 */
738 /* libjpeg stores CMYK values between 0 and 255, */
739 /* so we replace C by C * 255 / 255, etc... and we obtain: */
740 /* R = (255 - C) * (255 - K) / 255 */
741 /* G = (255 - M) * (255 - K) / 255 */
742 /* B = (255 - Y) * (255 - K) / 255 */
743 /* with C, M, Y and K between 0 and 255. */
744 *ptr2 =
745 (0xff000000) |
746 (((255 - ptr[0]) * (255 - ptr[3]) / 255) << 16) |
747 (((255 - ptr[1]) * (255 - ptr[3]) / 255) << 8) |
748 (((255 - ptr[2]) * (255 - ptr[3]) / 255));
749 ptr += 4;
750 ptr2++;
751 }
752 }
753 }
754 }
755 else
756 {
757 // if line # > region last line, break
758 if (l >= (ie->load_opts.region.y + ie->load_opts.region.h))
759 {
760 line_done = EINA_TRUE;
761 /* if rotation flag is set , we have to rotate image */
762 goto done;
763 /*jpeg_destroy_decompress(&cinfo);
764 _evas_jpeg_membuf_src_term(&cinfo);
765 *error = EVAS_LOAD_ERROR_NONE;
766 return EINA_FALSE;*/
767 }
768 // els if scan block intersects region start or later
769 else if ((l + scans) >
770 (ie->load_opts.region.y))
771 {
772 for (y = 0; y < scans; y++)
773 {
774 if (((y + l) >= ie->load_opts.region.y) &&
775 ((y + l) < (ie->load_opts.region.y + ie->load_opts.region.h)))
776 {
777 ptr += ie->load_opts.region.x;
778 if (cinfo.saw_Adobe_marker)
779 {
780 for (x = 0; x < ie->load_opts.region.w; x++)
781 {
782 /* According to libjpeg doc, Photoshop inverse the values of C, M, Y and K, */
783 /* that is C is replaces by 255 - C, etc...*/
784 /* See the comment below for the computation of RGB values from CMYK ones. */
785 *ptr2 =
786 (0xff000000) |
787 ((ptr[0] * ptr[3] / 255) << 16) |
788 ((ptr[1] * ptr[3] / 255) << 8) |
789 ((ptr[2] * ptr[3] / 255));
790 ptr += 4;
791 ptr2++;
792 }
793 }
794 else
795 {
796 for (x = 0; x < ie->load_opts.region.w; x++)
797 {
798 /* Conversion from CMYK to RGB is done in 2 steps: */
799 /* CMYK => CMY => RGB (see http://www.easyrgb.com/index.php?X=MATH) */
800 /* after computation, if C, M, Y and K are between 0 and 1, we have: */
801 /* R = (1 - C) * (1 - K) * 255 */
802 /* G = (1 - M) * (1 - K) * 255 */
803 /* B = (1 - Y) * (1 - K) * 255 */
804 /* libjpeg stores CMYK values between 0 and 255, */
805 /* so we replace C by C * 255 / 255, etc... and we obtain: */
806 /* R = (255 - C) * (255 - K) / 255 */
807 /* G = (255 - M) * (255 - K) / 255 */
808 /* B = (255 - Y) * (255 - K) / 255 */
809 /* with C, M, Y and K between 0 and 255. */
810 *ptr2 =
811 (0xff000000) |
812 (((255 - ptr[0]) * (255 - ptr[3]) / 255) << 16) |
813 (((255 - ptr[1]) * (255 - ptr[3]) / 255) << 8) |
814 (((255 - ptr[2]) * (255 - ptr[3]) / 255));
815 ptr += 4;
816 ptr2++;
817 }
818 }
819 ptr += (4 * (w - (ie->load_opts.region.x + ie->load_opts.region.w)));
820 }
821 else
822 ptr += (4 * w);
823 }
824 }
825 }
826 }
827 }
828 /* We handle then RGB with 3 components */
829 else if (cinfo.output_components == 3)
830 {
831/*
832 double t;
833 if (region)
834 {
835 // debug for now
836 printf("R| %p %5ix%5i %s: %5i %5i %5ix%5i - ",
837 ie,
838 ie->w, ie->h,
839 ie->file,
840 ie->load_opts.region.x,
841 ie->load_opts.region.y,
842 ie->load_opts.region.w,
843 ie->load_opts.region.h);
844 }
845 t = get_time();
846 */
847 for (i = 0; (int)i < cinfo.rec_outbuf_height; i++)
848 line[i] = data + (i * w * 3);
849 for (l = 0; l < h; l += cinfo.rec_outbuf_height)
850 {
851 jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
852 scans = cinfo.rec_outbuf_height;
853 if ((h - l) < scans) scans = h - l;
854 ptr = data;
855 if (!region)
856 {
857 for (y = 0; y < scans; y++)
858 {
859 for (x = 0; x < w; x++)
860 {
861 *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[1], ptr[2]);
862 ptr += 3;
863 ptr2++;
864 }
865 }
866 }
867 else
868 {
869 // if line # > region last line, break
870 // but not return immediately for rotation job
871 if (l >= (ie->load_opts.region.y + ie->load_opts.region.h))
872 {
873 line_done = EINA_TRUE;
874 /* if rotation flag is set , we have to rotate image */
875 goto done;
876 }
877 // else if scan block intersects region start or later
878 else if ((l + scans) >
879 (ie->load_opts.region.y))
880 {
881 for (y = 0; y < scans; y++)
882 {
883 if (((y + l) >= ie->load_opts.region.y) &&
884 ((y + l) < (ie->load_opts.region.y + ie->load_opts.region.h)))
885 {
886 ptr += (3 * ie->load_opts.region.x);
887 for (x = 0; x < ie->load_opts.region.w; x++)
888 {
889 *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[1], ptr[2]);
890 ptr += 3;
891 ptr2++;
892 }
893 ptr += (3 * (w - (ie->load_opts.region.x + ie->load_opts.region.w)));
894 }
895 else
896 ptr += (3 * w);
897 }
898 }
899 }
900 }
901/*
902 t = get_time() - t;
903 printf("%3.3f\n", t);
904 */
905 }
906 /* We finally handle RGB with 1 component */
907 else if (cinfo.output_components == 1)
908 {
909 for (i = 0; (int)i < cinfo.rec_outbuf_height; i++)
910 line[i] = data + (i * w);
911 for (l = 0; l < h; l += cinfo.rec_outbuf_height)
912 {
913 jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
914 scans = cinfo.rec_outbuf_height;
915 if ((h - l) < scans) scans = h - l;
916 ptr = data;
917 if (!region)
918 {
919 for (y = 0; y < scans; y++)
920 {
921 for (x = 0; x < w; x++)
922 {
923 *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[0], ptr[0]);
924 ptr++;
925 ptr2++;
926 }
927 }
928 }
929 else
930 {
931 // if line # > region last line, break
932 if (l >= (ie->load_opts.region.y + ie->load_opts.region.h))
933 {
934 line_done = EINA_TRUE;
935 /* if rotation flag is set , we have to rotate image */
936 goto done;
937 /*jpeg_destroy_decompress(&cinfo);
938 _evas_jpeg_membuf_src_term(&cinfo);
939 *error = EVAS_LOAD_ERROR_NONE;
940 return EINA_TRUE;*/
941 }
942 // els if scan block intersects region start or later
943 else if ((l + scans) >
944 (ie->load_opts.region.y))
945 {
946 for (y = 0; y < scans; y++)
947 {
948 if (((y + l) >= ie->load_opts.region.y) &&
949 ((y + l) < (ie->load_opts.region.y + ie->load_opts.region.h)))
950 {
951 ptr += ie->load_opts.region.x;
952 for (x = 0; x < ie->load_opts.region.w; x++)
953 {
954 *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[0], ptr[0]);
955 ptr++;
956 ptr2++;
957 }
958 ptr += w - (ie->load_opts.region.x + ie->load_opts.region.w);
959 }
960 else
961 ptr += w;
962 }
963 }
964 }
965 }
966 }
967 /* if rotation operation need, rotate it */
968done:
969
970 if (ie->flags.rotated)
971 {
972 DATA32 *data1, *data2, *to, *from;
973 int x, y, w, h, hw;
974
975 if (change_wh)
976 {
977 tmp = ie->w;
978 ie->w = ie->h;
979 ie->h = tmp;
980 }
981
982 w = ie->w;
983 h = ie->h;
984 hw =w * h;
985
986 data1 = evas_cache_image_pixels(ie);
987
988 if (degree == 180)
989 {
990 DATA32 tmp;
991
992 data2 = data1 + (h * w) -1;
993 for (x = (w * h) / 2; --x >= 0;)
994 {
995 tmp = *data1;
996 *data1 = *data2;
997 *data2 = tmp;
998 data1++;
999 data2--;
1000 }
1001 }
1002 else
1003 {
1004 data2 = NULL;
1005 to = NULL;
1006 if (ptr_rotate) data2 = ptr_rotate;
1007
1008 if (degree == 90)
1009 {
1010 to = data1 + w - 1;
1011 hw = -hw - 1;
1012 }
1013 else if (degree == 270)
1014 {
1015 to = data1 + hw - w;
1016 w = -w;
1017 hw = hw + 1;
1018 }
1019
1020 if (to)
1021 {
1022 from = data2;
1023 for (x = ie->w; --x >= 0;)
1024 {
1025 for (y =ie->h; --y >= 0;)
1026 {
1027 *to = *from;
1028 from++;
1029 to += w;
1030 }
1031 to += hw;
1032 }
1033 }
1034 if (ptr_rotate)
1035 {
1036 free(ptr_rotate);
1037 ptr_rotate = NULL;
1038 }
1039 }
1040 if (region)
1041 {
1042 ie->load_opts.region.x = load_region_x;
1043 ie->load_opts.region.y = load_region_y;
1044 ie->load_opts.region.w = load_region_w;
1045 ie->load_opts.region.h = load_region_h;
1046 }
1047 }
1048 if (line_done)
1049 {
1050 jpeg_destroy_decompress(&cinfo);
1051 _evas_jpeg_membuf_src_term(&cinfo);
1052 *error = EVAS_LOAD_ERROR_NONE;
1053 return EINA_FALSE;
1054 }
1055 /* end data decoding */
1056 jpeg_finish_decompress(&cinfo);
1057 jpeg_destroy_decompress(&cinfo);
1058 _evas_jpeg_membuf_src_term(&cinfo);
1059 *error = EVAS_LOAD_ERROR_NONE;
1060 return EINA_TRUE;
1061}
1062
1063#if 0 /* not used at the moment */
1064static Eina_Bool
1065evas_image_load_file_data_jpeg_alpha_internal(Image_Entry *ie, FILE *f, int *error)
1066{
1067 int w, h;
1068 struct jpeg_decompress_struct cinfo;
1069 struct _JPEG_error_mgr jerr;
1070 DATA8 *ptr, *line[16], *data;
1071 DATA32 *ptr2;
1072 int x, y, l, i, scans, prevy;
1073
1074 if (!f)
1075 {
1076 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
1077 return EINA_FALSE;
1078 }
1079 cinfo.err = jpeg_std_error(&(jerr.pub));
1080 jerr.pub.error_exit = _JPEGFatalErrorHandler;
1081 jerr.pub.emit_message = _JPEGErrorHandler2;
1082 jerr.pub.output_message = _JPEGErrorHandler;
1083 if (setjmp(jerr.setjmp_buffer))
1084 {
1085 jpeg_destroy_decompress(&cinfo);
1086 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
1087 return EINA_FALSE;
1088 }
1089 jpeg_create_decompress(&cinfo);
1090 jpeg_stdio_src(&cinfo, f);
1091 jpeg_read_header(&cinfo, TRUE);
1092 cinfo.do_fancy_upsampling = FALSE;
1093 cinfo.do_block_smoothing = FALSE;
1094 jpeg_start_decompress(&cinfo);
1095
1096/* head decoding */
1097 ie->w = w = cinfo.output_width;
1098 ie->h = h = cinfo.output_height;
1099/* end head decoding */
1100/* data decoding */
1101 if (cinfo.rec_outbuf_height > 16)
1102 {
1103 jpeg_destroy_decompress(&cinfo);
1104 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
1105 return EINA_FALSE;;
1106 }
1107 data = alloca(w * 16 * 3);
1108 if (!ie->flags.loaded)
1109 {
1110 jpeg_destroy_decompress(&cinfo);
1111 *error = EVAS_LOAD_ERROR_NONE;
1112 return EINA_TRUE;
1113 }
1114 ptr2 = evas_cache_image_pixels(ie);
1115 prevy = 0;
1116 if (cinfo.output_components == 3)
1117 {
1118 for (i = 0; i < cinfo.rec_outbuf_height; i++)
1119 line[i] = data + (i * w * 3);
1120 for (l = 0; l < h; l += cinfo.rec_outbuf_height)
1121 {
1122 jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
1123 scans = cinfo.rec_outbuf_height;
1124 if ((h - l) < scans) scans = h - l;
1125 ptr = data;
1126 for (y = 0; y < scans; y++)
1127 {
1128 for (x = 0; x < w; x++)
1129 {
1130 *ptr2 =
1131 ((*ptr2) & 0x00ffffff) |
1132 (((ptr[0] + ptr[1] + ptr[2]) / 3) << 24);
1133 ptr += 3;
1134 ptr2++;
1135 }
1136 }
1137 }
1138 }
1139 else if (cinfo.output_components == 1)
1140 {
1141 for (i = 0; i < cinfo.rec_outbuf_height; i++)
1142 line[i] = data + (i * w);
1143 for (l = 0; l < h; l += cinfo.rec_outbuf_height)
1144 {
1145 jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
1146 scans = cinfo.rec_outbuf_height;
1147 if ((h - l) < scans) scans = h - l;
1148 ptr = data;
1149 for (y = 0; y < scans; y++)
1150 {
1151 for (x = 0; x < w; x++)
1152 {
1153 *ptr2 =
1154 ((*ptr2) & 0x00ffffff) |
1155 ((ptr[0]) << 24);
1156 ptr++;
1157 ptr2++;
1158 }
1159 }
1160 }
1161 }
1162/* end data decoding */
1163 jpeg_finish_decompress(&cinfo);
1164 jpeg_destroy_decompress(&cinfo);
1165 *error = EVAS_LOAD_ERROR_NONE;
1166 return EINA_TRUE;
1167}
1168#endif
1169
1170static Eina_Bool
1171evas_image_load_file_head_jpeg(Image_Entry *ie,
1172 const char *file, const char *key __UNUSED__,
1173 int *error)
1174{
1175 Eina_File *f;
1176 void *map;
1177 Eina_Bool val = EINA_FALSE;
1178
1179 f = eina_file_open(file, EINA_FALSE);
1180 if (!f)
1181 {
1182 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
1183 return EINA_FALSE;
1184 }
1185 map = eina_file_map_all(f, EINA_FILE_WILLNEED);
1186 if (!map)
1187 {
1188 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
1189 goto on_error;
1190 }
1191
1192 val = evas_image_load_file_head_jpeg_internal(ie,
1193 map, eina_file_size_get(f),
1194 error);
1195
1196 eina_file_map_free(f, map);
1197
1198 on_error:
1199 eina_file_close(f);
1200 return val;
1201}
1202
1203static Eina_Bool
1204evas_image_load_file_data_jpeg(Image_Entry *ie,
1205 const char *file, const char *key __UNUSED__,
1206 int *error)
1207{
1208 Eina_File *f;
1209 void *map;
1210 Eina_Bool val = EINA_FALSE;
1211
1212 f = eina_file_open(file, EINA_FALSE);
1213 if (!f)
1214 {
1215 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
1216 return EINA_FALSE;
1217 }
1218 map = eina_file_map_all(f, EINA_FILE_WILLNEED);
1219 if (!map)
1220 {
1221 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
1222 goto on_error;
1223 }
1224
1225 val = evas_image_load_file_data_jpeg_internal(ie,
1226 map, eina_file_size_get(f),
1227 error);
1228
1229 eina_file_map_free(f, map);
1230
1231 on_error:
1232 eina_file_close(f);
1233 return val;
1234}
1235
1236static int
1237module_open(Evas_Module *em)
1238{
1239 if (!em) return 0;
1240 em->functions = (void *)(&evas_image_load_jpeg_func);
1241 return 1;
1242}
1243
1244static void
1245module_close(Evas_Module *em __UNUSED__)
1246{
1247}
1248
1249static Evas_Module_Api evas_modapi =
1250{
1251 EVAS_MODULE_API_VERSION,
1252 "jpeg",
1253 "none",
1254 {
1255 module_open,
1256 module_close
1257 }
1258};
1259
1260EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, jpeg);
1261
1262#ifndef EVAS_STATIC_BUILD_JPEG
1263EVAS_EINA_MODULE_DEFINE(image_loader, jpeg);
1264#endif
1265