forked from enlightenment/efl
* Evas: Fix jpeg loader cannot deal with exif information correctly
This commit is contained in:
parent
7927c0f9fa
commit
958a430f5e
|
@ -1,3 +1,7 @@
|
||||||
|
2013-06-28 Jiyoun Park
|
||||||
|
|
||||||
|
* Evas: Fix jpeg loader cannot deal with exif information correctly
|
||||||
|
|
||||||
2013-06-26 Daniel Willmann
|
2013-06-26 Daniel Willmann
|
||||||
|
|
||||||
* Evas: Fix evas_common_convert_yuv_42* functions to actually return
|
* Evas: Fix evas_common_convert_yuv_42* functions to actually return
|
||||||
|
|
1
NEWS
1
NEWS
|
@ -341,3 +341,4 @@ Fixes:
|
||||||
* Evas: Fix evas_gl direct rendering to support partial redraw.
|
* Evas: Fix evas_gl direct rendering to support partial redraw.
|
||||||
* Evas textblock: Fixed issue with textblocks without fonts segfaulting.
|
* 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 evas_common_convert_yuv_42* functions to actually return the converted data.
|
||||||
|
* Evas: Fix jpeg loader cannot deal with exif information correctly
|
||||||
|
|
|
@ -32,8 +32,8 @@ struct _Evas_Loader_Internal
|
||||||
static void _JPEGFatalErrorHandler(j_common_ptr cinfo);
|
static void _JPEGFatalErrorHandler(j_common_ptr cinfo);
|
||||||
static void _JPEGErrorHandler(j_common_ptr cinfo);
|
static void _JPEGErrorHandler(j_common_ptr cinfo);
|
||||||
static void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
|
static void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
|
||||||
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);
|
||||||
static int _get_orientation_app1(char *app1_head, size_t remain_length);
|
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);
|
static int _get_orientation(void *map, size_t length);
|
||||||
|
|
||||||
#if 0 /* not used at the moment */
|
#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 JfxxHeader[] = {0x4A, 0x46, 0x58, 0x58, 0x00};
|
||||||
static const unsigned char App0[] = {0xff, 0xe0};
|
static const unsigned char App0[] = {0xff, 0xe0};
|
||||||
static const unsigned char App1[] = {0xff, 0xe1};
|
static const unsigned char App1[] = {0xff, 0xe1};
|
||||||
|
static const unsigned char MM[] = {0x49, 0x49};
|
||||||
|
static const unsigned char II[] = {0x4d, 0x4d};
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EXIF_BYTE_ALIGN_II,
|
EXIF_BYTE_ALIGN_II,
|
||||||
EXIF_BYTE_ALIGN_MM
|
EXIF_BYTE_ALIGN_MM
|
||||||
} ExifByteAlign;
|
} ExifByteAlign;
|
||||||
|
|
||||||
static int
|
static Eina_Bool
|
||||||
_get_orientation_app0(char *app0_head, size_t remain_length)
|
_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 w = 0, h = 0;
|
||||||
unsigned int format = 0;
|
unsigned int format = 0;
|
||||||
unsigned int data_size = 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 is appn's start pointer excluding app0 marker */
|
||||||
p = app0_head + 2;
|
p = app0_head + 2;
|
||||||
|
|
||||||
|
|
||||||
length = ((*p << 8) + *(p + 1));
|
length = ((*p << 8) + *(p + 1));
|
||||||
|
|
||||||
/* JFIF segment format */
|
/* JFIF segment format */
|
||||||
|
@ -194,99 +199,135 @@ _get_orientation_app0(char *app0_head, size_t remain_length)
|
||||||
}
|
}
|
||||||
|
|
||||||
data_size = format * w * h;
|
data_size = format * w * h;
|
||||||
p += length + data_size;
|
|
||||||
|
|
||||||
if (!memcmp(p, App1, sizeof (App1)))
|
if ((*position + 2+ length + data_size) > fsize)
|
||||||
return _get_orientation_app1(p, remain_length - (2 + length + data_size));
|
return EINA_FALSE;
|
||||||
else
|
|
||||||
return 0;
|
*position = *position + 2 + length + data_size;
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
/* If app1 data is abnormal, returns EINA_FALSE.
|
||||||
_get_orientation_app1(char *app1_head, size_t remain_length)
|
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;
|
unsigned char *app1_head, *buf;
|
||||||
char orientation[2];
|
unsigned char orientation[2];
|
||||||
ExifByteAlign byte_align;
|
ExifByteAlign byte_align;
|
||||||
unsigned int num_directory = 0;
|
unsigned int num_directory = 0;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
int direction;
|
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;
|
buf = app1_head;
|
||||||
|
|
||||||
/* 1. check 4~9bype with Exif Header (0x45786966 0000) */
|
data_size = ((*(buf + 2) << 8) + *(buf + 3));
|
||||||
if (memcmp(buf + 4, ExifHeader, sizeof (ExifHeader))) return 0;
|
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)" */
|
/* 2. get 10&11 byte get info of "II(0x4949)" or "MM(0x4d4d)" */
|
||||||
/* 3. get [18]&[19] get directory entry # */
|
/* 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;
|
byte_align = EXIF_BYTE_ALIGN_MM;
|
||||||
num_directory = ((*(buf + 18) << 8) + *(buf + 19));
|
num_directory = ((*(buf + 18) << 8) + *(buf + 19));
|
||||||
orientation[0] = 0x01;
|
orientation[0] = 0x01;
|
||||||
orientation[1] = 0x12;
|
orientation[1] = 0x12;
|
||||||
}
|
}
|
||||||
else if (!strncmp(buf + 10, "II", 2))
|
else if (!memcmp(buf + 10, II, sizeof (II)))
|
||||||
{
|
{
|
||||||
byte_align = EXIF_BYTE_ALIGN_II;
|
byte_align = EXIF_BYTE_ALIGN_II;
|
||||||
num_directory = ((*(buf + 19) << 8) + *(buf + 18));
|
num_directory = ((*(buf + 19) << 8) + *(buf + 18));
|
||||||
orientation[0] = 0x12;
|
orientation[0] = 0x12;
|
||||||
orientation[1] = 0x01;
|
orientation[1] = 0x01;
|
||||||
}
|
}
|
||||||
else return 0;
|
else return EINA_FALSE;
|
||||||
|
|
||||||
|
/* check num_directory data */
|
||||||
|
if ((*position + (12 * num_directory + 20)) > fsize) return EINA_FALSE;
|
||||||
|
|
||||||
buf = app1_head + 20;
|
buf = app1_head + 20;
|
||||||
|
|
||||||
if (remain_length < (12 * num_directory + 20)) return 0;
|
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
|
|
||||||
for (i = 0; i < num_directory; i++ )
|
for (i = 0; i < num_directory; i++ )
|
||||||
{
|
{
|
||||||
if (!strncmp(buf + j, orientation, 2))
|
if (!memcmp(buf + j, orientation, 2))
|
||||||
{
|
{
|
||||||
/*get orientation tag */
|
/*get orientation tag */
|
||||||
if (byte_align == EXIF_BYTE_ALIGN_MM)
|
if (byte_align == EXIF_BYTE_ALIGN_MM)
|
||||||
direction = *(buf+ j + 9);
|
direction = *(buf+ j + 9);
|
||||||
else direction = *(buf+ j + 8);
|
else direction = *(buf+ j + 8);
|
||||||
switch (direction)
|
switch (direction)
|
||||||
{
|
{
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
return 180;
|
*orientation_res = 180;
|
||||||
|
return EINA_TRUE;
|
||||||
case 6:
|
case 6:
|
||||||
case 7:
|
case 7:
|
||||||
return 90;
|
*orientation_res = 90;
|
||||||
|
return EINA_TRUE;
|
||||||
case 5:
|
case 5:
|
||||||
case 8:
|
case 8:
|
||||||
return 270;
|
*orientation_res = 270;
|
||||||
|
return EINA_TRUE;
|
||||||
default:
|
default:
|
||||||
return 0;
|
*orientation_res = 0;
|
||||||
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
j = j + 12;
|
j = j + 12;
|
||||||
}
|
}
|
||||||
return 0;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_get_orientation(void *map, size_t length)
|
_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 */
|
/* open file and get 22 byte frome file */
|
||||||
if (!map) return 0;
|
if (!map) return 0;
|
||||||
/* 1. read 22byte */
|
/* 1. read 22byte */
|
||||||
if (length < 22) return 0;
|
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) */
|
/* 2. check 2,3 bypte with APP0(0xFFE0) or APP1(0xFFE1) */
|
||||||
if (!memcmp(buf + 2, App0, sizeof (App0)))
|
while((length - position) > 0)
|
||||||
return _get_orientation_app0(buf + 2, length - 2);
|
{
|
||||||
if (!memcmp(buf + 2, App1, sizeof (App1)))
|
if (!memcmp(buf + position, App0, sizeof (App0)))
|
||||||
return _get_orientation_app1(buf + 2, length - 2);
|
{
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue