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