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