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://www.tizenopensource.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.
18 * The Exif specification defines an Orientation Tag to indicate the orientation of the
19 * camera relative to the captured scene. This can be used by the camera either to
20 * indicate the orientation automatically by an orientation sensor,
21 * or to allow the user to indicate the orientation manually by a menu switch,
22 * without actually transforming the image data itself.
23 * Here is an explanation given by TsuruZoh Tachibanaya in
24 * his description of the Exif file format:
26 * The orientation of the camera relative to the scene, when the image was captured.
27 * The relation of the '0th row' and '0th column' to visual position is shown as below.
29 * Value 0th Row 0th Column
39 * Read this table as follows (thanks to Peter Nielsen for clarifying this - see also below):
40 * Entry #6 in the table says that the 0th row in the stored image is the right side of
41 * the captured scene, and the 0th column in the stored image is the top side of
44 * Here is another description given by Adam M. Costello:
46 * For convenience, here is what the letter F would look like if it were tagged correctly
47 * and displayed by a program that ignores the orientation tag
48 * (thus showing the stored image):
52 * 888888 888888 88 88 8888888888 88 88 8888888888
53 * 88 88 88 88 88 88 88 88 88 88 88 88
54 * 8888 8888 8888 8888 88 8888888888 8888888888 88
64 #include <Elementary.h>
68 #define GL_EXIF_BUF_LEN_MAX 65536L
69 #define GL_EXIF_BUF_TIME_LEN_MAX 20
70 #define GL_EXIF_DEFAULT_YEAR 1900
72 #define GL_EXIF_SOI 0xD8
73 #define GL_EXIF_TAG 0xFF
74 #define GL_EXIF_APP0 0xE0
75 #define GL_EXIF_APP1 0xE1
76 #define GL_EXIF_JFIF_00 0x00
77 #define GL_EXIF_JFIF_01 0x01
78 #define GL_EXIF_JFIF_02 0x02
80 #define GL_EXI_TMP_JPEG_FILE "/opt/media/.gallery_tmp_write_exif.jpg"
82 /* Write one byte, testing for EOF */
83 static int __gl_exif_write_1_byte(FILE *fd, int c)
85 if (fputc(c, fd) < 0) {
86 gl_dbgE("fputc failed!");
93 /* Read one byte, testing for EOF */
94 static int __gl_exif_read_1_byte(FILE *fd)
98 /* Return next input byte, or EOF if no more */
101 gl_dbgE("Premature EOF in JPEG file!");
108 /* Read 2 bytes, convert to unsigned int */
109 /* All 2-byte quantities in JPEG markers are MSB first */
110 static int __gl_exif_read_2_bytes(FILE *fd, unsigned int *len)
115 /* Return next input byte, or EOF if no more */
118 gl_dbgE("Premature EOF in JPEG file!");
122 /* Return next input byte, or EOF if no more */
125 gl_dbgE("Premature EOF in JPEG file!");
130 *len = (((unsigned int)c1) << 8) + ((unsigned int)c2);
135 /* Add raw exif tag and data */
136 static int __gl_exif_add_header(FILE *fd, unsigned int *orientation)
138 GL_CHECK_VAL(orientation, -1);
139 GL_CHECK_VAL(fd, -1);
142 char *time_buf = NULL;
143 unsigned int offset = 0;
145 /* raw EXIF header data */
146 const unsigned char exif1[] = {
147 GL_EXIF_TAG, GL_EXIF_SOI, GL_EXIF_TAG, GL_EXIF_APP1
149 /* Write File head, check for JPEG SOI + Exif APP1 */
150 for (i = 0; i < 4; i++) {
151 if (__gl_exif_write_1_byte(fd, exif1[i]) < 0)
154 /* SET the marker parameter length count */
155 /* Length includes itself, so must be at least 2
156 Following Exif data length must be at least 6; 30+36 bytes*/
157 const unsigned char exif2[] = { 0x00, 0x42 };
158 for (i = 0; i < 2; i++) {
159 if (__gl_exif_write_1_byte(fd, exif2[i]) < 0)
163 /* Write Exif head -- "Exif" */
164 const unsigned char exif3[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
165 for (i = 0; i < 6; i++) {
166 if (__gl_exif_write_1_byte(fd, exif3[i]) < 0)
170 /* Set byte order and Tag Mark , "II(0x4949)" */
171 const unsigned char exif4[] = { 0x49, 0x49, 0x2A, 0x00 };
172 for (i = 0; i < 4; i++) {
173 if (__gl_exif_write_1_byte(fd, exif4[i]) < 0)
178 /* Set first IFD offset (offset to IFD0) , II-08000000 */
179 const unsigned char exif5[] = { 0x08, 0x00, 0x00, 0x00 };
180 for (i = 0; i < 4; i++) {
181 if (__gl_exif_write_1_byte(fd, exif5[i]) < 0)
186 /* IFD: Image File Directory */
187 /* Set the number of directory entries contained in this IFD, - EEEE ;
188 * 2 entry: orientation, data time */
189 const unsigned char exif6[] = { 0x02, 0x00 };
190 for (i = 0; i < 2; i++) {
191 if (__gl_exif_write_1_byte(fd, exif6[i]) < 0)
196 /* Add Orientation Tag in IFD0; 0x0112 */
197 const unsigned char exif7[] = { 0x12, 0x01 };
198 for (i = 0; i < 2; i++) {
199 if (__gl_exif_write_1_byte(fd, exif7[i]) < 0)
204 gl_dbg("Write: %d", *orientation);
205 const unsigned char exif8[] = { 0x03, 0x00, 0x01, 0x00, 0x00, 0x00 };
206 for (i = 0; i < 6; i++) {
207 if (__gl_exif_write_1_byte(fd, exif8[i]) < 0)
212 /* Set the Orientation value */
213 if (__gl_exif_write_1_byte(fd, (unsigned char)(*orientation)) < 0)
216 const unsigned char exif9[] = { 0x00, 0x00, 0x00 };
217 for (i = 0; i < 3; i++) {
218 if (__gl_exif_write_1_byte(fd, exif9[i]) < 0)
223 /* Add Data Time Tag in IFD0; 0x0132 */
224 const unsigned char exif10[] = { 0x32, 0x01 };
225 for (i = 0; i < 2; i++) {
226 if (__gl_exif_write_1_byte(fd, exif10[i]) < 0)
232 const unsigned char exif11[] = { 0x02, 0x00 };
233 for (i = 0; i < 2; i++) {
234 if (__gl_exif_write_1_byte(fd, exif11[i]) < 0)
239 /* Data lengh, byte count */
240 const unsigned char exif12[] = { 0x14, 0x00, 0x00, 0x00 };
241 for (i = 0; i < 4; i++) {
242 if (__gl_exif_write_1_byte(fd, exif12[i]) < 0)
247 /* 20 bytes larger than 4 bytes,
248 * so next 4 bytes is data offset start from "II"(0x4949)*/
250 gl_dbg("offset: %2X", offset + 8);
251 /* Too add data offset, plus 4 bytes self and plus 4 bytes IFD terminator */
252 if (__gl_exif_write_1_byte(fd, (unsigned char)(offset + 4)) < 0)
255 const unsigned char exif13[] = { 0x00, 0x00, 0x00 };
256 for (i = 0; i < 3; i++) {
257 if (__gl_exif_write_1_byte(fd, exif13[i]) < 0)
261 /*After last directory entry, there is a 4bytes of data('LLLLLLLL' at the chart),
262 * it means an offset to next IFD. If its value is '0x00000000',
263 * it means this is the last IFD and there is no linked IFD */
264 const unsigned char exif14[] = { 0x00, 0x00, 0x00, 0x00 };
265 for (i = 0; i < 4; i++) {
266 if (__gl_exif_write_1_byte(fd, exif14[i]) < 0)
270 /* Date Time of image was last modified.
271 * Data format is "YYYY:MM:DD HH:MM:SS"+0x00, total 20bytes
278 tm = localtime_r(&t, &tms);
280 time_buf = (char *)calloc(1, GL_EXIF_BUF_TIME_LEN_MAX);
281 if (time_buf == NULL) {
282 gl_dbgE("Faild to allocate memory!");
285 snprintf(time_buf, GL_EXIF_BUF_TIME_LEN_MAX,
286 "%04i:%02i:%02i %02i:%02i:%02i",
287 tm->tm_year + GL_EXIF_DEFAULT_YEAR, tm->tm_mon + 1,
288 tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
290 gl_dbg("time_buf: %s", time_buf);
291 if (fwrite(time_buf, 1, GL_EXIF_BUF_TIME_LEN_MAX, fd) != GL_EXIF_BUF_TIME_LEN_MAX) {
292 gl_dbgW("Write size are diff!");
306 /* Add exif to jfif 1.00, to add exif for some cases */
307 static int __gl_exif_rw_jfif_1dot00(char *file_path, unsigned int *orientation)
309 GL_CHECK_VAL(orientation, -1);
310 GL_CHECK_VAL(file_path, -1);
311 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
316 if ((fd = fopen(file_path, "rb+")) == NULL) {
317 gl_dbgE("Can't open %s!", file_path);
321 char *tmp_file = GL_EXI_TMP_JPEG_FILE;
323 if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
324 gl_dbgE("Can't open %s!", tmp_file);
328 /* Remove header of JFIF from 0 to first 0xFF */
329 bool b_tag_ff = false;
331 tmp_exif = __gl_exif_read_1_byte(fd);
335 tmp[0] = (unsigned char)tmp_exif;
337 gl_dbg("- %02X", tmp[0]);
339 if (tmp[0] == GL_EXIF_TAG) {
343 /* Move back 1 byte */
344 fseek(fd, -1, SEEK_CUR);
349 /* Add raw EXIF header data */
350 if (__gl_exif_add_header(tmp_fd, orientation) < 0)
354 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
355 /* Write JPEG image data from first 0xFF to tmp file after EXIF header */
356 while ((r_size = fread(tmp, 1, sizeof(tmp), fd)) > 0) {
357 gl_dbg("r_size: %ld", r_size);
358 if (fwrite(tmp, 1, r_size, tmp_fd) != r_size)
359 gl_dbgW("Write and read size are diff!");
361 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
365 fd = fopen(file_path, "wb");
367 gl_dbgE("Error creating file %s!", file_path);
371 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
372 /* Write back tmp file after to JPEG image */
373 fseek(tmp_fd, 0, SEEK_SET);
374 while ((r_size = fread(tmp, 1, sizeof(tmp), tmp_fd)) > 0) {
375 gl_dbg("r_size: %ld", r_size);
376 if (fwrite(tmp, 1, r_size, fd) != r_size)
377 gl_dbgW("Write and read size are diff!");
379 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
392 /* Delete tmp file */
393 if (!ecore_file_unlink(tmp_file))
394 gl_dbgE("Delete file failed");
401 /* Add exif to jfif 1.01, older version, don't have exif */
402 static int __gl_exif_rw_jfif_1dot01(char *file_path, unsigned int *orientation)
404 GL_CHECK_VAL(orientation, -1);
405 GL_CHECK_VAL(file_path, -1);
406 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
410 if ((fd = fopen(file_path, "rb+")) == NULL) {
411 gl_dbgE("Can't open %s!", file_path);
415 char *tmp_file = GL_EXI_TMP_JPEG_FILE;
417 if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
418 gl_dbgE("Can't open %s!", tmp_file);
422 /* Add raw EXIF header data */
423 if (__gl_exif_add_header(tmp_fd, orientation) < 0)
427 /* Remove start of JPEG image data section, 20 bytes */
428 r_size = fread(tmp, sizeof(char), 20, fd);
430 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
431 /* Write JPEG image data to tmp file after EXIF header */
432 while ((r_size = fread(tmp, 1, sizeof(tmp), fd)) > 0) {
433 gl_dbg("r_size: %ld", r_size);
434 if (fwrite(tmp, 1, r_size, tmp_fd) != r_size)
435 gl_dbgW("Write and read size are diff!");
437 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
441 fd = fopen(file_path, "wb");
443 gl_dbgE("Error creating file %s!", file_path);
447 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
448 /* Write back tmp file after to JPEG image */
449 fseek(tmp_fd, 0, SEEK_SET);
450 while ((r_size = fread(tmp, 1, sizeof(tmp), tmp_fd)) > 0) {
451 gl_dbg("r_size: %ld", r_size);
452 if (fwrite(tmp, 1, r_size, fd) != r_size)
453 gl_dbgW("Write and read size are diff!");
455 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
468 /* Delete tmp file */
469 if (!ecore_file_unlink(tmp_file))
470 gl_dbgE("Delete file failed");
477 /* Add exif to jfif 1.02, to add exif for some cases */
478 static int __gl_exif_rw_jfif_1dot02(char *file_path, unsigned int *orientation)
480 GL_CHECK_VAL(orientation, -1);
481 GL_CHECK_VAL(file_path, -1);
482 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
487 if ((fd = fopen(file_path, "rb+")) == NULL) {
488 gl_dbgE("Can't open %s!", file_path);
492 char *tmp_file = GL_EXI_TMP_JPEG_FILE;
494 if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
495 gl_dbgE("Can't open %s!", tmp_file);
499 /* Copy header of JFIF from 0 to first 0xFF */
500 bool b_tag_ff = false;
502 tmp_exif = __gl_exif_read_1_byte(fd);
506 tmp[0] = (unsigned char)tmp_exif;
508 gl_dbg("- %02X", tmp[0]);
510 if (tmp[0] == GL_EXIF_TAG) {
514 /* Move back 1 byte */
515 fseek(fd, -1, SEEK_CUR);
519 if (__gl_exif_write_1_byte(tmp_fd, tmp[0]) < 0)
524 /* Add raw EXIF header data */
525 if (__gl_exif_add_header(tmp_fd, orientation) < 0)
529 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
530 /* Write JPEG image data from first 0xFF to tmp file after EXIF header */
531 while ((r_size = fread(tmp, 1, sizeof(tmp), fd)) > 0) {
532 gl_dbg("r_size: %ld", r_size);
533 if (fwrite(tmp, 1, r_size, tmp_fd) != r_size)
534 gl_dbgW("Write and read size are diff!");
536 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
540 fd = fopen(file_path, "wb");
542 gl_dbgE("Error creating file %s!", file_path);
546 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
547 /* Write back tmp file after to JPEG image */
548 fseek(tmp_fd, 0, SEEK_SET);
549 while ((r_size = fread(tmp, 1, sizeof(tmp), tmp_fd)) > 0) {
550 gl_dbg("r_size: %ld", r_size);
551 if (fwrite(tmp, 1, r_size, fd) != r_size)
552 gl_dbgW("Write and read size are diff!");
554 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
567 /* Delete tmp file */
568 if (!ecore_file_unlink(tmp_file))
569 gl_dbgE("Delete file failed");
576 static int __gl_exif_rw_jfif(FILE *fd, char *file_path,
577 unsigned int *orientation, bool b_write)
579 GL_CHECK_VAL(fd, -1);
580 GL_CHECK_VAL(file_path, -1);
581 GL_CHECK_VAL(orientation, -1);
582 unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
584 unsigned int length = 0;
586 bool is_motorola = false; /* Flag for byte order */
587 unsigned int offset = 0;
589 unsigned char version = 0x00;
591 if (__gl_exif_read_2_bytes(fd, &length) < 0)
593 gl_dbg("length: %d", length);
595 for (i = 0; i < 5; i++) {
596 tmp_exif = __gl_exif_read_1_byte(fd);
599 tmp[i] = (unsigned char)tmp_exif;
603 if (tmp[0] != 0x4A || tmp[1] != 0x46 || tmp[2] != 0x49 ||
604 tmp[3] != 0x46 || tmp[4] != 0x00) {
605 gl_dbgE("Not met Jfif!");
609 for (i = 0; i < 2; i++) {
610 tmp_exif = __gl_exif_read_1_byte(fd);
613 tmp[i] = (unsigned char)tmp_exif;
616 /* Check JFIF version */
617 if (tmp[0] == 0x01 && tmp[1] == GL_EXIF_JFIF_00) {
619 } else if (tmp[0] == 0x01 && tmp[1] == GL_EXIF_JFIF_01) {
621 } else if (tmp[0] == 0x01 && tmp[1] == GL_EXIF_JFIF_02) {
624 gl_dbgE("Unknow Jfif version[%d.%d]!", tmp[0], tmp[1]);
632 bool b_tag_ff = false;
634 tmp_exif = __gl_exif_read_1_byte(fd);
638 tmp[0] = (unsigned char)tmp_exif;
640 gl_dbg("- %02X", tmp[0]);
643 if (tmp[0] == GL_EXIF_TAG) {
651 if (tmp[0] == GL_EXIF_APP1) {
652 gl_dbgW("Exif in APP1!");
656 gl_dbgW("No Exif in APP1!");
661 /* Normal orientation = 0degree = 1 */
666 if (version == GL_EXIF_JFIF_00) {
667 return __gl_exif_rw_jfif_1dot00(file_path, orientation);
668 } else if (version == GL_EXIF_JFIF_01) {
669 return __gl_exif_rw_jfif_1dot01(file_path, orientation);
671 return __gl_exif_rw_jfif_1dot02(file_path, orientation);
677 tmp_exif = __gl_exif_read_1_byte(fd);
681 tmp[0] = (unsigned char)tmp_exif;
685 for (i = 0; i < 5; i++) {
686 tmp_exif = __gl_exif_read_1_byte(fd);
690 tmp[i] = (unsigned char)tmp_exif;
691 gl_dbg("- %02X", tmp[i]);
693 if (tmp[0] == 0x78 && tmp[1] == 0x69 && tmp[2] == 0x66 &&
694 tmp[3] == 0x00 && tmp[4] == 0x00) {
695 gl_dbgW("Met Exif!");
698 gl_dbgW("Not met Exif!");
704 for (i = 0; i < 4; i++) {
705 tmp_exif = __gl_exif_read_1_byte(fd);
708 tmp[i] = (unsigned char)tmp_exif;
711 /* Check byte order and Tag Mark , "II(0x4949)" or "MM(0x4d4d)" */
712 if (tmp[0] == 0x49 && tmp[1] == 0x49 && tmp[2] == 0x2A &&
716 } else if (tmp[0] == 0x4D && tmp[1] == 0x4D && tmp[2] == 0x00 &&
724 for (i = 0; i < 4; i++) {
725 tmp_exif = __gl_exif_read_1_byte(fd);
729 tmp[i] = (unsigned char)tmp_exif;
730 gl_dbg("- %02X", tmp[i]);
733 /* Get first IFD offset (offset to IFD0) , MM-08000000, II-00000008 */
735 if (tmp[4] != 0 && tmp[5] != 0)
741 if (tmp[7] != 0 && tmp[6] != 0)
747 gl_dbg("offset: %d", offset);
749 /* IFD: Image File Directory */
750 /* Get the number of directory entries contained in this IFD, - 2 bytes, EE */
751 unsigned int tags_cnt = 0;
752 for (i = 0; i < 2; i++) {
753 tmp_exif = __gl_exif_read_1_byte(fd);
757 tmp[i] = (unsigned char)tmp_exif;
768 gl_dbg("tags_cnt: %d", tags_cnt);
770 gl_dbgE("tags_cnt == 0 - 2");
774 /* Search for Orientation Tag in IFD0 */
775 unsigned int tag_num = 0;
777 /* Every directory entry size is 12 */
778 for (i = 0; i < 12; i++) {
779 tmp_exif = __gl_exif_read_1_byte(fd);
783 tmp[i] = (unsigned char)tmp_exif;
795 /* found Orientation Tag */
796 if (tag_num == 0x0112) {
797 gl_dbgW("Found orientation tag!");
800 if (--tags_cnt == 0) {
801 gl_dbgE("tags_cnt == 0");
806 /* |TT|ff|NNNN|DDDD| --- TT - 2 bytes, tag NO. ;ff - 2 bytes, data format
807 NNNN - 4 bytes, entry count; DDDD - 4 bytes Data value */
809 gl_dbg("Write: %d", *orientation);
810 /* Set the Orientation value */
812 tmp[9] = (unsigned char)(*orientation);
814 tmp[8] = (unsigned char)(*orientation);
816 /* Move pointer back to the entry start point */
817 fseek(fd, -12, SEEK_CUR);
818 fwrite(tmp, 1, 10, fd);
820 /* Get the Orientation value */
823 gl_dbgE("tmp[8] != 0");
826 *orientation = (unsigned int)tmp[9];
829 gl_dbgE("tmp[9] != 0");
832 *orientation = (unsigned int)tmp[8];
834 if (*orientation > 8) {
835 gl_dbgE("*orient > 8");
838 gl_dbg("Read: %d", *orientation);
850 static int __gl_exif_rw_orient(char *file_path, unsigned int *orient, bool b_write)
852 GL_CHECK_VAL(file_path, -1);
853 gl_dbg("b_write: %d", b_write);
854 unsigned int length = 0;
856 bool is_motorola = false; /* Flag for byte order */
857 unsigned int offset = 0;
858 unsigned int jfif_offset = 0;
859 unsigned int tags_cnt = 0;
860 unsigned int tag_num = 0;
862 unsigned char exif_data[GL_EXIF_BUF_LEN_MAX] = { 0, };
867 if ((fd = fopen(file_path, "rb+")) == NULL) {
868 gl_dbgE("Can't open %s!", file_path);
872 if ((fd = fopen(file_path, "rb")) == NULL) {
873 gl_dbgE("Can't open %s!", file_path);
878 /* Read File head, check for JPEG SOI + Exif APP1 */
879 for (i = 0; i < 4; i++) {
880 tmp_exif = __gl_exif_read_1_byte(fd);
884 exif_data[i] = (unsigned char)tmp_exif;
887 if (exif_data[0] == GL_EXIF_TAG && exif_data[1] == GL_EXIF_SOI) {
890 gl_dbgE("Not a JPEG file!");
894 if (exif_data[2] == GL_EXIF_TAG && exif_data[3] == GL_EXIF_APP1) {
895 gl_dbgW("Exif in APP1!");
896 } else if (exif_data[2] == GL_EXIF_TAG &&
897 exif_data[3] == GL_EXIF_APP0) {
898 gl_dbgW("Jfif in APP0!");
899 int ret = __gl_exif_rw_jfif(fd, file_path, orient, b_write);
902 gl_dbgE("Not a Exif in APP1 or Jiff in APP2[%d]!", exif_data[3]);
906 /* Get the marker parameter length count */
907 if (__gl_exif_read_2_bytes(fd, &length) < 0)
909 gl_dbg("length: %d", length);
910 /* Length includes itself, so must be at least 2
911 Following Exif data length must be at least 6 */
913 gl_dbgE("length < 8");
918 /* Length of an IFD entry */
920 gl_dbgE("length < 12");
924 /* Read Exif head, check for "Exif" */
925 for (i = 0; i < 6; i++) {
926 tmp_exif = __gl_exif_read_1_byte(fd);
930 exif_data[i] = (unsigned char)tmp_exif;
931 gl_dbg("- %02X", exif_data[i]);
934 if (exif_data[0] != 0x45 || exif_data[1] != 0x78 ||
935 exif_data[2] != 0x69 || exif_data[3] != 0x66 ||
936 exif_data[4] != 0x00 || exif_data[5] != 0x00) {
937 gl_dbgE("Not met Exif!");
942 for (i = 0; i < length; i++) {
943 tmp_exif = __gl_exif_read_1_byte(fd);
946 exif_data[i] = (unsigned char)tmp_exif;
949 /* Check byte order and Tag Mark , "II(0x4949)" or "MM(0x4d4d)" */
950 if (exif_data[0] == 0x49 && exif_data[1] == 0x49 &&
951 exif_data[2] == 0x2A && exif_data[3] == 0x00) {
954 } else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D &&
955 exif_data[2] == 0x00 && exif_data[3] == 0x2A) {
962 /* Get first IFD offset (offset to IFD0) , MM-00000008, II-08000000 */
964 if (exif_data[4] != 0 && exif_data[5] != 0)
966 offset = exif_data[6];
968 offset += exif_data[7];
970 if (exif_data[7] != 0 && exif_data[6] != 0)
972 offset = exif_data[5];
974 offset += exif_data[4];
976 /* check end of data segment */
977 if (offset > length - 2) {
978 gl_dbgE("offset > length - 2");
981 /* IFD: Image File Directory */
982 /* Get the number of directory entries contained in this IFD, - EEEE */
984 tags_cnt = exif_data[offset];
986 tags_cnt += exif_data[offset+1];
988 tags_cnt = exif_data[offset+1];
990 tags_cnt += exif_data[offset];
993 gl_dbgE("tags_cnt == 0 - 2");
998 /* check end of data segment */
999 if (offset > length - 12) {
1000 gl_dbgE("offset > length - 12");
1001 goto GL_EXIF_FAILED;
1004 /* Search for Orientation Tag in IFD0 */
1006 /* Get Tag number */
1008 tag_num = exif_data[offset];
1010 tag_num += exif_data[offset+1];
1012 tag_num = exif_data[offset+1];
1014 tag_num += exif_data[offset];
1016 /* found Orientation Tag */
1017 if (tag_num == 0x0112) {
1018 gl_dbgW("Found orientation tag!");
1021 if (--tags_cnt == 0) {
1022 gl_dbgE("tags_cnt == 0");
1023 goto GL_EXIF_FAILED;
1025 /* Every directory entry size is 12 */
1030 gl_dbg("Write: %d", *orient);
1031 /* Set the Orientation value */
1033 exif_data[offset+9] = (unsigned char)(*orient);
1035 exif_data[offset+8] = (unsigned char)(*orient);
1037 fseek(fd, jfif_offset + (4 + 2 + 6 + 2) + offset, SEEK_SET);
1038 fwrite(exif_data + 2 + offset, 1, 10, fd);
1040 /* Get the Orientation value */
1042 if (exif_data[offset+8] != 0) {
1043 gl_dbgE("exif_data[offset+8] != 0");
1044 goto GL_EXIF_FAILED;
1046 *orient = (unsigned int)exif_data[offset+9];
1048 if (exif_data[offset+9] != 0) {
1049 gl_dbgE("exif_data[offset+9] != 0");
1050 goto GL_EXIF_FAILED;
1052 *orient = (unsigned int)exif_data[offset+8];
1055 gl_dbgE("*orient > 8");
1056 goto GL_EXIF_FAILED;
1058 gl_dbg("Read: %d", *orient);
1070 int _gl_exif_get_orientation(char *file_path, unsigned int *orientation)
1072 GL_CHECK_VAL(orientation, -1);
1073 GL_CHECK_VAL(file_path, -1);
1074 gl_dbg("file_path: %s", file_path);
1076 return __gl_exif_rw_orient(file_path, orientation, false);
1079 int _gl_exif_set_orientation(char *file_path, unsigned int orientation)
1081 GL_CHECK_VAL(file_path, -1);
1082 gl_dbg("file_path: %s", file_path);
1084 return __gl_exif_rw_orient(file_path, &orientation, true);
1087 int _gl_exif_get_rotated_orientation(unsigned int orientation, bool b_left)
1089 int rotated_orientataion;
1090 gl_dbg("b_left: %d", b_left);
1092 switch (orientation){
1093 case GL_ORIENTATION_ROT_0:
1094 /* true: 0 -> 270, false: 0 -> 90 */
1096 rotated_orientataion = GL_ORIENTATION_ROT_270;
1098 rotated_orientataion = GL_ORIENTATION_ROT_90;
1100 case GL_ORIENTATION_ROT_90:
1101 /* true: 90 -> 0, false: 90 -> 180 */
1103 rotated_orientataion = GL_ORIENTATION_ROT_0;
1105 rotated_orientataion = GL_ORIENTATION_ROT_180;
1107 case GL_ORIENTATION_ROT_180:
1108 /* true: 180 -> 90, false: 180 -> 270 */
1110 rotated_orientataion = GL_ORIENTATION_ROT_90;
1112 rotated_orientataion = GL_ORIENTATION_ROT_270;
1114 case GL_ORIENTATION_ROT_270:
1115 /* true: 270 -> 180, false: 270 -> 0 */
1117 rotated_orientataion = GL_ORIENTATION_ROT_180;
1119 rotated_orientataion = GL_ORIENTATION_ROT_0;
1122 gl_dbgE("Wrong oriectation: %d!", orientation);
1123 rotated_orientataion = GL_ORIENTATION_ROT_ERR;
1127 gl_dbg("New orientation: %d", rotated_orientataion);
1128 return rotated_orientataion;