2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 * The Exif specification defines an Orientation Tag to indicate the orientation of the
21 * camera relative to the captured scene. This can be used by the camera either to
22 * indicate the orientation automatically by an orientation sensor,
23 * or to allow the user to indicate the orientation manually by a menu switch,
24 * without actually transforming the image data itself.
25 * Here is an explanation given by TsuruZoh Tachibanaya in
26 * his description of the Exif file format:
28 * The orientation of the camera relative to the scene, when the image was captured.
29 * The relation of the '0th row' and '0th column' to visual position is shown as below.
31 * Value 0th Row 0th Column
41 * Read this table as follows (thanks to Peter Nielsen for clarifying this - see also below):
42 * Entry #6 in the table says that the 0th row in the stored image is the right side of
43 * the captured scene, and the 0th column in the stored image is the top side of
46 * Here is another description given by Adam M. Costello:
48 * For convenience, here is what the letter F would look like if it were tagged correctly
49 * and displayed by a program that ignores the orientation tag
50 * (thus showing the stored image):
54 * 888888 888888 88 88 8888888888 88 88 8888888888
55 * 88 88 88 88 88 88 88 88 88 88 88 88
56 * 8888 8888 8888 8888 88 8888888888 8888888888 88
61 #include "ivug-debug.h"
62 #include "ivug-exif.h"
65 #define LOG_LVL (DBG_MSG_LVL_HIGH | DBG_MSG_LVL_DEBUG)
68 #define LOG_CAT "IV-EXIF"
70 #define gl_dbgE MSG_ERROR
71 #define gl_dbgW MSG_WARN
73 #define gl_dbg MSG_MED
75 #define GL_CHECK_VAL(expr, val) \
78 MSG_ERROR("[%s] Return value %d", #expr, val );\
87 #include <Elementary.h>
89 #define GL_EXIF_BUF_LEN_MAX 65536L
90 #define GL_EXIF_BUF_TIME_LEN_MAX 20
91 #define GL_EXIF_DEFAULT_YEAR 1900
93 #define GL_EXIF_SOI 0xD8
94 #define GL_EXIF_TAG 0xFF
95 #define GL_EXIF_APP0 0xE0
96 #define GL_EXIF_APP1 0xE1
97 #define GL_EXIF_JFIF_00 0x00
98 #define GL_EXIF_JFIF_01 0x01
99 #define GL_EXIF_JFIF_02 0x02
101 #define GL_EXIF_IFD_DATA_FORMAT_UNSIGNED_BYTE 1
102 #define GL_EXIF_IFD_DATA_FORMAT_ASCII_STRINGS 1
103 #define GL_EXIF_IFD_DATA_FORMAT_UNSIGNED_SHORT 2
104 #define GL_EXIF_IFD_DATA_FORMAT_UNSIGNED_LONG 4
105 #define GL_EXIF_IFD_DATA_FORMAT_UNSIGNED_RATIONAL 8
106 #define GL_EXIF_IFD_DATA_FORMAT_SIGNED_BYTE 1
107 #define GL_EXIF_IFD_DATA_FORMAT_UNDEFINED 1
108 #define GL_EXIF_IFD_DATA_FORMAT_SIGNED_SHORT 2
109 #define GL_EXIF_IFD_DATA_FORMAT_SIGNED_LONG 4
110 #define GL_EXIF_IFD_DATA_FORMAT_SIGNED_RATIONAL 8
111 #define GL_EXIF_IFD_DATA_FORMAT_SIGNED_FLOAT 4
112 #define GL_EXIF_IFD_DATA_FORMAT_DOUBLE_FLOAT 8
114 #define GL_EXI_TMP_JPEG_FILE "/opt/usr/media/.gallery_tmp_write_exif.jpg"
116 /* Write one byte, testing for EOF */
117 static int __gl_exif_write_1_byte(FILE *fd, int c)
119 if (fputc(c, fd) < 0) {
120 gl_dbgE("fputc failed!");
127 /* Read one byte, testing for EOF */
128 static int __gl_exif_read_1_byte(FILE *fd)
132 /* Return next input byte, or EOF if no more */
135 gl_dbgE("Premature EOF in JPEG file!");
142 /* Read 2 bytes, convert to unsigned int */
143 /* All 2-byte quantities in JPEG markers are MSB first */
144 static int __gl_exif_read_2_bytes(FILE *fd, unsigned int *len)
149 /* Return next input byte, or EOF if no more */
152 gl_dbgE("Premature EOF in JPEG file!");
156 /* Return next input byte, or EOF if no more */
159 gl_dbgE("Premature EOF in JPEG file!");
164 *len = (((unsigned int)c1) << 8) + ((unsigned int)c2);
169 /* Add raw exif tag and data */
170 static int __gl_exif_add_header(FILE *fd, unsigned int *orientation)
172 GL_CHECK_VAL(orientation, -1);
173 GL_CHECK_VAL(fd, -1);
176 char *time_buf = NULL;
177 unsigned int offset = 0;
179 /* raw EXIF header data */
180 const unsigned char exif1[] = {
181 GL_EXIF_TAG, GL_EXIF_SOI, GL_EXIF_TAG, GL_EXIF_APP1
183 /* Write File head, check for JPEG SOI + Exif APP1 */
184 for (i = 0; i < 4; i++) {
185 if (__gl_exif_write_1_byte(fd, exif1[i]) < 0)
188 /* SET the marker parameter length count */
189 /* Length includes itself, so must be at least 2
190 Following Exif data length must be at least 6; 30+36 bytes*/
191 const unsigned char exif2[] = { 0x00, 0x42 };
192 for (i = 0; i < 2; i++) {
193 if (__gl_exif_write_1_byte(fd, exif2[i]) < 0)
197 /* Write Exif head -- "Exif" */
198 const unsigned char exif3[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
199 for (i = 0; i < 6; i++) {
200 if (__gl_exif_write_1_byte(fd, exif3[i]) < 0)
204 /* Set byte order and Tag Mark , "II(0x4949)" */
205 const unsigned char exif4[] = { 0x49, 0x49, 0x2A, 0x00 };
206 for (i = 0; i < 4; i++) {
207 if (__gl_exif_write_1_byte(fd, exif4[i]) < 0)
212 /* Set first IFD offset (offset to IFD0) , II-08000000 */
213 const unsigned char exif5[] = { 0x08, 0x00, 0x00, 0x00 };
214 for (i = 0; i < 4; i++) {
215 if (__gl_exif_write_1_byte(fd, exif5[i]) < 0)
220 /* IFD: Image File Directory */
221 /* Set the number of directory entries contained in this IFD, - EEEE ;
222 * 2 entry: orientation, data time */
223 const unsigned char exif6[] = { 0x02, 0x00 };
224 for (i = 0; i < 2; i++) {
225 if (__gl_exif_write_1_byte(fd, exif6[i]) < 0)
230 /* Add Orientation Tag in IFD0; 0x0112 */
231 const unsigned char exif7[] = { 0x12, 0x01 };
232 for (i = 0; i < 2; i++) {
233 if (__gl_exif_write_1_byte(fd, exif7[i]) < 0)
238 gl_dbg("Write: %d", *orientation);
239 const unsigned char exif8[] = { 0x03, 0x00, 0x01, 0x00, 0x00, 0x00 };
240 for (i = 0; i < 6; i++) {
241 if (__gl_exif_write_1_byte(fd, exif8[i]) < 0)
246 /* Set the Orientation value */
247 if (__gl_exif_write_1_byte(fd, (unsigned char)(*orientation)) < 0)
250 const unsigned char exif9[] = { 0x00, 0x00, 0x00 };
251 for (i = 0; i < 3; i++) {
252 if (__gl_exif_write_1_byte(fd, exif9[i]) < 0)
257 /* Add Data Time Tag in IFD0; 0x0132 */
258 const unsigned char exif10[] = { 0x32, 0x01 };
259 for (i = 0; i < 2; i++) {
260 if (__gl_exif_write_1_byte(fd, exif10[i]) < 0)
266 const unsigned char exif11[] = { 0x02, 0x00 };
267 for (i = 0; i < 2; i++) {
268 if (__gl_exif_write_1_byte(fd, exif11[i]) < 0)
273 /* Data lengh, byte count */
274 const unsigned char exif12[] = { 0x14, 0x00, 0x00, 0x00 };
275 for (i = 0; i < 4; i++) {
276 if (__gl_exif_write_1_byte(fd, exif12[i]) < 0)
281 /* 20 bytes larger than 4 bytes,
282 * so next 4 bytes is data offset start from "II"(0x4949)*/
284 gl_dbg("offset: %2X", offset + 8);
285 /* Too add data offset, plus 4 bytes self and plus 4 bytes IFD terminator */
286 if (__gl_exif_write_1_byte(fd, (unsigned char)(offset + 4)) < 0)
289 const unsigned char exif13[] = { 0x00, 0x00, 0x00 };
290 for (i = 0; i < 3; i++) {
291 if (__gl_exif_write_1_byte(fd, exif13[i]) < 0)
295 /*After last directory entry, there is a 4bytes of data('LLLLLLLL' at the chart),
296 * it means an offset to next IFD. If its value is '0x00000000',
297 * it means this is the last IFD and there is no linked IFD */
298 const unsigned char exif14[] = { 0x00, 0x00, 0x00, 0x00 };
299 for (i = 0; i < 4; i++) {
300 if (__gl_exif_write_1_byte(fd, exif14[i]) < 0)
304 /* Date Time of image was last modified.
305 * Data format is "YYYY:MM:DD HH:MM:SS"+0x00, total 20bytes
312 tm = localtime_r(&t, &tms);
314 time_buf = (char *)calloc(1, GL_EXIF_BUF_TIME_LEN_MAX);
315 if (time_buf == NULL) {
316 gl_dbgE("Faild to allocate memory!");
319 snprintf(time_buf, GL_EXIF_BUF_TIME_LEN_MAX,
320 "%04i:%02i:%02i %02i:%02i:%02i",
321 tm->tm_year + GL_EXIF_DEFAULT_YEAR, tm->tm_mon + 1,
322 tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
324 gl_dbg("time_buf: %s", time_buf);
325 if (fwrite(time_buf, 1, GL_EXIF_BUF_TIME_LEN_MAX, fd) != GL_EXIF_BUF_TIME_LEN_MAX) {
326 gl_dbgW("Write size are diff!");
340 /* Add exif to jfif , don't have exif */
341 static int __gl_exif_add_exif_to_jfif(const char *file_path, unsigned int *orientation)
343 GL_CHECK_VAL(orientation, -1);
344 GL_CHECK_VAL(file_path, -1);
345 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
349 if ((fd = fopen(file_path, "rb+")) == NULL) {
350 gl_dbgE("Can't open %s!", file_path);
354 char *tmp_file = GL_EXI_TMP_JPEG_FILE;
356 if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
357 gl_dbgE("Can't open %s!", tmp_file);
361 /* Add raw EXIF header data */
362 if (__gl_exif_add_header(tmp_fd, orientation) < 0)
366 /* Remove start of JPEG image data section, 20 bytes */
367 r_size = fread(tmp, sizeof(char), 20, fd);
369 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
370 /* Write JPEG image data to tmp file after EXIF header */
371 while ((r_size = fread(tmp, 1, sizeof(tmp), fd)) > 0) {
372 gl_dbg("r_size: %ld", r_size);
373 if (fwrite(tmp, 1, r_size, tmp_fd) != r_size)
374 gl_dbgW("Write and read size are diff!");
376 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
380 fd = fopen(file_path, "wb");
382 gl_dbgE("Error creating file %s!", file_path);
386 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
387 /* Write back tmp file after to JPEG image */
388 fseek(tmp_fd, 0, SEEK_SET);
389 while ((r_size = fread(tmp, 1, sizeof(tmp), tmp_fd)) > 0) {
390 gl_dbg("r_size: %ld", r_size);
391 if (fwrite(tmp, 1, r_size, fd) != r_size)
392 gl_dbgW("Write and read size are diff!");
394 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
406 /* Delete tmp file */
407 if (!ecore_file_unlink(tmp_file))
408 gl_dbgE("Delete file failed");
415 /* Add exif to jfif 1.00, to add exif for some cases */
416 static int __gl_exif_rw_jfif_1dot00(char *file_path, unsigned int *orientation)
418 GL_CHECK_VAL(orientation, -1);
419 GL_CHECK_VAL(file_path, -1);
420 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
425 if ((fd = fopen(file_path, "rb+")) == NULL) {
426 gl_dbgE("Can't open %s!", file_path);
430 char *tmp_file = GL_EXI_TMP_JPEG_FILE;
432 if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
433 gl_dbgE("Can't open %s!", tmp_file);
437 /* Add raw EXIF header data */
438 if (__gl_exif_add_header(tmp_fd, orientation) < 0)
442 /* Remove start of JPEG image data section, 20 bytes */
443 r_size = fread(tmp, sizeof(char), 20, fd);
445 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
446 /* Write JPEG image data from first 0xFF to tmp file after EXIF header */
447 while ((r_size = fread(tmp, 1, sizeof(tmp), fd)) > 0) {
448 gl_dbg("r_size: %ld", r_size);
449 if (fwrite(tmp, 1, r_size, tmp_fd) != r_size)
450 gl_dbgW("Write and read size are diff!");
452 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
456 fd = fopen(file_path, "wb");
458 gl_dbgE("Error creating file %s!", file_path);
462 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
463 /* Write back tmp file after to JPEG image */
464 fseek(tmp_fd, 0, SEEK_SET);
465 while ((r_size = fread(tmp, 1, sizeof(tmp), tmp_fd)) > 0) {
466 gl_dbg("r_size: %ld", r_size);
467 if (fwrite(tmp, 1, r_size, fd) != r_size)
468 gl_dbgW("Write and read size are diff!");
470 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
482 /* Delete tmp file */
483 if (!ecore_file_unlink(tmp_file))
484 gl_dbgE("Delete file failed");
490 /* Add exif to jfif 1.01, older version, don't have exif */
491 static int __gl_exif_rw_jfif_1dot01(char *file_path, unsigned int *orientation)
493 GL_CHECK_VAL(orientation, -1);
494 GL_CHECK_VAL(file_path, -1);
495 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
499 if ((fd = fopen(file_path, "rb+")) == NULL) {
500 gl_dbgE("Can't open %s!", file_path);
504 char *tmp_file = GL_EXI_TMP_JPEG_FILE;
506 if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
507 gl_dbgE("Can't open %s!", tmp_file);
511 /* Add raw EXIF header data */
512 if (__gl_exif_add_header(tmp_fd, orientation) < 0)
516 /* Remove start of JPEG image data section, 20 bytes */
517 r_size = fread(tmp, sizeof(char), 20, fd);
519 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
520 /* Write JPEG image data to tmp file after EXIF header */
521 while ((r_size = fread(tmp, 1, sizeof(tmp), fd)) > 0) {
522 gl_dbg("r_size: %ld", r_size);
523 if (fwrite(tmp, 1, r_size, tmp_fd) != r_size)
524 gl_dbgW("Write and read size are diff!");
526 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
530 fd = fopen(file_path, "wb");
532 gl_dbgE("Error creating file %s!", file_path);
536 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
537 /* Write back tmp file after to JPEG image */
538 fseek(tmp_fd, 0, SEEK_SET);
539 while ((r_size = fread(tmp, 1, sizeof(tmp), tmp_fd)) > 0) {
540 gl_dbg("r_size: %ld", r_size);
541 if (fwrite(tmp, 1, r_size, fd) != r_size)
542 gl_dbgW("Write and read size are diff!");
544 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
556 /* Delete tmp file */
557 if (!ecore_file_unlink(tmp_file))
558 gl_dbgE("Delete file failed");
564 /* Add exif to jfif 1.02, to add exif for some cases */
565 static int __gl_exif_rw_jfif_1dot02(char *file_path, unsigned int *orientation)
567 GL_CHECK_VAL(orientation, -1);
568 GL_CHECK_VAL(file_path, -1);
569 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
574 if ((fd = fopen(file_path, "rb+")) == NULL) {
575 gl_dbgE("Can't open %s!", file_path);
579 char *tmp_file = GL_EXI_TMP_JPEG_FILE;
581 if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
582 gl_dbgE("Can't open %s!", tmp_file);
586 /* Add raw EXIF header data */
587 if (__gl_exif_add_header(tmp_fd, orientation) < 0)
591 /* Remove start of JPEG image data section, 20 bytes */
592 r_size = fread(tmp, sizeof(char), 20, fd);
593 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
594 /* Write JPEG image data from first 0xFF to tmp file after EXIF header */
595 while ((r_size = fread(tmp, 1, sizeof(tmp), fd)) > 0) {
596 gl_dbg("r_size: %ld", r_size);
597 if (fwrite(tmp, 1, r_size, tmp_fd) != r_size)
598 gl_dbgW("Write and read size are diff!");
600 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
604 fd = fopen(file_path, "wb");
606 gl_dbgE("Error creating file %s!", file_path);
610 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
611 /* Write back tmp file after to JPEG image */
612 fseek(tmp_fd, 0, SEEK_SET);
613 while ((r_size = fread(tmp, 1, sizeof(tmp), tmp_fd)) > 0) {
614 gl_dbg("r_size: %ld", r_size);
615 if (fwrite(tmp, 1, r_size, fd) != r_size)
616 gl_dbgW("Write and read size are diff!");
618 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
629 /* Delete tmp file */
630 if (!ecore_file_unlink(tmp_file))
631 gl_dbgE("Delete file failed");
638 /* Add orientation tag to jpegs which have exif tag but do not have orientation tag: include jfif and exif*/
639 static int __gl_exif_add_orientation_tag(const char *file_path,
640 unsigned int *orientation){
642 GL_CHECK_VAL(orientation, -1);
643 GL_CHECK_VAL(file_path, -1);
644 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
649 unsigned int length = 0;
650 bool is_motorola = false; /* Flag for byte order */
651 unsigned int offset = 0;
653 const unsigned char ifd_data_format[13] = {
654 /*add 0 to ifd_data_format[0] ,for easy to use*/
656 GL_EXIF_IFD_DATA_FORMAT_UNSIGNED_BYTE,
657 GL_EXIF_IFD_DATA_FORMAT_ASCII_STRINGS,
658 GL_EXIF_IFD_DATA_FORMAT_UNSIGNED_SHORT,
659 GL_EXIF_IFD_DATA_FORMAT_UNSIGNED_LONG,
660 GL_EXIF_IFD_DATA_FORMAT_UNSIGNED_RATIONAL,
661 GL_EXIF_IFD_DATA_FORMAT_SIGNED_BYTE,
662 GL_EXIF_IFD_DATA_FORMAT_UNDEFINED,
663 GL_EXIF_IFD_DATA_FORMAT_SIGNED_SHORT,
664 GL_EXIF_IFD_DATA_FORMAT_SIGNED_LONG,
665 GL_EXIF_IFD_DATA_FORMAT_SIGNED_RATIONAL,
666 GL_EXIF_IFD_DATA_FORMAT_SIGNED_FLOAT,
667 GL_EXIF_IFD_DATA_FORMAT_DOUBLE_FLOAT
671 if ((fd = fopen(file_path, "rb+")) == NULL) {
672 gl_dbgE("Can't open %s!", file_path);
676 char *tmp_file = GL_EXI_TMP_JPEG_FILE;
678 if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
679 gl_dbgE("Can't open %s!", tmp_file);
683 bool b_tag_ff = false;
685 tmp_exif = __gl_exif_read_1_byte(fd);
689 /*copy data from jpeg to tmp_fd (from "FF D8" to " FF E1",because those data we needn't modify)*/
690 if (__gl_exif_write_1_byte(tmp_fd, tmp_exif) < 0)
693 tmp[0] = (unsigned char)tmp_exif;
695 gl_dbg("- %02X", tmp[0]);
698 if (tmp[0] == GL_EXIF_TAG) {
706 if (tmp[0] == GL_EXIF_APP1) {
707 gl_dbgW("Exif in APP1!");
710 gl_dbgW("0x%02X!",tmp[0]);
715 /* Get the marker parameter length count */
716 if (__gl_exif_read_2_bytes(fd, &length) < 0)
718 gl_dbg("length: %d", length);
719 /* Length includes itself, so must be at least 2
720 Following Exif data length must be at least 6 */
722 gl_dbgE("length < 8");
725 /*modify the marker parameter length, orientation tag is 12*/
727 gl_dbgW("modified length: %d", length);
728 tmp[0] =( length >> 8 )& 0xff ;
729 tmp[1] = length & 0xff ;
730 for(i = 0; i < 2; i++){
731 if (__gl_exif_write_1_byte(tmp_fd, tmp[i]) < 0)
735 for (i = 0; i < 6; i++) {
736 tmp_exif = __gl_exif_read_1_byte(fd);
740 tmp[i] = (unsigned char)tmp_exif;
741 gl_dbg("- %02X", tmp[i]);
742 if (__gl_exif_write_1_byte(tmp_fd, tmp[i]) < 0)
745 if (tmp[0] == 0x45 && tmp[1] == 0x78 && tmp[2] == 0x69 && tmp[3] == 0x66 &&
746 tmp[4] == 0x00 && tmp[5] == 0x00) {
747 gl_dbgW("Met Exif!");
749 gl_dbgW("Not met Exif!");
753 for (i = 0; i < 4; i++) {
754 tmp_exif = __gl_exif_read_1_byte(fd);
757 tmp[i] = (unsigned char)tmp_exif;
758 if (__gl_exif_write_1_byte(tmp_fd, tmp[i]) < 0)
762 /* Check byte order and Tag Mark , "II(0x4949)" or "MM(0x4d4d)" */
763 if (tmp[0] == 0x49 && tmp[1] == 0x49 && tmp[2] == 0x2A &&
767 } else if (tmp[0] == 0x4D && tmp[1] == 0x4D && tmp[2] == 0x00 &&
775 for (i = 0; i < 4; i++) {
776 tmp_exif = __gl_exif_read_1_byte(fd);
780 tmp[i] = (unsigned char)tmp_exif;
781 gl_dbg("- %02X", tmp[i]);
782 if (__gl_exif_write_1_byte(tmp_fd, tmp[i]) < 0)
786 /* Get first IFD offset (offset to IFD0) , MM-08000000, II-00000008 */
788 if (tmp[0] != 0 && tmp[1] != 0)
794 if (tmp[3] != 0 && tmp[2] != 0)
800 gl_dbg("offset: %d", offset);
801 /*if offset >8, copy data from there to IFD start position*/
803 for (i = 0; i < (offset - 8); i++) {
804 tmp_exif = __gl_exif_read_1_byte(fd);
808 tmp[i] = (unsigned char)tmp_exif;
809 gl_dbg("- %02X", tmp[i]);
810 if (__gl_exif_write_1_byte(tmp_fd, tmp[i]) < 0)
815 /* IFD: Image File Directory */
816 /* Get the number of directory entries contained in this IFD, - 2 bytes, EE */
817 unsigned int tags_cnt = 0;
818 for (i = 0; i < 2; i++) {
819 tmp_exif = __gl_exif_read_1_byte(fd);
823 tmp[i] = (unsigned char)tmp_exif;
834 gl_dbg("tags_cnt: %d", tags_cnt);
835 /*modify tags num,add orientation tag */
837 gl_dbg("modified tags_cnt: %d", tags_cnt);
839 tmp[0] = (tags_cnt >> 8) & 0xff;
840 tmp[1] = tags_cnt & 0xff;
842 tmp[0] = tags_cnt & 0xff;
843 tmp[1] = (tags_cnt >> 8) & 0xff;
845 for (i = 0; i < 2; i++) {
846 gl_dbg("modified- %02X", tmp[i]);
847 if (__gl_exif_write_1_byte(tmp_fd, tmp[i]) < 0)
851 /* Add Orientation Tag in IFD0 */
852 unsigned int tag_num = 0;
853 unsigned char orientation_tag[12] = { 0, };
854 bool b_found_position = false;
856 unsigned int data_type = 0;
857 unsigned int unit_num = 0;
858 unsigned int data_length = 0;
859 unsigned int offset_value = 0;
860 /*initialize orientation_tag value*/
862 orientation_tag[0] = 0x01;
863 orientation_tag[1] = 0x12;
865 orientation_tag[2] = 0x00;
866 orientation_tag[3] = 0x03;
868 orientation_tag[4] = 0x00;
869 orientation_tag[5] = 0x00;
870 orientation_tag[6] = 0x00;
871 orientation_tag[7] = 0x01;
873 orientation_tag[8] = 0x00;
874 orientation_tag[9] = (unsigned char)(*orientation);
875 orientation_tag[10] = 0x00;
876 orientation_tag[11] = 0x00;
879 orientation_tag[0] = 0x12;
880 orientation_tag[1] = 0x01;
881 orientation_tag[2] = 0x03;
882 orientation_tag[3] = 0x00;
883 orientation_tag[4] = 0x01;
884 orientation_tag[5] = 0x00;
885 orientation_tag[6] = 0x00;
886 orientation_tag[7] = 0x00;
887 orientation_tag[8] = (unsigned char)(*orientation);
888 orientation_tag[9] = 0x00;
889 orientation_tag[10] = 0x00;
890 orientation_tag[11] = 0x00;
892 /*if there is no other tag, then only insert orientation_tag,don't go to the while(1)*/
894 for(j = 0; j < 12 ;j++) {
895 gl_dbg("orientation_tag- %02X", orientation_tag[j]);
896 if (__gl_exif_write_1_byte(tmp_fd, orientation_tag[j]) < 0)
901 if (--tags_cnt == 0) {
905 /* Every directory entry size is 12 */
906 for (i = 0; i < 12; i++) {
907 tmp_exif = __gl_exif_read_1_byte(fd);
911 tmp[i] = (unsigned char)tmp_exif;
923 gl_dbgW("tag num %02X!" , tag_num);
924 /* to find Orientation Tag position */
925 if (tag_num < 0x0112) {
927 } else if (tag_num > 0x0112){
928 if(!b_found_position){
929 for(j = 0; j < 12 ;j++){
930 gl_dbg("orientation_tag- %02X", orientation_tag[j]);
931 if (__gl_exif_write_1_byte(tmp_fd, orientation_tag[j]) < 0)
934 b_found_position = true;
961 gl_dbgW("data_type %02X!" , data_type);
962 gl_dbgW("unit_num %02X!" , unit_num);
963 if((data_type < 1) ||(data_type > 12)){
964 gl_dbgE("Wrong data type!");
968 data_length = ifd_data_format[data_type] * unit_num;
969 gl_dbgW("data_length %02X!" , data_length);
970 /*data_length >4 ,next 4 bytes store the offset, so need to modify the offset*/
973 offset_value = tmp[8];
975 offset_value += tmp[9];
977 offset_value += tmp[10];
979 offset_value += tmp[11];
980 gl_dbgW("offset_value %02X!" , offset_value);
981 /*add orientation offset*/
983 gl_dbgW("changed offset_value %02X!" , offset_value);
984 tmp[8] = (offset_value >> 24) & 0xff;
985 tmp[9] = (offset_value >> 16) & 0xff;
986 tmp[10] = (offset_value >> 8) & 0xff;
987 tmp[11] = offset_value & 0xff;
988 gl_dbg("tmp[8] %02X!" , tmp[8]);
989 gl_dbg("tmp[9] %02X!" , tmp[9]);
990 gl_dbg("tmp[10] %02X!" , tmp[10]);
991 gl_dbg("tmp[11] %02X!" , tmp[11]);
993 offset_value = tmp[11];
995 offset_value += tmp[10];
997 offset_value += tmp[9];
999 offset_value += tmp[8];
1000 gl_dbgW("offset_value %02X!" , offset_value);
1001 /*add orientation offset*/
1003 gl_dbgW("changed offset_value %02X!" , offset_value);
1005 tmp[11] = (offset_value >> 24) & 0xff;
1006 tmp[10] = (offset_value >> 16) & 0xff;
1007 tmp[9] = (offset_value >> 8) & 0xff;
1008 tmp[8] = offset_value & 0xff;
1009 gl_dbg("tmp[8] %02X!" , tmp[8]);
1010 gl_dbg("tmp[9] %02X!" , tmp[9]);
1011 gl_dbg("tmp[10] %02X!" , tmp[10]);
1012 gl_dbg("tmp[11] %02X!" , tmp[11]);
1019 for(i = 0; i < 12 ;i++){
1020 gl_dbg("- %02X", tmp[i]);
1021 if (__gl_exif_write_1_byte(tmp_fd,tmp[i]) < 0)
1022 goto GL_EXIF_FAILED;
1025 memset(tmp, 0x00, 12);
1028 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
1029 /* Write JPEG image data to tmp file after EXIF header */
1030 while ((r_size = fread(tmp, 1, sizeof(tmp), fd)) > 0) {
1031 gl_dbg("r_size: %ld", r_size);
1032 if (fwrite(tmp, 1, r_size, tmp_fd) != r_size)
1033 gl_dbgW("Write and read size are diff!");
1035 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
1039 fd = fopen(file_path, "wb");
1041 gl_dbgE("Error creating file %s!", file_path);
1042 goto GL_EXIF_FAILED;
1045 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
1046 /* Write back tmp file after to JPEG image */
1047 fseek(tmp_fd, 0, SEEK_SET);
1048 while ((r_size = fread(tmp, 1, sizeof(tmp), tmp_fd)) > 0) {
1049 gl_dbg("r_size: %ld", r_size);
1050 if (fwrite(tmp, 1, r_size, fd) != r_size)
1051 gl_dbgW("Write and read size are diff!");
1052 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
1069 /* Delete tmp file */
1070 if (!ecore_file_unlink(tmp_file))
1071 gl_dbgE("Delete file failed");
1077 static int __gl_exif_rw_jfif(FILE *fd, const char *file_path,
1078 unsigned int *orientation, bool b_write)
1080 GL_CHECK_VAL(fd, -1);
1081 GL_CHECK_VAL(file_path, -1);
1082 GL_CHECK_VAL(orientation, -1);
1083 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
1085 unsigned int length = 0;
1087 bool is_motorola = false; /* Flag for byte order */
1088 unsigned int offset = 0;
1090 /*unsigned char version = 0x00; */
1092 if (__gl_exif_read_2_bytes(fd, &length) < 0)
1093 goto GL_EXIF_FAILED;
1094 gl_dbg("length: %d", length);
1096 for (i = 0; i < 5; i++) {
1097 tmp_exif = __gl_exif_read_1_byte(fd);
1099 goto GL_EXIF_FAILED;
1100 tmp[i] = (unsigned char)tmp_exif;
1104 if (tmp[0] != 0x4A || tmp[1] != 0x46 || tmp[2] != 0x49 ||
1105 tmp[3] != 0x46 || tmp[4] != 0x00) {
1106 gl_dbgE("Not met Jfif!");
1107 goto GL_EXIF_FAILED;
1110 for (i = 0; i < 2; i++) {
1111 tmp_exif = __gl_exif_read_1_byte(fd);
1113 goto GL_EXIF_FAILED;
1114 tmp[i] = (unsigned char)tmp_exif;
1117 /* Check JFIF version */
1118 if (tmp[0] == 0x01 && tmp[1] == GL_EXIF_JFIF_00) {
1119 gl_dbg("Jfif 1.00");
1120 } else if (tmp[0] == 0x01 && tmp[1] == GL_EXIF_JFIF_01) {
1121 gl_dbg("Jfif 1.01");
1122 } else if (tmp[0] == 0x01 && tmp[1] == GL_EXIF_JFIF_02) {
1123 gl_dbg("Jfif 1.02");
1125 gl_dbgE("Unknow Jfif version[%d.%d]!", tmp[0], tmp[1]);
1126 goto GL_EXIF_FAILED;
1130 /*version = tmp[1]; */
1133 bool b_tag_ff = false;
1135 tmp_exif = __gl_exif_read_1_byte(fd);
1137 goto GL_EXIF_FAILED;
1139 tmp[0] = (unsigned char)tmp_exif;
1141 gl_dbg("- %02X", tmp[0]);
1144 if (tmp[0] == GL_EXIF_TAG) {
1152 if (tmp[0] == GL_EXIF_APP1) {
1153 gl_dbgW("Exif in APP1!");
1157 gl_dbgW("No Exif in APP1!");
1162 /* Normal orientation = 0degree = 1 */
1166 return __gl_exif_add_exif_to_jfif(file_path, orientation);
1168 if (version == GL_EXIF_JFIF_00) {
1169 return __gl_exif_rw_jfif_1dot00(file_path, orientation);
1170 } else if (version == GL_EXIF_JFIF_01) {
1171 return __gl_exif_rw_jfif_1dot01(file_path, orientation);
1173 return __gl_exif_rw_jfif_1dot02(file_path, orientation);
1180 for (i = 0; i < 6; i++) {
1181 tmp_exif = __gl_exif_read_1_byte(fd);
1183 gl_dbgW("Not met Exif!");
1184 goto GL_EXIF_FAILED;
1187 tmp[i] = (unsigned char)tmp_exif;
1188 gl_dbg("- %02X", tmp[i]);
1190 if (tmp[0] == 0x45 && tmp[1] == 0x78 && tmp[2] == 0x69 && tmp[3] == 0x66 &&
1191 tmp[4] == 0x00 && tmp[5] == 0x00) {
1192 gl_dbgW("Met Exif!");
1195 gl_dbg("Not met Exif!");
1196 fseek(fd, -5, SEEK_CUR);
1201 /* Read Exif body */
1202 for (i = 0; i < 4; i++) {
1203 tmp_exif = __gl_exif_read_1_byte(fd);
1205 goto GL_EXIF_FAILED;
1206 tmp[i] = (unsigned char)tmp_exif;
1209 /* Check byte order and Tag Mark , "II(0x4949)" or "MM(0x4d4d)" */
1210 if (tmp[0] == 0x49 && tmp[1] == 0x49 && tmp[2] == 0x2A &&
1213 is_motorola = false;
1214 } else if (tmp[0] == 0x4D && tmp[1] == 0x4D && tmp[2] == 0x00 &&
1219 goto GL_EXIF_FAILED;
1222 for (i = 0; i < 4; i++) {
1223 tmp_exif = __gl_exif_read_1_byte(fd);
1225 goto GL_EXIF_FAILED;
1227 tmp[i] = (unsigned char)tmp_exif;
1228 gl_dbg("- %02X", tmp[i]);
1231 /* Get first IFD offset (offset to IFD0) , MM-08000000, II-00000008 */
1233 if (tmp[0] != 0 && tmp[1] != 0)
1234 goto GL_EXIF_FAILED;
1239 if (tmp[3] != 0 && tmp[2] != 0)
1240 goto GL_EXIF_FAILED;
1245 gl_dbg("offset: %d", offset);
1247 /* IFD: Image File Directory */
1248 /* Get the number of directory entries contained in this IFD, - 2 bytes, EE */
1249 unsigned int tags_cnt = 0;
1250 for (i = 0; i < 2; i++) {
1251 tmp_exif = __gl_exif_read_1_byte(fd);
1253 goto GL_EXIF_FAILED;
1255 tmp[i] = (unsigned char)tmp_exif;
1266 gl_dbg("tags_cnt: %d", tags_cnt);
1267 if (tags_cnt == 0) {
1268 gl_dbgE("tags_cnt == 0,no found orientation tag!");
1270 gl_dbgW("to add an orientation tag!");
1273 return __gl_exif_add_orientation_tag(file_path, orientation);
1276 /* Normal orientation = 0degree = 1 */
1280 goto GL_EXIF_FAILED;
1283 /* Search for Orientation Tag in IFD0 */
1284 unsigned int tag_num = 0;
1286 /* Every directory entry size is 12 */
1287 for (i = 0; i < 12; i++) {
1288 tmp_exif = __gl_exif_read_1_byte(fd);
1290 goto GL_EXIF_FAILED;
1292 tmp[i] = (unsigned char)tmp_exif;
1294 /* Get Tag number */
1304 /* found Orientation Tag */
1305 if (tag_num == 0x0112) {
1306 gl_dbgW("Found orientation tag!");
1309 if (--tags_cnt == 0) {
1310 gl_dbgW("tags_cnt == 0, no found orientation tag!");
1312 gl_dbgW("to add an orientation tag!");
1315 return __gl_exif_add_orientation_tag(file_path, orientation);
1318 /* Normal orientation = 0degree = 1 */
1322 goto GL_EXIF_FAILED;
1326 /* |TT|ff|NNNN|DDDD| --- TT - 2 bytes, tag NO. ;ff - 2 bytes, data format
1327 NNNN - 4 bytes, entry count; DDDD - 4 bytes Data value */
1329 gl_dbg("Write: %d", *orientation);
1330 /* Set the Orientation value */
1332 tmp[9] = (unsigned char)(*orientation);
1334 tmp[8] = (unsigned char)(*orientation);
1336 /* Move pointer back to the entry start point */
1337 if (fseek(fd, -12, SEEK_CUR) < 0) {
1338 gl_dbgE("fseek failed!");
1339 goto GL_EXIF_FAILED;
1341 fwrite(tmp, 1, 10, fd);
1343 /* Get the Orientation value */
1346 gl_dbgE("tmp[8] != 0");
1347 goto GL_EXIF_FAILED;
1349 *orientation = (unsigned int)tmp[9];
1352 gl_dbgE("tmp[9] != 0");
1353 goto GL_EXIF_FAILED;
1355 *orientation = (unsigned int)tmp[8];
1357 if (*orientation > 8) {
1358 gl_dbgE("*orient > 8");
1359 goto GL_EXIF_FAILED;
1361 gl_dbg("Read: %d", *orientation);
1372 bool _gl_exif_check_img_type(char *file_path)
1374 GL_CHECK_VAL(file_path, -1);
1377 unsigned char exif_data[4] = { 0, };
1381 if ((fd = fopen(file_path, "rb")) == NULL) {
1382 gl_dbgE("Can't open %s!", file_path);
1387 /* Read File head, check for JPEG SOI + Exif APP1 */
1388 for (i = 0; i < 4; i++) {
1389 tmp_exif = __gl_exif_read_1_byte(fd);
1391 goto GL_EXIF_FAILED;
1393 exif_data[i] = (unsigned char)tmp_exif;
1396 if (exif_data[0] == GL_EXIF_TAG && exif_data[1] == GL_EXIF_SOI) {
1397 gl_dbg("JPEG file");
1399 gl_dbgE("Not a JPEG file!");
1400 goto GL_EXIF_FAILED;
1403 if (exif_data[2] == GL_EXIF_TAG && exif_data[3] == GL_EXIF_APP1) {
1404 gl_dbgW("Exif in APP1!");
1406 } else if (exif_data[2] == GL_EXIF_TAG &&
1407 exif_data[3] == GL_EXIF_APP0) {
1408 gl_dbgW("Jfif in APP0!");
1411 gl_dbgE("Not a Exif in APP1 or Jiff in APP2[%d]!", exif_data[3]);
1421 static int __gl_exif_rw_orient(const char *file_path, unsigned int *orient, bool b_write)
1423 GL_CHECK_VAL(file_path, -1);
1424 gl_dbg("b_write: %d", b_write);
1425 unsigned int length = 0;
1427 bool is_motorola = false; /* Flag for byte order */
1428 unsigned int offset = 0;
1429 unsigned int jfif_offset = 0;
1430 unsigned int tags_cnt = 0;
1431 unsigned int tag_num = 0;
1433 unsigned char exif_data[GL_EXIF_BUF_LEN_MAX] = { 0, };
1438 if ((fd = fopen(file_path, "rb+")) == NULL) {
1439 gl_dbgE("Can't open %s!", file_path);
1443 if ((fd = fopen(file_path, "rb")) == NULL) {
1444 gl_dbgE("Can't open %s!", file_path);
1449 /* Read File head, check for JPEG SOI + Exif APP1 */
1450 for (i = 0; i < 4; i++) {
1451 tmp_exif = __gl_exif_read_1_byte(fd);
1453 goto GL_EXIF_FAILED;
1455 exif_data[i] = (unsigned char)tmp_exif;
1458 if (exif_data[0] == GL_EXIF_TAG && exif_data[1] == GL_EXIF_SOI) {
1459 gl_dbg("JPEG file");
1461 gl_dbgE("Not a JPEG file!");
1462 goto GL_EXIF_FAILED;
1465 if (exif_data[2] == GL_EXIF_TAG && exif_data[3] == GL_EXIF_APP1) {
1466 gl_dbgW("Exif in APP1!");
1467 } else if (exif_data[2] == GL_EXIF_TAG &&
1468 exif_data[3] == GL_EXIF_APP0) {
1469 gl_dbgW("Jfif in APP0!");
1470 int ret = __gl_exif_rw_jfif(fd, file_path, orient, b_write);
1473 gl_dbgE("Not a Exif in APP1 or Jiff in APP2[%d]!", exif_data[3]);
1474 goto GL_EXIF_FAILED;
1477 /* Get the marker parameter length count */
1478 if (__gl_exif_read_2_bytes(fd, &length) < 0)
1479 goto GL_EXIF_FAILED;
1480 gl_dbg("length: %d", length);
1481 /* Length includes itself, so must be at least 2
1482 Following Exif data length must be at least 6 */
1484 gl_dbgE("length < 8");
1485 goto GL_EXIF_FAILED;
1489 /* Length of an IFD entry */
1491 gl_dbgE("length < 12");
1492 goto GL_EXIF_FAILED;
1495 /* Read Exif head, check for "Exif" */
1496 for (i = 0; i < 6; i++) {
1497 tmp_exif = __gl_exif_read_1_byte(fd);
1499 goto GL_EXIF_FAILED;
1501 exif_data[i] = (unsigned char)tmp_exif;
1502 gl_dbg("- %02X", exif_data[i]);
1505 if (exif_data[0] != 0x45 || exif_data[1] != 0x78 ||
1506 exif_data[2] != 0x69 || exif_data[3] != 0x66 ||
1507 exif_data[4] != 0x00 || exif_data[5] != 0x00) {
1508 gl_dbgE("Not met Exif!");
1509 goto GL_EXIF_FAILED;
1512 /* Read Exif body */
1513 for (i = 0; i < length; i++) {
1514 tmp_exif = __gl_exif_read_1_byte(fd);
1516 goto GL_EXIF_FAILED;
1517 exif_data[i] = (unsigned char)tmp_exif;
1520 /* Check byte order and Tag Mark , "II(0x4949)" or "MM(0x4d4d)" */
1521 if (exif_data[0] == 0x49 && exif_data[1] == 0x49 &&
1522 exif_data[2] == 0x2A && exif_data[3] == 0x00) {
1524 is_motorola = false;
1525 } else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D &&
1526 exif_data[2] == 0x00 && exif_data[3] == 0x2A) {
1530 goto GL_EXIF_FAILED;
1533 /* Get first IFD offset (offset to IFD0) , MM-00000008, II-08000000 */
1535 if (exif_data[4] != 0 && exif_data[5] != 0)
1536 goto GL_EXIF_FAILED;
1537 offset = exif_data[6];
1539 offset += exif_data[7];
1541 if (exif_data[7] != 0 && exif_data[6] != 0)
1542 goto GL_EXIF_FAILED;
1543 offset = exif_data[5];
1545 offset += exif_data[4];
1547 /* check end of data segment */
1548 if (offset > length - 2) {
1549 gl_dbgE("offset > length - 2");
1550 goto GL_EXIF_FAILED;
1553 /* IFD: Image File Directory */
1554 /* Get the number of directory entries contained in this IFD, - EEEE */
1556 tags_cnt = exif_data[offset];
1558 tags_cnt += exif_data[offset+1];
1560 tags_cnt = exif_data[offset+1];
1562 tags_cnt += exif_data[offset];
1564 if (tags_cnt == 0) {
1565 gl_dbgE("tags_cnt == 0 - 2");
1566 goto GL_EXIF_FAILED;
1570 /* check end of data segment */
1571 if (offset > length - 12) {
1572 gl_dbgE("offset > length - 12");
1573 goto GL_EXIF_FAILED;
1576 /* Search for Orientation Tag in IFD0 */
1578 /* Get Tag number */
1580 tag_num = exif_data[offset];
1582 tag_num += exif_data[offset+1];
1584 tag_num = exif_data[offset+1];
1586 tag_num += exif_data[offset];
1588 /* found Orientation Tag */
1589 if (tag_num == 0x0112) {
1590 gl_dbgW("Found orientation tag!");
1593 if (--tags_cnt == 0) {
1594 gl_dbgW("tags_cnt == 0, no found orientation tag!");
1596 gl_dbgW("to add an orientation tag!");
1599 return __gl_exif_add_orientation_tag(file_path, orient);
1602 /* Normal orientation = 0degree = 1 */
1606 goto GL_EXIF_FAILED;
1609 /* Every directory entry size is 12 */
1614 gl_dbg("Write: %d", *orient);
1615 /* Set the Orientation value */
1617 exif_data[offset+9] = (unsigned char)(*orient);
1619 exif_data[offset+8] = (unsigned char)(*orient);
1621 if (fseek(fd, jfif_offset + (4 + 2 + 6 + 2) + offset, SEEK_SET) < 0) {
1622 gl_dbgE("fseek failed!");
1623 goto GL_EXIF_FAILED;
1625 fwrite(exif_data + 2 + offset, 1, 10, fd);
1627 /* Get the Orientation value */
1629 if (exif_data[offset+8] != 0) {
1630 gl_dbgE("exif_data[offset+8] != 0");
1631 goto GL_EXIF_FAILED;
1633 *orient = (unsigned int)exif_data[offset+9];
1635 if (exif_data[offset+9] != 0) {
1636 gl_dbgE("exif_data[offset+9] != 0");
1637 goto GL_EXIF_FAILED;
1639 *orient = (unsigned int)exif_data[offset+8];
1642 gl_dbgE("*orient > 8");
1643 goto GL_EXIF_FAILED;
1645 gl_dbg("Read: %d", *orient);
1668 #define IVUG_EXIF_ROTATE_0 (1)
1669 #define IVUG_EXIF_ROTATE_90 (6)
1670 #define IVUG_EXIF_ROTATE_180 (3)
1671 #define IVUG_EXIF_ROTATE_270 (8)
1674 int ivug_exif_get_rotate(const char *file, int *degree)
1676 MSG_ASSERT(file != NULL);
1678 unsigned int orientation = 0;
1680 int ret = __gl_exif_rw_orient(file, &orientation, false);
1681 if (-1 != ret && 0 != orientation)
1683 switch (orientation)
1685 case IVUG_EXIF_ROTATE_0:
1688 case IVUG_EXIF_ROTATE_90:
1691 case IVUG_EXIF_ROTATE_180:
1694 case IVUG_EXIF_ROTATE_270:
1699 gl_dbgE("Invalid Orientation : %d", orientation);
1703 gl_dbg("Get Degree: %d' %s", *degree, file);
1708 gl_dbgE("Unknown Degree: %s", file);
1714 int ivug_exif_set_rotate(const char *file, int degree)
1716 MSG_ASSERT(file != NULL);
1718 gl_dbg("Set Degree: %d' %s", degree, file);
1720 unsigned int orientation;
1725 orientation = IVUG_EXIF_ROTATE_0;
1729 orientation = IVUG_EXIF_ROTATE_90;
1733 orientation = IVUG_EXIF_ROTATE_180;
1737 orientation = IVUG_EXIF_ROTATE_270;
1740 orientation = IVUG_EXIF_ROTATE_0;;
1741 gl_dbgE("Invalid Degree : %d", degree);
1745 int ret = __gl_exif_rw_orient(file, &orientation, true);