jypark pushed a commit to branch master.
commit 958a430f5e5aab7c232671be7352fa44a1b8e971
Author: Jiyoun Park <[email protected]>
Date: Sat Jun 29 15:00:43 2013 +0900
* Evas: Fix jpeg loader cannot deal with exif information correctly
---
ChangeLog | 4 +
NEWS | 1 +
.../evas/loaders/jpeg/evas_image_load_jpeg.c | 115 ++++++++++++++-------
3 files changed, 83 insertions(+), 37 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 4763b4f..772dff5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-06-28 Jiyoun Park
+
+ * Evas: Fix jpeg loader cannot deal with exif information correctly
+
2013-06-26 Daniel Willmann
* Evas: Fix evas_common_convert_yuv_42* functions to actually return
diff --git a/NEWS b/NEWS
index ebafdf8..873f218 100644
--- a/NEWS
+++ b/NEWS
@@ -341,3 +341,4 @@ Fixes:
* Evas: Fix evas_gl direct rendering to support partial redraw.
* Evas textblock: Fixed issue with textblocks without fonts segfaulting.
* Evas: Fix evas_common_convert_yuv_42* functions to actually return the
converted data.
+ * Evas: Fix jpeg loader cannot deal with exif information correctly
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 96de9c6..3d9999a 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
static void _JPEGFatalErrorHandler(j_common_ptr cinfo);
static void _JPEGErrorHandler(j_common_ptr cinfo);
static void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
-static int _get_orientation_app0(char *app0_head, size_t remain_length);
-static int _get_orientation_app1(char *app1_head, size_t remain_length);
+static Eina_Bool _get_next_app0(unsigned char *map, size_t fsize, size_t
*position);
+static Eina_Bool _get_orientation_app1(unsigned char *map, size_t fsize,
size_t *position, int *orientation);
static int _get_orientation(void *map, size_t length);
#if 0 /* not used at the moment */
@@ -156,24 +156,29 @@ static const unsigned char JfifHeader[] = {0x4A, 0x46,
0x49, 0x46, 0x00};
static const unsigned char JfxxHeader[] = {0x4A, 0x46, 0x58, 0x58, 0x00};
static const unsigned char App0[] = {0xff, 0xe0};
static const unsigned char App1[] = {0xff, 0xe1};
+static const unsigned char MM[] = {0x49, 0x49};
+static const unsigned char II[] = {0x4d, 0x4d};
typedef enum {
EXIF_BYTE_ALIGN_II,
EXIF_BYTE_ALIGN_MM
} ExifByteAlign;
-static int
-_get_orientation_app0(char *app0_head, size_t remain_length)
+static Eina_Bool
+_get_next_app0(unsigned char *map, size_t fsize, size_t *position)
{
- unsigned int length = 0;
+ unsigned short length = 0;
unsigned int w = 0, h = 0;
unsigned int format = 0;
unsigned int data_size = 0;
- char *p;
+ unsigned char *app0_head, *p;
+
+ /* header_mark:2, length:2, identifier:5 version:2, unit:1, den=4 thum=2 */
+ if ((*position + 16) >= fsize) return EINA_FALSE;
+ app0_head = map + *position;
/* p is appn's start pointer excluding app0 marker */
p = app0_head + 2;
-
length = ((*p << 8) + *(p + 1));
/* JFIF segment format */
@@ -194,99 +199,135 @@ _get_orientation_app0(char *app0_head, size_t
remain_length)
}
data_size = format * w * h;
- p += length + data_size;
- if (!memcmp(p, App1, sizeof (App1)))
- return _get_orientation_app1(p, remain_length - (2 + length +
data_size));
- else
- return 0;
+ if ((*position + 2+ length + data_size) > fsize)
+ return EINA_FALSE;
+
+ *position = *position + 2 + length + data_size;
+
+ return EINA_TRUE;
}
-static int
-_get_orientation_app1(char *app1_head, size_t remain_length)
+/* If app1 data is abnormal, returns EINA_FALSE.
+ If app1 data is normal, returns EINA_TRUE.
+ If app1 data is normal but not orientation data, orientation value is -1.
+ */
+
+static Eina_Bool
+_get_orientation_app1(unsigned char *map, size_t fsize, size_t *position, int
*orientation_res)
{
- char *buf;
- char orientation[2];
+ unsigned char *app1_head, *buf;
+ unsigned char orientation[2];
ExifByteAlign byte_align;
unsigned int num_directory = 0;
unsigned int i, j;
int direction;
+ unsigned int data_size = 0;
- /* start of app1 frame */
+ /* app1 mark:2, data_size:2, exif:6 tiff:8 */
+ if ((*position + 18) >= fsize) return EINA_FALSE;
+ app1_head = map + *position;
buf = app1_head;
- /* 1. check 4~9bype with Exif Header (0x45786966 0000) */
- if (memcmp(buf + 4, ExifHeader, sizeof (ExifHeader))) return 0;
+ data_size = ((*(buf + 2) << 8) + *(buf + 3));
+ if ((*position + 2 + data_size) > fsize) return EINA_FALSE;
+
+ if (memcmp(buf + 4, ExifHeader, sizeof (ExifHeader)))
+ {
+ *position = *position + 2 + data_size;
+ *orientation_res = -1;
+ return EINA_TRUE;
+ }
/* 2. get 10&11 byte get info of "II(0x4949)" or "MM(0x4d4d)" */
/* 3. get [18]&[19] get directory entry # */
- if (!strncmp(buf + 10, "MM", 2))
+ if (!memcmp(buf + 10, MM, sizeof (MM)))
{
byte_align = EXIF_BYTE_ALIGN_MM;
num_directory = ((*(buf + 18) << 8) + *(buf + 19));
orientation[0] = 0x01;
orientation[1] = 0x12;
}
- else if (!strncmp(buf + 10, "II", 2))
+ else if (!memcmp(buf + 10, II, sizeof (II)))
{
byte_align = EXIF_BYTE_ALIGN_II;
num_directory = ((*(buf + 19) << 8) + *(buf + 18));
orientation[0] = 0x12;
orientation[1] = 0x01;
}
- else return 0;
+ else return EINA_FALSE;
- buf = app1_head + 20;
+ /* check num_directory data */
+ if ((*position + (12 * num_directory + 20)) > fsize) return EINA_FALSE;
- if (remain_length < (12 * num_directory + 20)) return 0;
+ buf = app1_head + 20;
j = 0;
for (i = 0; i < num_directory; i++ )
{
- if (!strncmp(buf + j, orientation, 2))
+ if (!memcmp(buf + j, orientation, 2))
{
/*get orientation tag */
if (byte_align == EXIF_BYTE_ALIGN_MM)
- direction = *(buf+ j + 9);
+ direction = *(buf+ j + 9);
else direction = *(buf+ j + 8);
switch (direction)
{
case 3:
case 4:
- return 180;
+ *orientation_res = 180;
+ return EINA_TRUE;
case 6:
case 7:
- return 90;
+ *orientation_res = 90;
+ return EINA_TRUE;
case 5:
case 8:
- return 270;
+ *orientation_res = 270;
+ return EINA_TRUE;
default:
- return 0;
+ *orientation_res = 0;
+ return EINA_TRUE;
}
}
else
j = j + 12;
}
- return 0;
+ return EINA_FALSE;
}
static int
_get_orientation(void *map, size_t length)
{
- char *buf;
+ unsigned char *buf;
+ size_t position = 0;
+ int orientation = -1;
+ Eina_Bool res = EINA_FALSE;
/* open file and get 22 byte frome file */
if (!map) return 0;
/* 1. read 22byte */
if (length < 22) return 0;
- buf = (char *)map;
+ buf = (unsigned char *)map;
+ position = 2;
/* 2. check 2,3 bypte with APP0(0xFFE0) or APP1(0xFFE1) */
- if (!memcmp(buf + 2, App0, sizeof (App0)))
- return _get_orientation_app0(buf + 2, length - 2);
- if (!memcmp(buf + 2, App1, sizeof (App1)))
- return _get_orientation_app1(buf + 2, length - 2);
+ while((length - position) > 0)
+ {
+ if (!memcmp(buf + position, App0, sizeof (App0)))
+ {
+ res = _get_next_app0(map, length, &position);
+ if (!res) break;
+ }
+ else if (!memcmp(buf + position, App1, sizeof (App1)))
+ {
+ res = _get_orientation_app1(map, length, &position, &orientation);
+ if (!res) break;
+ if (orientation != -1) return orientation;
+ }
+ else break;
+ }
return 0;
}
--
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev