summaryrefslogtreecommitdiff
path: root/src/lib/emile
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2015-03-17 08:50:19 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-03-17 09:58:18 +0100
commit4ca8bfd15c2be8870320ceee86e5bb89a1a2d2d8 (patch)
tree25b1b40b3db9be55316f852113b68d55168a716f /src/lib/emile
parentf9125499f9743a3ed551f1f1f2144b331d7e2056 (diff)
emile: add JPEG support.
Diffstat (limited to 'src/lib/emile')
-rw-r--r--src/lib/emile/emile_image.c1283
1 files changed, 1273 insertions, 10 deletions
diff --git a/src/lib/emile/emile_image.c b/src/lib/emile/emile_image.c
index 9f26a9aa00..9aa9a75653 100644
--- a/src/lib/emile/emile_image.c
+++ b/src/lib/emile/emile_image.c
@@ -6,6 +6,10 @@
6# include <netinet/in.h> 6# include <netinet/in.h>
7#endif 7#endif
8 8
9#ifdef HAVE_EVIL
10# include <Evil.h>
11#endif
12
9#ifdef _WIN32 13#ifdef _WIN32
10# include <winsock2.h> 14# include <winsock2.h>
11#endif /* ifdef _WIN32 */ 15#endif /* ifdef _WIN32 */
@@ -16,6 +20,14 @@
16# include "lz4.h" 20# include "lz4.h"
17#endif 21#endif
18 22
23#ifdef _WIN32
24# define XMD_H /* This prevents libjpeg to redefine INT32 */
25#endif
26
27#include <stdio.h>
28#include <setjmp.h>
29#include <jpeglib.h>
30
19#include "rg_etc1.h" 31#include "rg_etc1.h"
20#include "Emile.h" 32#include "Emile.h"
21 33
@@ -23,6 +35,45 @@
23#include <arm_neon.h> 35#include <arm_neon.h>
24#endif 36#endif
25 37
38#define IMG_MAX_SIZE 65000
39
40#define IMG_TOO_BIG(w, h) \
41 ((((unsigned long long)w) * ((unsigned long long)h)) >= \
42 ((1ULL << (29 * (sizeof(void *) / 4))) - 2048))
43
44#define SPANS_COMMON(x1, w1, x2, w2) \
45 (!(( (int)((x2) + (int)(w2)) <= (int)(x1)) || (int)((x2) >= (int)((x1) + (int)(w1)))))
46
47#define RECTS_INTERSECT(x, y, w, h, xx, yy, ww, hh) \
48 ((SPANS_COMMON((x), (w), (xx), (ww))) && (SPANS_COMMON((y), (h), (yy), (hh))))
49
50#define RECTS_CLIP_TO_RECT(_x, _y, _w, _h, _cx, _cy, _cw, _ch) \
51 { \
52 if (RECTS_INTERSECT(_x, _y, _w, _h, _cx, _cy, _cw, _ch)) \
53 { \
54 if ((int)_x < (int)(_cx)) \
55 { \
56 if ((int)_w + ((int)_x - (int)(_cx)) < 0) _w = 0; \
57 else _w += ((int)_x - (int)(_cx)); \
58 _x = (_cx); \
59 } \
60 if ((int)(_x + _w) > (int)((_cx) + (_cw))) \
61 _w = (_cx) + (_cw) - _x; \
62 if ((int)_y < (int)(_cy)) \
63 { \
64 if ((int)_h + ((int)_y - (int)(_cy)) < 0) _h = 0; \
65 else _h += ((int)_y - (int)(_cy)); \
66 _y = (_cy); \
67 } \
68 if ((int)(_y + _h) > (int)((_cy) + (_ch))) \
69 _h = (_cy) + (_ch) - _y; \
70 } \
71 else \
72 { \
73 _w = 0; _h = 0; \
74 } \
75 }
76
26#ifndef WORDS_BIGENDIAN 77#ifndef WORDS_BIGENDIAN
27/* x86 */ 78/* x86 */
28#define A_VAL(p) (((uint8_t *)(p))[3]) 79#define A_VAL(p) (((uint8_t *)(p))[3])
@@ -37,6 +88,9 @@
37#define B_VAL(p) (((uint8_t *)(p))[3]) 88#define B_VAL(p) (((uint8_t *)(p))[3])
38#endif 89#endif
39 90
91#define ARGB_JOIN(a,r,g,b) \
92 (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
93
40#define OFFSET_BLOCK_SIZE 4 94#define OFFSET_BLOCK_SIZE 4
41#define OFFSET_ALGORITHM 5 95#define OFFSET_ALGORITHM 5
42#define OFFSET_OPTIONS 6 96#define OFFSET_OPTIONS 6
@@ -147,6 +201,11 @@ static const Emile_Colorspace cspaces_etc1_alpha[2] = {
147 EMILE_COLORSPACE_ARGB8888 201 EMILE_COLORSPACE_ARGB8888
148}; 202};
149 203
204static const Emile_Colorspace cspaces_gry[2] = {
205 EMILE_COLORSPACE_GRY8,
206 EMILE_COLORSPACE_ARGB8888
207};
208
150/************************************************************** 209/**************************************************************
151 * The TGV file format is oriented around compression mecanism 210 * The TGV file format is oriented around compression mecanism
152 * that hardware are good at decompressing. We do still provide 211 * that hardware are good at decompressing. We do still provide
@@ -181,8 +240,8 @@ static const Emile_Colorspace cspaces_etc1_alpha[2] = {
181 240
182static Eina_Bool 241static Eina_Bool
183_emile_tgv_bind(Emile_Image *image, 242_emile_tgv_bind(Emile_Image *image,
184 Emile_Image_Load_Opts *opts, 243 Emile_Image_Load_Opts *opts EINA_UNUSED,
185 Emile_Image_Animated *animated, 244 Emile_Image_Animated *animated EINA_UNUSED,
186 Emile_Image_Load_Error *error) 245 Emile_Image_Load_Error *error)
187{ 246{
188 const unsigned char *m; 247 const unsigned char *m;
@@ -220,6 +279,9 @@ _emile_tgv_head(Emile_Image *image,
220 m = _emile_image_file_source_map(image, &length); 279 m = _emile_image_file_source_map(image, &length);
221 if (!m) return EINA_FALSE; 280 if (!m) return EINA_FALSE;
222 281
282 // This can be used for later ABI change of the structure.
283 if (sizeof (Emile_Image_Property) != property_size) return EINA_FALSE;
284
223 switch (m[OFFSET_ALGORITHM] & 0xFF) 285 switch (m[OFFSET_ALGORITHM] & 0xFF)
224 { 286 {
225 case 0: 287 case 0:
@@ -343,6 +405,8 @@ _emile_tgv_data(Emile_Image *image,
343 return EINA_FALSE; 405 return EINA_FALSE;
344 } 406 }
345 407
408 if (sizeof (Emile_Image_Property) != property_size) return EINA_FALSE;
409
346 offset = OFFSET_BLOCKS; 410 offset = OFFSET_BLOCKS;
347 411
348 *error = EMILE_IMAGE_LOAD_ERROR_CORRUPT_FILE; 412 *error = EMILE_IMAGE_LOAD_ERROR_CORRUPT_FILE;
@@ -412,7 +476,6 @@ _emile_tgv_data(Emile_Image *image,
412 Eina_Rectangle current; 476 Eina_Rectangle current;
413 Eina_Binbuf *data_start; 477 Eina_Binbuf *data_start;
414 const unsigned char *it; 478 const unsigned char *it;
415 unsigned int expand_length;
416 unsigned int i, j; 479 unsigned int i, j;
417 480
418 block_length = _tgv_length_get(m + offset, length, &offset); 481 block_length = _tgv_length_get(m + offset, length, &offset);
@@ -566,22 +629,692 @@ _emile_tgv_close(Emile_Image *image EINA_UNUSED)
566} 629}
567 630
568/* JPEG Handling */ 631/* JPEG Handling */
632
633typedef struct _JPEG_error_mgr *emptr;
634struct _JPEG_error_mgr
635{
636 struct jpeg_error_mgr pub;
637 jmp_buf setjmp_buffer;
638};
639
640struct jpeg_membuf_src
641{
642 struct jpeg_source_mgr pub;
643
644 const unsigned char *buf;
645 size_t len;
646 struct jpeg_membuf_src *self;
647};
648
649static void
650_JPEGFatalErrorHandler(j_common_ptr cinfo)
651{
652 emptr errmgr;
653
654 errmgr = (emptr) cinfo->err;
655 longjmp(errmgr->setjmp_buffer, 1);
656 return;
657}
658
659static void
660_JPEGErrorHandler(j_common_ptr cinfo EINA_UNUSED)
661{
662 return;
663}
664
665static void
666_JPEGErrorHandler2(j_common_ptr cinfo EINA_UNUSED, int msg_level EINA_UNUSED)
667{
668 return;
669}
670
671static void
672_emile_jpeg_membuf_src_init(j_decompress_ptr cinfo EINA_UNUSED)
673{
674}
675
676static boolean
677_emile_jpeg_membuf_src_fill(j_decompress_ptr cinfo)
678{
679 static const JOCTET jpeg_eoi[2] = { 0xFF, JPEG_EOI };
680 struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
681
682 src->pub.bytes_in_buffer = sizeof(jpeg_eoi);
683 src->pub.next_input_byte = jpeg_eoi;
684
685 return TRUE;
686}
687
688static void
689_emile_jpeg_membuf_src_skip(j_decompress_ptr cinfo,
690 long num_bytes)
691{
692 struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
693
694 if ((((long)src->pub.bytes_in_buffer - (long)src->len) > num_bytes) ||
695 ((long)src->pub.bytes_in_buffer < num_bytes))
696 {
697 (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo));
698 return;
699 }
700 src->pub.bytes_in_buffer -= num_bytes;
701 src->pub.next_input_byte += num_bytes;
702}
703
704static void
705_emile_jpeg_membuf_src_term(j_decompress_ptr cinfo)
706{
707 struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
708 if (!src) return;
709 free(src);
710 cinfo->src = NULL;
711}
712
713static int
714_emile_jpeg_membuf_src(j_decompress_ptr cinfo,
715 const void *map, size_t length)
716{
717 struct jpeg_membuf_src *src;
718
719 src = calloc(1, sizeof(*src));
720 if (!src)
721 return -1;
722
723 src->self = src;
724
725 cinfo->src = &src->pub;
726 src->buf = map;
727 src->len = length;
728 src->pub.init_source = _emile_jpeg_membuf_src_init;
729 src->pub.fill_input_buffer = _emile_jpeg_membuf_src_fill;
730 src->pub.skip_input_data = _emile_jpeg_membuf_src_skip;
731 src->pub.resync_to_restart = jpeg_resync_to_restart;
732 src->pub.term_source = _emile_jpeg_membuf_src_term;
733 src->pub.bytes_in_buffer = src->len;
734 src->pub.next_input_byte = src->buf;
735
736 return 0;
737}
738
739/*! Magic number for EXIF header, App0, App1*/
740static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
741static const unsigned char JfifHeader[] = {0x4A, 0x46, 0x49, 0x46, 0x00};
742static const unsigned char JfxxHeader[] = {0x4A, 0x46, 0x58, 0x58, 0x00};
743static const unsigned char App0[] = {0xff, 0xe0};
744static const unsigned char App1[] = {0xff, 0xe1};
745static const unsigned char II[] = {0x49, 0x49};
746static const unsigned char MM[] = {0x4d, 0x4d};
747typedef enum {
748 EXIF_BYTE_ALIGN_II,
749 EXIF_BYTE_ALIGN_MM
750} ExifByteAlign;
751
569static Eina_Bool 752static Eina_Bool
570_emile_jpeg_bind(Emile_Image *image, 753_get_next_app0(const unsigned char *map, size_t fsize, size_t *position)
571 Emile_Image_Load_Opts *opts, 754{
572 Emile_Image_Animated *animated, 755 unsigned short length = 0;
573 Emile_Image_Load_Error *error) 756 unsigned int w = 0, h = 0;
757 unsigned int format = 0;
758 unsigned int data_size = 0;
759 const unsigned char *app0_head, *p;
760
761 /* header_mark:2, length:2, identifier:5 version:2, unit:1, den=4 thum=2 */
762 if ((*position + 16) >= fsize) return EINA_FALSE;
763 app0_head = map + *position;
764
765 /* p is appn's start pointer excluding app0 marker */
766 p = app0_head + 2;
767
768 length = ((*p << 8) + *(p + 1));
769
770 /* JFIF segment format */
771 if (!memcmp(p + 2, JfifHeader, sizeof (JfifHeader)))
772 {
773 format = 3;
774 w = *(p + 14);
775 h = *(p + 15);
776 }
777 else if (!memcmp(p + 2, JfxxHeader, sizeof (JfxxHeader)))
778 {
779 if (*(p + 7) == 0x11)
780 format = 1;
781 else
782 format = 3;
783 w = *(p + 8);
784 h = *(p + 9);
785 }
786
787 data_size = format * w * h;
788
789 if ((*position + 2+ length + data_size) > fsize)
790 return EINA_FALSE;
791
792 *position = *position + 2 + length + data_size;
793
794 return EINA_TRUE;
795}
796
797/* If app1 data is abnormal, returns EINA_FALSE.
798 If app1 data is normal, returns EINA_TRUE.
799 If app1 data is normal but not orientation data, orientation value is -1.
800 */
801
802static Eina_Bool
803_get_orientation_app1(const unsigned char *map, size_t fsize, size_t *position,
804 int *orientation_res, Eina_Bool *flipped)
574{ 805{
806 const unsigned char *app1_head, *buf;
807 unsigned char orientation[2];
808 ExifByteAlign byte_align;
809 unsigned int num_directory = 0;
810 unsigned int i, j;
811 int direction;
812 unsigned int data_size = 0;
813
814 /* app1 mark:2, data_size:2, exif:6 tiff:8 */
815 if ((*position + 18) >= fsize) return EINA_FALSE;
816 app1_head = map + *position;
817 buf = app1_head;
818
819 data_size = ((*(buf + 2) << 8) + *(buf + 3));
820 if ((*position + 2 + data_size) > fsize) return EINA_FALSE;
821
822 if (memcmp(buf + 4, ExifHeader, sizeof (ExifHeader)))
823 {
824 *position = *position + 2 + data_size;
825 *orientation_res = -1;
826 return EINA_TRUE;
827 }
828
829 /* 2. get 10&11 byte get info of "II(0x4949)" or "MM(0x4d4d)" */
830 /* 3. get [18]&[19] get directory entry # */
831 if (!memcmp(buf + 10, MM, sizeof (MM)))
832 {
833 byte_align = EXIF_BYTE_ALIGN_MM;
834 num_directory = ((*(buf + 18) << 8) + *(buf + 19));
835 orientation[0] = 0x01;
836 orientation[1] = 0x12;
837 }
838 else if (!memcmp(buf + 10, II, sizeof (II)))
839 {
840 byte_align = EXIF_BYTE_ALIGN_II;
841 num_directory = ((*(buf + 19) << 8) + *(buf + 18));
842 orientation[0] = 0x12;
843 orientation[1] = 0x01;
844 }
845 else return EINA_FALSE;
846
847 /* check num_directory data */
848 if ((*position + (12 * num_directory + 20)) > fsize) return EINA_FALSE;
849
850 buf = app1_head + 20;
851
852 j = 0;
853
854 for (i = 0; i < num_directory; i++ )
855 {
856 if (!memcmp(buf + j, orientation, 2))
857 {
858 /*get orientation tag */
859 if (byte_align == EXIF_BYTE_ALIGN_MM)
860 direction = *(buf+ j + 9);
861 else direction = *(buf+ j + 8);
862 switch (direction)
863 {
864 case 3:
865 *orientation_res = 180;
866 *flipped = EINA_FALSE;
867 return EINA_TRUE;
868 case 4:
869 *orientation_res = 180;
870 *flipped = EINA_TRUE;
871 return EINA_TRUE;
872 case 6:
873 *orientation_res = 90;
874 *flipped = EINA_FALSE;
875 return EINA_TRUE;
876 case 7:
877 *orientation_res = 90;
878 *flipped = EINA_TRUE;
879 return EINA_TRUE;
880 case 5:
881 *orientation_res = 270;
882 *flipped = EINA_TRUE;
883 return EINA_TRUE;
884 case 8:
885 *orientation_res = 270;
886 *flipped = EINA_FALSE;
887 return EINA_TRUE;
888 case 2:
889 *orientation_res = 0;
890 *flipped = EINA_TRUE;
891 return EINA_TRUE;
892 default:
893 *orientation_res = 0;
894 *flipped = EINA_FALSE;
895 return EINA_TRUE;
896 }
897 }
898 else
899 j = j + 12;
900 }
575 return EINA_FALSE; 901 return EINA_FALSE;
576} 902}
577 903
904static int
905_get_orientation(const void *map, size_t length, Eina_Bool *flipped)
906{
907 unsigned char *buf;
908 size_t position = 0;
909 int orientation = -1;
910 Eina_Bool res = EINA_FALSE;
911
912 *flipped = EINA_FALSE;
913
914 /* open file and get 22 byte frome file */
915 if (!map) return 0;
916 /* 1. read 22byte */
917 if (length < 22) return 0;
918 buf = (unsigned char *)map;
919
920 position = 2;
921 /* 2. check 2,3 bypte with APP0(0xFFE0) or APP1(0xFFE1) */
922 while((length - position) > 0)
923 {
924 if (!memcmp(buf + position, App0, sizeof (App0)))
925 {
926 res = _get_next_app0(map, length, &position);
927 if (!res) break;
928 }
929 else if (!memcmp(buf + position, App1, sizeof (App1)))
930 {
931 res = _get_orientation_app1(map, length, &position, &orientation, flipped);
932 if (!res) break;
933 if (orientation != -1) return orientation;
934 }
935 else break;
936 }
937 return 0;
938}
939
940static void
941_rotate_region(unsigned int *r_x, unsigned int *r_y, unsigned int *r_w, unsigned int *r_h,
942 unsigned int x, unsigned int y, unsigned int w, unsigned int h,
943 unsigned int output_w, unsigned int output_h,
944 int degree, Eina_Bool flipped)
945{
946 switch (degree)
947 {
948 case 90:
949 if (flipped)
950 {
951 *r_x = output_w - (y + h);
952 *r_y = output_h - (x + w);
953 *r_w = h;
954 *r_h = w;
955 }
956 else
957 {
958 *r_x = y;
959 *r_y = output_h - (x + y);
960 *r_w = h;
961 *r_h = w;
962 }
963 break;
964 case 180:
965 if (flipped)
966 {
967 *r_y = output_h - (y + h);
968 }
969 else
970 {
971 *r_x = output_w - (x + w);
972 *r_y = output_h - (y + h);
973 }
974 break;
975 case 270:
976 if (flipped)
977 {
978 *r_x = y;
979 *r_y = x;
980 *r_w = h;
981 *r_h = w;
982 }
983 else
984 {
985 *r_x = output_w - (y + h);
986 *r_y = x;
987 *r_w = h;
988 *r_h = w;
989 }
990 break;
991 default:
992 if (flipped)
993 *r_x = output_w - (x + w);
994 break;
995 }
996}
997
998static void
999_rotate_180(uint32_t *data, int w, int h)
1000{
1001 uint32_t *p1, *p2;
1002 uint32_t pt;
1003 int x;
1004
1005 p1 = data;
1006 p2 = data + (h * w) - 1;
1007 for (x = (w * h) / 2; --x >= 0;)
1008 {
1009 pt = *p1;
1010 *p1 = *p2;
1011 *p2 = pt;
1012 p1++;
1013 p2--;
1014 }
1015}
1016
1017static void
1018_flip_horizontal(uint32_t *data, int w, int h)
1019{
1020 uint32_t *p1, *p2;
1021 uint32_t pt;
1022 int x, y;
1023
1024 for (y = 0; y < h; y++)
1025 {
1026 p1 = data + (y * w);
1027 p2 = data + ((y + 1) * w) - 1;
1028 for (x = 0; x < (w >> 1); x++)
1029 {
1030 pt = *p1;
1031 *p1 = *p2;
1032 *p2 = pt;
1033 p1++;
1034 p2--;
1035 }
1036 }
1037}
1038
1039static void
1040_flip_vertical(uint32_t *data, int w, int h)
1041{
1042 uint32_t *p1, *p2;
1043 uint32_t pt;
1044 int x, y;
1045
1046 for (y = 0; y < (h >> 1); y++)
1047 {
1048 p1 = data + (y * w);
1049 p2 = data + ((h - 1 - y) * w);
1050 for (x = 0; x < w; x++)
1051 {
1052 pt = *p1;
1053 *p1 = *p2;
1054 *p2 = pt;
1055 p1++;
1056 p2++;
1057 }
1058 }
1059}
1060
1061static void
1062_rotate_change_wh(uint32_t *to, uint32_t *from,
1063 int w, int h,
1064 int dx, int dy)
1065{
1066 int x, y;
1067
1068 for (x = h; --x >= 0;)
1069 {
1070 for (y = w; --y >= 0;)
1071 {
1072 *to = *from;
1073 from++;
1074 to += dy;
1075 }
1076 to += dx;
1077 }
1078}
1079
1080static Eina_Bool
1081_emile_jpeg_bind(Emile_Image *image EINA_UNUSED,
1082 Emile_Image_Load_Opts *opts EINA_UNUSED,
1083 Emile_Image_Animated *animated EINA_UNUSED,
1084 Emile_Image_Load_Error *error EINA_UNUSED)
1085{
1086 return EINA_TRUE;
1087}
1088
578static Eina_Bool 1089static Eina_Bool
579_emile_jpeg_head(Emile_Image *image, 1090_emile_jpeg_head(Emile_Image *image,
580 Emile_Image_Property *prop, 1091 Emile_Image_Property *prop,
581 unsigned int property_size, 1092 unsigned int property_size,
582 Emile_Image_Load_Error *error) 1093 Emile_Image_Load_Error *error)
583{ 1094{
584 return EINA_FALSE; 1095 Emile_Image_Load_Opts *opts = NULL;
1096 const unsigned char *m;
1097 unsigned int scalew, scaleh;
1098 struct jpeg_decompress_struct cinfo;
1099 struct _JPEG_error_mgr jerr;
1100 unsigned int length;
1101
1102 /* for rotation decoding */
1103 int degree = 0;
1104 Eina_Bool change_wh = EINA_FALSE;
1105 unsigned int load_opts_w = 0, load_opts_h = 0;
1106
1107
1108 if (sizeof (Emile_Image_Property) != property_size)
1109 return EINA_FALSE;
1110
1111 m = _emile_image_file_source_map(image, &length);
1112 if (!m) return EINA_FALSE;
1113
1114 if (image->load_opts)
1115 opts = &image->opts;
1116
1117 memset(&cinfo, 0, sizeof(cinfo));
1118 cinfo.err = jpeg_std_error(&(jerr.pub));
1119 jerr.pub.error_exit = _JPEGFatalErrorHandler;
1120 jerr.pub.emit_message = _JPEGErrorHandler2;
1121 jerr.pub.output_message = _JPEGErrorHandler;
1122 if (setjmp(jerr.setjmp_buffer))
1123 {
1124 jpeg_destroy_decompress(&cinfo);
1125 _emile_jpeg_membuf_src_term(&cinfo);
1126 if (cinfo.saw_JFIF_marker)
1127 *error = EMILE_IMAGE_LOAD_ERROR_CORRUPT_FILE;
1128 else
1129 *error = EMILE_IMAGE_LOAD_ERROR_UNKNOWN_FORMAT;
1130 return EINA_FALSE;
1131 }
1132 jpeg_create_decompress(&cinfo);
1133
1134 if (_emile_jpeg_membuf_src(&cinfo, m, length))
1135 {
1136 jpeg_destroy_decompress(&cinfo);
1137 _emile_jpeg_membuf_src_term(&cinfo);
1138 *error = EMILE_IMAGE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
1139 return EINA_FALSE;
1140 }
1141
1142 if (cinfo.output_components == 1)
1143 {
1144 // We do handle GRY8 colorspace as an output for JPEG
1145 prop->cspaces = cspaces_gry;
1146 }
1147
1148 jpeg_read_header(&cinfo, TRUE);
1149 cinfo.do_fancy_upsampling = FALSE;
1150 cinfo.do_block_smoothing = FALSE;
1151 cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss)
1152 cinfo.dither_mode = JDITHER_ORDERED;
1153 cinfo.buffered_image = TRUE; // buffered mode in case jpg is progressive
1154 jpeg_start_decompress(&cinfo);
1155
1156 /* rotation decoding */
1157 if (opts->orientation)
1158 {
1159 degree = _get_orientation(m, length, &prop->flipped);
1160 if (degree != 0 || prop->flipped)
1161 {
1162 opts->degree = degree;
1163 prop->rotated = EINA_TRUE;
1164
1165 if (degree == 90 || degree == 270)
1166 change_wh = EINA_TRUE;
1167 }
1168
1169 }
1170
1171 /* head decoding */
1172 prop->w = cinfo.output_width;
1173 prop->h = cinfo.output_height;
1174 if ((prop->w < 1) || (prop->h < 1) || (prop->w > IMG_MAX_SIZE) || (prop->h > IMG_MAX_SIZE) ||
1175 (IMG_TOO_BIG(prop->w, prop->h)))
1176 {
1177 jpeg_destroy_decompress(&cinfo);
1178 _emile_jpeg_membuf_src_term(&cinfo);
1179 if (IMG_TOO_BIG(prop->w, prop->h))
1180 *error = EMILE_IMAGE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
1181 else
1182 *error = EMILE_IMAGE_LOAD_ERROR_GENERIC;
1183 return EINA_FALSE;
1184 }
1185 if (opts->scale_down_by > 1)
1186 {
1187 prop->w /= opts->scale_down_by;
1188 prop->h /= opts->scale_down_by;
1189 }
1190 else if (opts->dpi > 0.0)
1191 {
1192 prop->w = (prop->w * opts->dpi) / 90.0;
1193 prop->h = (prop->h * opts->dpi) / 90.0;
1194 }
1195 else if ((opts->w > 0) && (opts->h > 0))
1196 {
1197 unsigned int w2 = prop->w, h2 = prop->h;
1198 /* user set load_opts' w,h on the assumption
1199 that image already rotated according to it's orientation info */
1200 if (change_wh)
1201 {
1202 load_opts_w = opts->w;
1203 load_opts_h = opts->h;
1204 opts->w = load_opts_h;
1205 opts->h = load_opts_w;
1206 }
1207
1208 if (opts->w > 0)
1209 {
1210 w2 = opts->w;
1211 h2 = (opts->w * prop->h) / prop->w;
1212 if ((opts->h > 0) && (h2 > opts->h))
1213 {
1214 unsigned int w3;
1215 h2 = opts->h;
1216 w3 = (opts->h * prop->w) / prop->h;
1217 if (w3 > w2)
1218 w2 = w3;
1219 }
1220 }
1221 else if (opts->h > 0)
1222 {
1223 h2 = opts->h;
1224 w2 = (opts->h * prop->w) / prop->h;
1225 }
1226 prop->w = w2;
1227 prop->h = h2;
1228 if (change_wh)
1229 {
1230 opts->w = load_opts_w;
1231 opts->h = load_opts_h;
1232 }
1233 }
1234 if (prop->w < 1) prop->w = 1;
1235 if (prop->h < 1) prop->h = 1;
1236
1237 if ((prop->w != cinfo.output_width) || (prop->h != cinfo.output_height))
1238 {
1239 scalew = cinfo.output_width / prop->w;
1240 scaleh = cinfo.output_height / prop->h;
1241
1242 prop->scale = scalew;
1243 if (scaleh < scalew) prop->scale = scaleh;
1244
1245 if (prop->scale > 8) prop->scale = 8;
1246 else if (prop->scale < 1) prop->scale = 1;
1247
1248 if (prop->scale == 3) prop->scale = 2;
1249 else if (prop->scale == 5) prop->scale = 4;
1250 else if (prop->scale == 6) prop->scale = 4;
1251 else if (prop->scale == 7) prop->scale = 4;
1252 }
1253
1254 if (prop->scale > 1)
1255 {
1256 jpeg_destroy_decompress(&cinfo);
1257 _emile_jpeg_membuf_src_term(&cinfo);
1258 jpeg_create_decompress(&cinfo);
1259
1260 if (_emile_jpeg_membuf_src(&cinfo, m, length))
1261 {
1262 jpeg_destroy_decompress(&cinfo);
1263 _emile_jpeg_membuf_src_term(&cinfo);
1264 *error = EMILE_IMAGE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
1265 return EINA_FALSE;
1266 }
1267
1268 jpeg_read_header(&cinfo, TRUE);
1269 cinfo.do_fancy_upsampling = FALSE;
1270 cinfo.do_block_smoothing = FALSE;
1271 cinfo.scale_num = 1;
1272 cinfo.scale_denom = prop->scale;
1273 cinfo.buffered_image = TRUE; // buffered mode in case jpg is progressive
1274 jpeg_calc_output_dimensions(&(cinfo));
1275 jpeg_start_decompress(&cinfo);
1276 }
1277
1278 prop->w = cinfo.output_width;
1279 prop->h = cinfo.output_height;
1280
1281 // be nice and clip region to image. if its totally outside, fail load
1282 if ((opts->region.w > 0) && (opts->region.h > 0))
1283 {
1284 unsigned int load_region_x = opts->region.x, load_region_y = opts->region.y;
1285 unsigned int load_region_w = opts->region.w, load_region_h = opts->region.h;
1286 if (prop->rotated)
1287 {
1288 _rotate_region(&load_region_x, &load_region_y, &load_region_w, &load_region_h,
1289 opts->region.x, opts->region.y, opts->region.w, opts->region.h,
1290 prop->w, prop->h, degree, prop->flipped);
1291 }
1292 RECTS_CLIP_TO_RECT(load_region_x, load_region_y,
1293 load_region_w, load_region_h,
1294 0, 0, prop->w, prop->h);
1295 if ((load_region_w <= 0) || (load_region_h <= 0))
1296 {
1297 jpeg_destroy_decompress(&cinfo);
1298 _emile_jpeg_membuf_src_term(&cinfo);
1299 *error = EMILE_IMAGE_LOAD_ERROR_GENERIC;
1300 return EINA_FALSE;
1301 }
1302 prop->w = load_region_w;
1303 prop->h = load_region_h;
1304 }
1305/* end head decoding */
1306
1307 if (change_wh)
1308 {
1309 unsigned int tmp;
1310 tmp = prop->w;
1311 prop->w = prop->h;
1312 prop->h = tmp;
1313 }
1314 jpeg_destroy_decompress(&cinfo);
1315 _emile_jpeg_membuf_src_term(&cinfo);
1316 *error = EMILE_IMAGE_LOAD_ERROR_NONE;
1317 return EINA_TRUE;
585} 1318}
586 1319
587static Eina_Bool 1320static Eina_Bool
@@ -591,12 +1324,542 @@ _emile_jpeg_data(Emile_Image *image,
591 void *pixels, 1324 void *pixels,
592 Emile_Image_Load_Error *error) 1325 Emile_Image_Load_Error *error)
593{ 1326{
594 return EINA_FALSE; 1327 // Handle RGB, ARGB and GRY
1328 Emile_Image_Load_Opts *opts = NULL;
1329 unsigned int w, h;
1330 struct jpeg_decompress_struct cinfo;
1331 struct _JPEG_error_mgr jerr;
1332 const unsigned char *m = NULL;
1333 uint8_t *ptr, *line[16], *data;
1334 uint32_t *ptr2, *ptr_rotate = NULL;
1335 unsigned int x, y, l, i, scans;
1336 int region = 0;
1337 /* rotation setting */
1338 unsigned int ie_w = 0, ie_h = 0;
1339 struct {
1340 unsigned int x, y, w, h;
1341 } opts_region;
1342 volatile int degree = 0;
1343 volatile Eina_Bool change_wh = EINA_FALSE;
1344 Eina_Bool line_done = EINA_FALSE;
1345 unsigned int length;
1346
1347 if (sizeof (Emile_Image_Property) != property_size)
1348 return EINA_FALSE;
1349
1350 m = _emile_image_file_source_map(image, &length);
1351 if (!m) return EINA_FALSE;
1352
1353 if (image->load_opts)
1354 opts = &image->opts;
1355
1356 memset(&cinfo, 0, sizeof(cinfo));
1357 if (prop->rotated)
1358 {
1359 degree = opts->degree;
1360 if (degree == 90 || degree == 270)
1361 change_wh = EINA_TRUE;
1362 }
1363
1364 cinfo.err = jpeg_std_error(&(jerr.pub));
1365 jerr.pub.error_exit = _JPEGFatalErrorHandler;
1366 jerr.pub.emit_message = _JPEGErrorHandler2;
1367 jerr.pub.output_message = _JPEGErrorHandler;
1368 if (setjmp(jerr.setjmp_buffer))
1369 {
1370 jpeg_destroy_decompress(&cinfo);
1371 _emile_jpeg_membuf_src_term(&cinfo);
1372 *error = EMILE_IMAGE_LOAD_ERROR_CORRUPT_FILE;
1373 return EINA_FALSE;
1374 }
1375 jpeg_create_decompress(&cinfo);
1376
1377 if (_emile_jpeg_membuf_src(&cinfo, m, length))
1378 {
1379 jpeg_destroy_decompress(&cinfo);
1380 _emile_jpeg_membuf_src_term(&cinfo);
1381 *error = EMILE_IMAGE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
1382 return 0;
1383 }
1384
1385 jpeg_read_header(&cinfo, TRUE);
1386 cinfo.do_fancy_upsampling = FALSE;
1387 cinfo.do_block_smoothing = FALSE;
1388 cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss)
1389 cinfo.dither_mode = JDITHER_ORDERED;
1390
1391 if (prop->scale > 1)
1392 {
1393 cinfo.scale_num = 1;
1394 cinfo.scale_denom = prop->scale;
1395 }
1396
1397 /* Colorspace conversion options */
1398 /* libjpeg can do the following conversions: */
1399 /* GRAYSCLAE => RGB YCbCr => RGB and YCCK => CMYK */
1400 switch (cinfo.jpeg_color_space)
1401 {
1402 case JCS_UNKNOWN:
1403 break;
1404 case JCS_GRAYSCALE:
1405 case JCS_RGB:
1406 case JCS_YCbCr:
1407 cinfo.out_color_space = JCS_RGB;
1408 break;
1409 case JCS_CMYK:
1410 case JCS_YCCK:
1411 cinfo.out_color_space = JCS_CMYK;
1412 break;
1413 default:
1414 cinfo.out_color_space = JCS_RGB;
1415 break;
1416 }
1417
1418/* head decoding */
1419 jpeg_calc_output_dimensions(&(cinfo));
1420 jpeg_start_decompress(&cinfo);
1421
1422 w = cinfo.output_width;
1423 h = cinfo.output_height;
1424
1425 if (change_wh)
1426 {
1427 ie_w = prop->h;
1428 ie_h = prop->w;
1429 }
1430 else
1431 {
1432 ie_w = prop->w;
1433 ie_h = prop->h;
1434 }
1435
1436 if ((opts->region.w > 0) && (opts->region.h > 0))
1437 {
1438 region = 1;
1439
1440 opts_region.x = opts->region.x;
1441 opts_region.y = opts->region.y;
1442 opts_region.w = opts->region.w;
1443 opts_region.h = opts->region.h;
1444
1445 if (prop->rotated)
1446 {
1447 unsigned int load_region_x = 0, load_region_y = 0;
1448 unsigned int load_region_w = 0, load_region_h = 0;
1449
1450 load_region_x = opts->region.x;
1451 load_region_y = opts->region.y;
1452 load_region_w = opts->region.w;
1453 load_region_h = opts->region.h;
1454
1455 _rotate_region(&opts_region.x, &opts_region.y, &opts_region.w, &opts_region.h,
1456 load_region_x, load_region_y, load_region_w, load_region_h,
1457 w, h, degree, prop->flipped);
1458 }
1459#ifdef BUILD_LOADER_JPEG_REGION
1460 cinfo.region_x = opts_region.x;
1461 cinfo.region_y = opts_region.y;
1462 cinfo.region_w = opts_region.w;
1463 cinfo.region_h = opts_region.h;
1464#endif
1465 }
1466 if ((!region) && ((w != ie_w) || (h != ie_h)))
1467 {
1468 // race condition, the file could have change from when we call header
1469 // this test will not solve the problem with region code.
1470 jpeg_destroy_decompress(&cinfo);
1471 _emile_jpeg_membuf_src_term(&cinfo);
1472 *error = EMILE_IMAGE_LOAD_ERROR_GENERIC;
1473 return EINA_FALSE;
1474 }
1475 if ((region) &&
1476 ((ie_w != opts_region.w) || (ie_h != opts_region.h)))
1477 {
1478 jpeg_destroy_decompress(&cinfo);
1479 _emile_jpeg_membuf_src_term(&cinfo);
1480 *error = EMILE_IMAGE_LOAD_ERROR_GENERIC;
1481 return EINA_FALSE;
1482 /* ie_w = opts_region.w; */
1483 /* ie_h = opts_region.h; */
1484 /* if (change_wh) */
1485 /* { */
1486 /* ie->w = ie_h; */
1487 /* ie->h = ie_w; */
1488 /* } */
1489 /* else */
1490 /* { */
1491 /* ie->w = ie_w; */
1492 /* ie->h = ie_h; */
1493 /* } */
1494 }
1495
1496 if (!(((cinfo.out_color_space == JCS_RGB) &&
1497 ((cinfo.output_components == 3) || (cinfo.output_components == 1))) ||
1498 ((cinfo.out_color_space == JCS_CMYK) && (cinfo.output_components == 4))))
1499 {
1500 jpeg_destroy_decompress(&cinfo);
1501 _emile_jpeg_membuf_src_term(&cinfo);
1502 *error = EMILE_IMAGE_LOAD_ERROR_UNKNOWN_FORMAT;
1503 return EINA_FALSE;
1504 }
1505
1506/* end head decoding */
1507/* data decoding */
1508 if (cinfo.rec_outbuf_height > 16)
1509 {
1510 jpeg_destroy_decompress(&cinfo);
1511 _emile_jpeg_membuf_src_term(&cinfo);
1512 *error = EMILE_IMAGE_LOAD_ERROR_UNKNOWN_FORMAT;
1513 return EINA_FALSE;
1514 }
1515 data = alloca(w * 16 * cinfo.output_components);
1516 if ((prop->rotated) && change_wh)
1517 {
1518 ptr2 = malloc(w * h * sizeof(uint32_t));
1519 ptr_rotate = ptr2;
1520 }
1521 else
1522 ptr2 = pixels;
1523
1524 if (!ptr2)
1525 {
1526 *error = EMILE_IMAGE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
1527 return EINA_FALSE;
1528 }
1529
1530 /* We handle first CMYK (4 components) */
1531 if (cinfo.output_components == 4)
1532 {
1533 // FIXME: handle region
1534 for (i = 0; (int)i < cinfo.rec_outbuf_height; i++)
1535 line[i] = data + (i * w * 4);
1536 for (l = 0; l < h; l += cinfo.rec_outbuf_height)
1537 {
1538 jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
1539 scans = cinfo.rec_outbuf_height;
1540 if ((h - l) < scans) scans = h - l;
1541 ptr = data;
1542 if (!region)
1543 {
1544 for (y = 0; y < scans; y++)
1545 {
1546 if (cinfo.saw_Adobe_marker)
1547 {
1548 for (x = 0; x < w; x++)
1549 {
1550 /* According to libjpeg doc, Photoshop inverse the values of C, M, Y and K, */
1551 /* that is C is replaces by 255 - C, etc...*/
1552 /* See the comment below for the computation of RGB values from CMYK ones. */
1553 *ptr2 =
1554 (0xff000000) |
1555 ((ptr[0] * ptr[3] / 255) << 16) |
1556 ((ptr[1] * ptr[3] / 255) << 8) |
1557 ((ptr[2] * ptr[3] / 255));
1558 ptr += 4;
1559 ptr2++;
1560 }
1561 }
1562 else
1563 {
1564 for (x = 0; x < w; x++)
1565 {
1566 /* Conversion from CMYK to RGB is done in 2 steps: */
1567 /* CMYK => CMY => RGB (see http://www.easyrgb.com/index.php?X=MATH) */
1568 /* after computation, if C, M, Y and K are between 0 and 1, we have: */
1569 /* R = (1 - C) * (1 - K) * 255 */
1570 /* G = (1 - M) * (1 - K) * 255 */
1571 /* B = (1 - Y) * (1 - K) * 255 */
1572 /* libjpeg stores CMYK values between 0 and 255, */
1573 /* so we replace C by C * 255 / 255, etc... and we obtain: */
1574 /* R = (255 - C) * (255 - K) / 255 */
1575 /* G = (255 - M) * (255 - K) / 255 */
1576 /* B = (255 - Y) * (255 - K) / 255 */
1577 /* with C, M, Y and K between 0 and 255. */
1578 *ptr2 =
1579 (0xff000000) |
1580 (((255 - ptr[0]) * (255 - ptr[3]) / 255) << 16) |
1581 (((255 - ptr[1]) * (255 - ptr[3]) / 255) << 8) |
1582 (((255 - ptr[2]) * (255 - ptr[3]) / 255));
1583 ptr += 4;
1584 ptr2++;
1585 }
1586 }
1587 }
1588 }
1589 else
1590 {
1591 // if line # > region last line, break
1592 if (l >= (opts_region.y + opts_region.h))
1593 {
1594 line_done = EINA_TRUE;
1595 /* if rotation flag is set , we have to rotate image */
1596 goto done;
1597 /*jpeg_destroy_decompress(&cinfo);
1598 _emile_jpeg_membuf_src_term(&cinfo);
1599 *error = EMILE_IMAGE_LOAD_ERROR_NONE;
1600 return EINA_FALSE;*/
1601 }
1602 // els if scan block intersects region start or later
1603 else if ((l + scans) >
1604 (opts_region.y))
1605 {
1606 for (y = 0; y < scans; y++)
1607 {
1608 if (((y + l) >= opts_region.y) &&
1609 ((y + l) < (opts_region.y + opts_region.h)))
1610 {
1611 ptr += opts_region.x;
1612 if (cinfo.saw_Adobe_marker)
1613 {
1614 for (x = 0; x < opts_region.w; x++)
1615 {
1616 /* According to libjpeg doc, Photoshop inverse the values of C, M, Y and K, */
1617 /* that is C is replaces by 255 - C, etc...*/
1618 /* See the comment below for the computation of RGB values from CMYK ones. */
1619 *ptr2 =
1620 (0xff000000) |
1621 ((ptr[0] * ptr[3] / 255) << 16) |
1622 ((ptr[1] * ptr[3] / 255) << 8) |
1623 ((ptr[2] * ptr[3] / 255));
1624 ptr += 4;
1625 ptr2++;
1626 }
1627 }
1628 else
1629 {
1630 for (x = 0; x < opts_region.w; x++)
1631 {
1632 /* Conversion from CMYK to RGB is done in 2 steps: */
1633 /* CMYK => CMY => RGB (see http://www.easyrgb.com/index.php?X=MATH) */
1634 /* after computation, if C, M, Y and K are between 0 and 1, we have: */
1635 /* R = (1 - C) * (1 - K) * 255 */
1636 /* G = (1 - M) * (1 - K) * 255 */
1637 /* B = (1 - Y) * (1 - K) * 255 */
1638 /* libjpeg stores CMYK values between 0 and 255, */
1639 /* so we replace C by C * 255 / 255, etc... and we obtain: */
1640 /* R = (255 - C) * (255 - K) / 255 */
1641 /* G = (255 - M) * (255 - K) / 255 */
1642 /* B = (255 - Y) * (255 - K) / 255 */
1643 /* with C, M, Y and K between 0 and 255. */
1644 *ptr2 =
1645 (0xff000000) |
1646 (((255 - ptr[0]) * (255 - ptr[3]) / 255) << 16) |
1647 (((255 - ptr[1]) * (255 - ptr[3]) / 255) << 8) |
1648 (((255 - ptr[2]) * (255 - ptr[3]) / 255));
1649 ptr += 4;
1650 ptr2++;
1651 }
1652 }
1653 ptr += (4 * (w - (opts_region.x + opts_region.w)));
1654 }
1655 else
1656 ptr += (4 * w);
1657 }
1658 }
1659 }
1660 }
1661 }
1662 /* We handle then RGB with 3 components */
1663 else if (cinfo.output_components == 3)
1664 {
1665/*
1666 double t;
1667 if (region)
1668 {
1669 // debug for now
1670 printf("R| %p %5ix%5i %s: %5i %5i %5ix%5i - ",
1671 ie,
1672 ie->w, ie->h,
1673 ie->file,
1674 opts_region.x,
1675 opts_region.y,
1676 opts_region.w,
1677 opts_region.h);
1678 }
1679 t = get_time();
1680 */
1681 for (i = 0; (int)i < cinfo.rec_outbuf_height; i++)
1682 line[i] = data + (i * w * 3);
1683 for (l = 0; l < h; l += cinfo.rec_outbuf_height)
1684 {
1685 jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
1686 scans = cinfo.rec_outbuf_height;
1687 if ((h - l) < scans) scans = h - l;
1688 ptr = data;
1689 if (!region)
1690 {
1691 for (y = 0; y < scans; y++)
1692 {
1693 for (x = 0; x < w; x++)
1694 {
1695 *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[1], ptr[2]);
1696 ptr += 3;
1697 ptr2++;
1698 }
1699 }
1700 }
1701 else
1702 {
1703 // if line # > region last line, break
1704 // but not return immediately for rotation job
1705 if (l >= (opts_region.y + opts_region.h))
1706 {
1707 line_done = EINA_TRUE;
1708 /* if rotation flag is set , we have to rotate image */
1709 goto done;
1710 }
1711 // else if scan block intersects region start or later
1712 else if ((l + scans) >
1713 (opts_region.y))
1714 {
1715 for (y = 0; y < scans; y++)
1716 {
1717 if (((y + l) >= opts_region.y) &&
1718 ((y + l) < (opts_region.y + opts_region.h)))
1719 {
1720 ptr += (3 * opts_region.x);
1721 for (x = 0; x < opts_region.w; x++)
1722 {
1723 *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[1], ptr[2]);
1724 ptr += 3;
1725 ptr2++;
1726 }
1727 ptr += (3 * (w - (opts_region.x + opts_region.w)));
1728 }
1729 else
1730 ptr += (3 * w);
1731 }
1732 }
1733 }
1734 }
1735/*
1736 t = get_time() - t;
1737 printf("%3.3f\n", t);
1738 */
1739 }
1740 /* We finally handle RGB with 1 component */
1741 else if (cinfo.output_components == 1)
1742 {
1743 for (i = 0; (int)i < cinfo.rec_outbuf_height; i++)
1744 line[i] = data + (i * w);
1745 for (l = 0; l < h; l += cinfo.rec_outbuf_height)
1746 {
1747 jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
1748 scans = cinfo.rec_outbuf_height;
1749 if ((h - l) < scans) scans = h - l;
1750 ptr = data;
1751 if (!region)
1752 {
1753 for (y = 0; y < scans; y++)
1754 {
1755 for (x = 0; x < w; x++)
1756 {
1757 *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[0], ptr[0]);
1758 ptr++;
1759 ptr2++;
1760 }
1761 }
1762 }
1763 else
1764 {
1765 // if line # > region last line, break
1766 if (l >= (opts_region.y + opts_region.h))
1767 {
1768 line_done = EINA_TRUE;
1769 /* if rotation flag is set , we have to rotate image */
1770 goto done;
1771 /*jpeg_destroy_decompress(&cinfo);
1772 _emile_jpeg_membuf_src_term(&cinfo);
1773 *error = EMILE_IMAGE_LOAD_ERROR_NONE;
1774 return EINA_TRUE;*/
1775 }
1776 // els if scan block intersects region start or later
1777 else if ((l + scans) >
1778 (opts_region.y))
1779 {
1780 for (y = 0; y < scans; y++)
1781 {
1782 if (((y + l) >= opts_region.y) &&
1783 ((y + l) < (opts_region.y + opts_region.h)))
1784 {
1785 ptr += opts_region.x;
1786 for (x = 0; x < opts_region.w; x++)
1787 {
1788 *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[0], ptr[0]);
1789 ptr++;
1790 ptr2++;
1791 }
1792 ptr += w - (opts_region.x + opts_region.w);
1793 }
1794 else
1795 ptr += w;
1796 }
1797 }
1798 }
1799 }
1800 }
1801 /* if rotation operation need, rotate it */
1802done:
1803
1804 if (prop->rotated)
1805 {
1806 uint32_t *to;
1807 int hw;
1808
1809 hw = w * h;
1810 to = pixels;
1811
1812 switch (degree)
1813 {
1814 case 90:
1815 if (prop->flipped)
1816 _rotate_change_wh(to + hw - 1, ptr_rotate, w, h, hw - 1, -h);
1817 else
1818 _rotate_change_wh(to + h - 1, ptr_rotate, w, h, -hw - 1, h);
1819 break;
1820 case 180:
1821 if (prop->flipped)
1822 _flip_vertical(to, w, h);
1823 else
1824 _rotate_180(to, w, h);
1825 break;
1826 case 270:
1827 if (prop->flipped)
1828 _rotate_change_wh(to, ptr_rotate, w, h, -hw + 1, h);
1829 else
1830 _rotate_change_wh(to + hw - h, ptr_rotate, w, h, hw + 1, -h);
1831 break;
1832 default:
1833 if (prop->flipped)
1834 _flip_horizontal(to, w, h);
1835 break;
1836 }
1837 if (ptr_rotate)
1838 {
1839 free(ptr_rotate);
1840 ptr_rotate = NULL;
1841 }
1842 }
1843
1844 if (line_done)
1845 {
1846 jpeg_destroy_decompress(&cinfo);
1847 _emile_jpeg_membuf_src_term(&cinfo);
1848 *error = EMILE_IMAGE_LOAD_ERROR_NONE;
1849 return EINA_FALSE;
1850 }
1851 /* end data decoding */
1852 jpeg_finish_decompress(&cinfo);
1853 jpeg_destroy_decompress(&cinfo);
1854 _emile_jpeg_membuf_src_term(&cinfo);
1855 *error = EMILE_IMAGE_LOAD_ERROR_NONE;
1856 return EINA_TRUE;
595} 1857}
596 1858
597static void 1859static void
598_emile_jpeg_close(Emile_Image *image) 1860_emile_jpeg_close(Emile_Image *image EINA_UNUSED)
599{ 1861{
1862 // JPEG file loader doesn't keep any data allocated around (for now)
600} 1863}
601 1864
602/* Generic helper to instantiate a new Emile_Image */ 1865/* Generic helper to instantiate a new Emile_Image */