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