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