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