summaryrefslogtreecommitdiff
path: root/src/modules/evas/loaders/jpeg/evas_image_load_jpeg.c
diff options
context:
space:
mode:
authorJiyoun Park <jy0703.park@samsung.com>2013-06-29 15:00:43 +0900
committerJiyoun Park <jy0703.park@samsung.com>2013-06-29 15:00:43 +0900
commit958a430f5e5aab7c232671be7352fa44a1b8e971 (patch)
treef0c0ea8354a0fbe2ebede99ecf03f943c38b9f50 /src/modules/evas/loaders/jpeg/evas_image_load_jpeg.c
parent7927c0f9fa742c6b57e97ce3ad348633db369844 (diff)
* Evas: Fix jpeg loader cannot deal with exif information correctly
Diffstat (limited to '')
-rw-r--r--src/modules/evas/loaders/jpeg/evas_image_load_jpeg.c115
1 files changed, 78 insertions, 37 deletions
diff --git a/src/modules/evas/loaders/jpeg/evas_image_load_jpeg.c b/src/modules/evas/loaders/jpeg/evas_image_load_jpeg.c
index 96de9c6f84..3d9999a179 100644
--- a/src/modules/evas/loaders/jpeg/evas_image_load_jpeg.c
+++ b/src/modules/evas/loaders/jpeg/evas_image_load_jpeg.c
@@ -32,8 +32,8 @@ struct _Evas_Loader_Internal
32static void _JPEGFatalErrorHandler(j_common_ptr cinfo); 32static void _JPEGFatalErrorHandler(j_common_ptr cinfo);
33static void _JPEGErrorHandler(j_common_ptr cinfo); 33static void _JPEGErrorHandler(j_common_ptr cinfo);
34static void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level); 34static void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
35static int _get_orientation_app0(char *app0_head, size_t remain_length); 35static Eina_Bool _get_next_app0(unsigned char *map, size_t fsize, size_t *position);
36static int _get_orientation_app1(char *app1_head, size_t remain_length); 36static Eina_Bool _get_orientation_app1(unsigned char *map, size_t fsize, size_t *position, int *orientation);
37static int _get_orientation(void *map, size_t length); 37static int _get_orientation(void *map, size_t length);
38 38
39#if 0 /* not used at the moment */ 39#if 0 /* not used at the moment */
@@ -156,24 +156,29 @@ static const unsigned char JfifHeader[] = {0x4A, 0x46, 0x49, 0x46, 0x00};
156static const unsigned char JfxxHeader[] = {0x4A, 0x46, 0x58, 0x58, 0x00}; 156static const unsigned char JfxxHeader[] = {0x4A, 0x46, 0x58, 0x58, 0x00};
157static const unsigned char App0[] = {0xff, 0xe0}; 157static const unsigned char App0[] = {0xff, 0xe0};
158static const unsigned char App1[] = {0xff, 0xe1}; 158static const unsigned char App1[] = {0xff, 0xe1};
159static const unsigned char MM[] = {0x49, 0x49};
160static const unsigned char II[] = {0x4d, 0x4d};
159typedef enum { 161typedef enum {
160 EXIF_BYTE_ALIGN_II, 162 EXIF_BYTE_ALIGN_II,
161 EXIF_BYTE_ALIGN_MM 163 EXIF_BYTE_ALIGN_MM
162} ExifByteAlign; 164} ExifByteAlign;
163 165
164static int 166static Eina_Bool
165_get_orientation_app0(char *app0_head, size_t remain_length) 167_get_next_app0(unsigned char *map, size_t fsize, size_t *position)
166{ 168{
167 unsigned int length = 0; 169 unsigned short length = 0;
168 unsigned int w = 0, h = 0; 170 unsigned int w = 0, h = 0;
169 unsigned int format = 0; 171 unsigned int format = 0;
170 unsigned int data_size = 0; 172 unsigned int data_size = 0;
171 char *p; 173 unsigned char *app0_head, *p;
174
175 /* header_mark:2, length:2, identifier:5 version:2, unit:1, den=4 thum=2 */
176 if ((*position + 16) >= fsize) return EINA_FALSE;
177 app0_head = map + *position;
172 178
173 /* p is appn's start pointer excluding app0 marker */ 179 /* p is appn's start pointer excluding app0 marker */
174 p = app0_head + 2; 180 p = app0_head + 2;
175 181
176
177 length = ((*p << 8) + *(p + 1)); 182 length = ((*p << 8) + *(p + 1));
178 183
179 /* JFIF segment format */ 184 /* JFIF segment format */
@@ -194,99 +199,135 @@ _get_orientation_app0(char *app0_head, size_t remain_length)
194 } 199 }
195 200
196 data_size = format * w * h; 201 data_size = format * w * h;
197 p += length + data_size;
198 202
199 if (!memcmp(p, App1, sizeof (App1))) 203 if ((*position + 2+ length + data_size) > fsize)
200 return _get_orientation_app1(p, remain_length - (2 + length + data_size)); 204 return EINA_FALSE;
201 else 205
202 return 0; 206 *position = *position + 2 + length + data_size;
207
208 return EINA_TRUE;
203} 209}
204 210
205static int 211/* If app1 data is abnormal, returns EINA_FALSE.
206_get_orientation_app1(char *app1_head, size_t remain_length) 212 If app1 data is normal, returns EINA_TRUE.
213 If app1 data is normal but not orientation data, orientation value is -1.
214 */
215
216static Eina_Bool
217_get_orientation_app1(unsigned char *map, size_t fsize, size_t *position, int *orientation_res)
207{ 218{
208 char *buf; 219 unsigned char *app1_head, *buf;
209 char orientation[2]; 220 unsigned char orientation[2];
210 ExifByteAlign byte_align; 221 ExifByteAlign byte_align;
211 unsigned int num_directory = 0; 222 unsigned int num_directory = 0;
212 unsigned int i, j; 223 unsigned int i, j;
213 int direction; 224 int direction;
225 unsigned int data_size = 0;
214 226
215 /* start of app1 frame */ 227 /* app1 mark:2, data_size:2, exif:6 tiff:8 */
228 if ((*position + 18) >= fsize) return EINA_FALSE;
229 app1_head = map + *position;
216 buf = app1_head; 230 buf = app1_head;
217 231
218 /* 1. check 4~9bype with Exif Header (0x45786966 0000) */ 232 data_size = ((*(buf + 2) << 8) + *(buf + 3));
219 if (memcmp(buf + 4, ExifHeader, sizeof (ExifHeader))) return 0; 233 if ((*position + 2 + data_size) > fsize) return EINA_FALSE;
234
235 if (memcmp(buf + 4, ExifHeader, sizeof (ExifHeader)))
236 {
237 *position = *position + 2 + data_size;
238 *orientation_res = -1;
239 return EINA_TRUE;
240 }
220 241
221 /* 2. get 10&11 byte get info of "II(0x4949)" or "MM(0x4d4d)" */ 242 /* 2. get 10&11 byte get info of "II(0x4949)" or "MM(0x4d4d)" */
222 /* 3. get [18]&[19] get directory entry # */ 243 /* 3. get [18]&[19] get directory entry # */
223 if (!strncmp(buf + 10, "MM", 2)) 244 if (!memcmp(buf + 10, MM, sizeof (MM)))
224 { 245 {
225 byte_align = EXIF_BYTE_ALIGN_MM; 246 byte_align = EXIF_BYTE_ALIGN_MM;
226 num_directory = ((*(buf + 18) << 8) + *(buf + 19)); 247 num_directory = ((*(buf + 18) << 8) + *(buf + 19));
227 orientation[0] = 0x01; 248 orientation[0] = 0x01;
228 orientation[1] = 0x12; 249 orientation[1] = 0x12;
229 } 250 }
230 else if (!strncmp(buf + 10, "II", 2)) 251 else if (!memcmp(buf + 10, II, sizeof (II)))
231 { 252 {
232 byte_align = EXIF_BYTE_ALIGN_II; 253 byte_align = EXIF_BYTE_ALIGN_II;
233 num_directory = ((*(buf + 19) << 8) + *(buf + 18)); 254 num_directory = ((*(buf + 19) << 8) + *(buf + 18));
234 orientation[0] = 0x12; 255 orientation[0] = 0x12;
235 orientation[1] = 0x01; 256 orientation[1] = 0x01;
236 } 257 }
237 else return 0; 258 else return EINA_FALSE;
238 259
239 buf = app1_head + 20; 260 /* check num_directory data */
261 if ((*position + (12 * num_directory + 20)) > fsize) return EINA_FALSE;
240 262
241 if (remain_length < (12 * num_directory + 20)) return 0; 263 buf = app1_head + 20;
242 264
243 j = 0; 265 j = 0;
244 266
245 for (i = 0; i < num_directory; i++ ) 267 for (i = 0; i < num_directory; i++ )
246 { 268 {
247 if (!strncmp(buf + j, orientation, 2)) 269 if (!memcmp(buf + j, orientation, 2))
248 { 270 {
249 /*get orientation tag */ 271 /*get orientation tag */
250 if (byte_align == EXIF_BYTE_ALIGN_MM) 272 if (byte_align == EXIF_BYTE_ALIGN_MM)
251 direction = *(buf+ j + 9); 273 direction = *(buf+ j + 9);
252 else direction = *(buf+ j + 8); 274 else direction = *(buf+ j + 8);
253 switch (direction) 275 switch (direction)
254 { 276 {
255 case 3: 277 case 3:
256 case 4: 278 case 4:
257 return 180; 279 *orientation_res = 180;
280 return EINA_TRUE;
258 case 6: 281 case 6:
259 case 7: 282 case 7:
260 return 90; 283 *orientation_res = 90;
284 return EINA_TRUE;
261 case 5: 285 case 5:
262 case 8: 286 case 8:
263 return 270; 287 *orientation_res = 270;
288 return EINA_TRUE;
264 default: 289 default:
265 return 0; 290 *orientation_res = 0;
291 return EINA_TRUE;
266 } 292 }
267 } 293 }
268 else 294 else
269 j = j + 12; 295 j = j + 12;
270 } 296 }
271 return 0; 297 return EINA_FALSE;
272} 298}
273 299
274static int 300static int
275_get_orientation(void *map, size_t length) 301_get_orientation(void *map, size_t length)
276{ 302{
277 char *buf; 303 unsigned char *buf;
304 size_t position = 0;
305 int orientation = -1;
306 Eina_Bool res = EINA_FALSE;
278 307
279 /* open file and get 22 byte frome file */ 308 /* open file and get 22 byte frome file */
280 if (!map) return 0; 309 if (!map) return 0;
281 /* 1. read 22byte */ 310 /* 1. read 22byte */
282 if (length < 22) return 0; 311 if (length < 22) return 0;
283 buf = (char *)map; 312 buf = (unsigned char *)map;
284 313
314 position = 2;
285 /* 2. check 2,3 bypte with APP0(0xFFE0) or APP1(0xFFE1) */ 315 /* 2. check 2,3 bypte with APP0(0xFFE0) or APP1(0xFFE1) */
286 if (!memcmp(buf + 2, App0, sizeof (App0))) 316 while((length - position) > 0)
287 return _get_orientation_app0(buf + 2, length - 2); 317 {
288 if (!memcmp(buf + 2, App1, sizeof (App1))) 318 if (!memcmp(buf + position, App0, sizeof (App0)))
289 return _get_orientation_app1(buf + 2, length - 2); 319 {
320 res = _get_next_app0(map, length, &position);
321 if (!res) break;
322 }
323 else if (!memcmp(buf + position, App1, sizeof (App1)))
324 {
325 res = _get_orientation_app1(map, length, &position, &orientation);
326 if (!res) break;
327 if (orientation != -1) return orientation;
328 }
329 else break;
330 }
290 return 0; 331 return 0;
291} 332}
292 333