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