initial upload for tizen 2.0 beta
[apps/home/gallery.git] / src / util / gl-exif.c
1 /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   *
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
7   *
8   *     http://www.tizenopensource.org/license
9   *
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.
15   */
16
17 /**
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:
25  *
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.
28  *
29  * Value         0th Row                0th Column
30  *   1    top             left side
31  *   2    top             right side
32  *   3    bottom                  right side
33  *   4    bottom                  left side
34  *   5    left side          top
35  *   6    right side        top
36  *   7    right side        bottom
37  *   8    left side          bottom
38  *
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
42  * the captured scene.
43  *
44  * Here is another description given by Adam M. Costello:
45  *
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):
49  *
50  *       1             2         3      4            5                 6                   7                  8
51  *
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
55  *  88               88        88    88
56  *  88               88  888888   888888
57 */
58
59 #ifdef _USE_ROTATE_BG
60
61 #include <stdlib.h>
62 #include <string.h>
63 #include <time.h>
64 #include <Elementary.h>
65 #include "gl-exif.h"
66 #include "gl-debug.h"
67
68 #define GL_EXIF_BUF_LEN_MAX 65536L
69 #define GL_EXIF_BUF_TIME_LEN_MAX 20
70 #define GL_EXIF_DEFAULT_YEAR 1900
71
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
79
80 #define GL_EXI_TMP_JPEG_FILE "/opt/media/.gallery_tmp_write_exif.jpg"
81
82 /* Write one byte, testing for EOF */
83 static int __gl_exif_write_1_byte(FILE *fd, int c)
84 {
85         if (fputc(c, fd) < 0) {
86                 gl_dbgE("fputc failed!");
87                 return -1;
88         }
89
90         return 0;
91 }
92
93 /* Read one byte, testing for EOF */
94 static int __gl_exif_read_1_byte(FILE *fd)
95 {
96         int c = 0;
97
98         /* Return next input byte, or EOF if no more */
99         c = getc(fd);
100         if (c == EOF) {
101                 gl_dbgE("Premature EOF in JPEG file!");
102                 return -1;
103         }
104
105         return c;
106 }
107
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)
111 {
112         int c1 = 0;
113         int c2 = 0;
114
115         /* Return next input byte, or EOF if no more */
116         c1 = getc(fd);
117         if (c1 == EOF) {
118                 gl_dbgE("Premature EOF in JPEG file!");
119                 return -1;
120         }
121
122         /* Return next input byte, or EOF if no more */
123         c2 = getc(fd);
124         if (c2 == EOF) {
125                 gl_dbgE("Premature EOF in JPEG file!");
126                 return -1;
127         }
128
129         if (len)
130                 *len = (((unsigned int)c1) << 8) + ((unsigned int)c2);
131
132         return 0;
133 }
134
135 /* Add raw exif tag and data */
136 static int __gl_exif_add_header(FILE *fd, unsigned int *orientation)
137 {
138         GL_CHECK_VAL(orientation, -1);
139         GL_CHECK_VAL(fd, -1);
140         int i = 0;
141         int ret = -1;
142         char *time_buf = NULL;
143         unsigned int offset = 0;
144
145         /* raw EXIF header data */
146         const unsigned char exif1[] = {
147                 GL_EXIF_TAG, GL_EXIF_SOI, GL_EXIF_TAG, GL_EXIF_APP1
148         };
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)
152                         goto GL_EXIF_FAILED;
153         }
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)
160                         goto GL_EXIF_FAILED;
161         }
162
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)
167                         goto GL_EXIF_FAILED;
168         }
169
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)
174                         goto GL_EXIF_FAILED;
175         }
176         offset += 4;
177
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)
182                         goto GL_EXIF_FAILED;
183         }
184         offset += 4;
185
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)
192                         goto GL_EXIF_FAILED;
193         }
194         offset += 2;
195
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)
200                         goto GL_EXIF_FAILED;
201         }
202         offset += 2;
203
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)
208                         goto GL_EXIF_FAILED;
209         }
210         offset += 6;
211
212         /* Set the Orientation value */
213         if (__gl_exif_write_1_byte(fd, (unsigned char)(*orientation)) < 0)
214                 goto GL_EXIF_FAILED;
215
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)
219                         goto GL_EXIF_FAILED;
220         }
221         offset += 4;
222
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)
227                         goto GL_EXIF_FAILED;
228         }
229         offset += 2;
230
231         /* Type: strings */
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)
235                         goto GL_EXIF_FAILED;
236         }
237         offset += 2;
238
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)
243                         goto GL_EXIF_FAILED;
244         }
245         offset += 8;
246
247         /* 20 bytes larger than 4 bytes,
248           * so next 4 bytes is data offset start from "II"(0x4949)*/
249
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)
253                 goto GL_EXIF_FAILED;
254
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)
258                         goto GL_EXIF_FAILED;
259         }
260
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)
267                         goto GL_EXIF_FAILED;
268         }
269
270         /* Date Time of image was last modified.
271           * Data format is "YYYY:MM:DD HH:MM:SS"+0x00, total 20bytes
272           */
273         time_t t;
274         struct tm tms;
275         struct tm *tm;
276
277         t = time (NULL);
278         tm = localtime_r(&t, &tms);
279
280         time_buf = (char *)calloc(1, GL_EXIF_BUF_TIME_LEN_MAX);
281         if (time_buf == NULL) {
282                 gl_dbgE("Faild to allocate memory!");
283                 goto GL_EXIF_FAILED;
284         }
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);
289
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!");
293                 goto GL_EXIF_FAILED;
294         }
295
296         ret = 0;
297
298  GL_EXIF_FAILED:
299
300         gl_dbg("All done");
301         if (time_buf)
302                 free(time_buf);
303         return ret;
304 }
305
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)
308 {
309         GL_CHECK_VAL(orientation, -1);
310         GL_CHECK_VAL(file_path, -1);
311         unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
312         FILE *fd = NULL;
313         int ret = -1;
314         int tmp_exif = -1;
315
316         if ((fd = fopen(file_path, "rb+")) == NULL) {
317                 gl_dbgE("Can't open %s!", file_path);
318                 return -1;
319         }
320
321         char *tmp_file = GL_EXI_TMP_JPEG_FILE;
322         FILE *tmp_fd = NULL;
323         if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
324                 gl_dbgE("Can't open %s!", tmp_file);
325                 goto GL_EXIF_FAILED;
326         }
327
328         /* Remove header of JFIF from 0 to first 0xFF */
329         bool b_tag_ff = false;
330         while(1) {
331                 tmp_exif = __gl_exif_read_1_byte(fd);
332                 if (tmp_exif < 0)
333                         goto GL_EXIF_FAILED;
334
335                 tmp[0] = (unsigned char)tmp_exif;
336
337                 gl_dbg("- %02X", tmp[0]);
338                 if (!b_tag_ff) {
339                         if (tmp[0] == GL_EXIF_TAG) {
340                                 gl_dbgW("0xFF!");
341                                 b_tag_ff = true;
342                         }
343                         /* Move back 1 byte */
344                         fseek(fd, -1, SEEK_CUR);
345                         break;
346                 }
347         }
348
349         /* Add raw EXIF header data */
350         if (__gl_exif_add_header(tmp_fd, orientation) < 0)
351                 goto GL_EXIF_FAILED;
352
353         size_t r_size = 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!");
360
361                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
362         }
363
364         fclose(fd);
365         fd = fopen(file_path, "wb");
366         if (!fd) {
367                 gl_dbgE("Error creating file %s!", file_path);
368                 goto GL_EXIF_FAILED;
369         }
370
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!");
378
379                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
380         }
381
382         ret = 0;
383
384  GL_EXIF_FAILED:
385
386         if (fd)
387                 fclose(fd);
388         if (tmp_fd)
389                 fclose(tmp_fd);
390
391         if (tmp_file) {
392                 /* Delete tmp file */
393                 if (!ecore_file_unlink(tmp_file))
394                         gl_dbgE("Delete file failed");
395         }
396
397         gl_dbg("All done");
398         return ret;
399 }
400
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)
403 {
404         GL_CHECK_VAL(orientation, -1);
405         GL_CHECK_VAL(file_path, -1);
406         unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
407         FILE *fd = NULL;
408         int ret = -1;
409
410         if ((fd = fopen(file_path, "rb+")) == NULL) {
411                 gl_dbgE("Can't open %s!", file_path);
412                 return -1;
413         }
414
415         char *tmp_file = GL_EXI_TMP_JPEG_FILE;
416         FILE *tmp_fd = NULL;
417         if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
418                 gl_dbgE("Can't open %s!", tmp_file);
419                 goto GL_EXIF_FAILED;
420         }
421
422         /* Add raw EXIF header data */
423         if (__gl_exif_add_header(tmp_fd, orientation) < 0)
424                 goto GL_EXIF_FAILED;
425
426         size_t r_size = 0;
427         /* Remove start of JPEG image data section, 20 bytes */
428         r_size = fread(tmp, sizeof(char), 20, fd);
429
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!");
436
437                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
438         }
439
440         fclose(fd);
441         fd = fopen(file_path, "wb");
442         if (!fd) {
443                 gl_dbgE("Error creating file %s!", file_path);
444                 goto GL_EXIF_FAILED;
445         }
446
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!");
454
455                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
456         }
457
458         ret = 0;
459
460  GL_EXIF_FAILED:
461
462         if (fd)
463                 fclose(fd);
464         if (tmp_fd)
465                 fclose(tmp_fd);
466
467         if (tmp_file) {
468                 /* Delete tmp file */
469                 if (!ecore_file_unlink(tmp_file))
470                         gl_dbgE("Delete file failed");
471         }
472
473         gl_dbg("All done");
474         return ret;
475 }
476
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)
479 {
480         GL_CHECK_VAL(orientation, -1);
481         GL_CHECK_VAL(file_path, -1);
482         unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
483         FILE *fd = NULL;
484         int ret = -1;
485         int tmp_exif = -1;
486
487         if ((fd = fopen(file_path, "rb+")) == NULL) {
488                 gl_dbgE("Can't open %s!", file_path);
489                 return -1;
490         }
491
492         char *tmp_file = GL_EXI_TMP_JPEG_FILE;
493         FILE *tmp_fd = NULL;
494         if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
495                 gl_dbgE("Can't open %s!", tmp_file);
496                 goto GL_EXIF_FAILED;
497         }
498
499         /* Copy header of JFIF from 0 to first 0xFF */
500         bool b_tag_ff = false;
501         while(1) {
502                 tmp_exif = __gl_exif_read_1_byte(fd);
503                 if (tmp_exif < 0)
504                         goto GL_EXIF_FAILED;
505
506                 tmp[0] = (unsigned char)tmp_exif;
507
508                 gl_dbg("- %02X", tmp[0]);
509                 if (!b_tag_ff) {
510                         if (tmp[0] == GL_EXIF_TAG) {
511                                 gl_dbgW("0xFF!");
512                                 b_tag_ff = true;
513                         }
514                         /* Move back 1 byte */
515                         fseek(fd, -1, SEEK_CUR);
516                         break;
517                 }
518
519                 if (__gl_exif_write_1_byte(tmp_fd, tmp[0]) < 0)
520                         goto GL_EXIF_FAILED;
521
522         }
523
524         /* Add raw EXIF header data */
525         if (__gl_exif_add_header(tmp_fd, orientation) < 0)
526                 goto GL_EXIF_FAILED;
527
528         size_t r_size = 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!");
535
536                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
537         }
538
539         fclose(fd);
540         fd = fopen(file_path, "wb");
541         if (!fd) {
542                 gl_dbgE("Error creating file %s!", file_path);
543                 goto GL_EXIF_FAILED;
544         }
545
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!");
553
554                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
555         }
556
557         ret = 0;
558
559  GL_EXIF_FAILED:
560
561         if (fd)
562                 fclose(fd);
563         if (tmp_fd)
564                 fclose(tmp_fd);
565
566         if (tmp_file) {
567                 /* Delete tmp file */
568                 if (!ecore_file_unlink(tmp_file))
569                         gl_dbgE("Delete file failed");
570         }
571
572         gl_dbg("All done");
573         return ret;
574 }
575
576 static int __gl_exif_rw_jfif(FILE *fd, char *file_path,
577                              unsigned int *orientation, bool b_write)
578 {
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, };
583         int i = 0;
584         unsigned int length = 0;
585         int tmp_exif = -1;
586         bool is_motorola = false; /* Flag for byte order */
587         unsigned int offset = 0;
588         int ret = -1;
589         unsigned char version = 0x00;
590
591         if (__gl_exif_read_2_bytes(fd, &length) < 0)
592                 goto GL_EXIF_FAILED;
593         gl_dbg("length: %d", length);
594
595         for (i = 0; i < 5; i++) {
596                 tmp_exif = __gl_exif_read_1_byte(fd);
597                 if (tmp_exif < 0)
598                         goto GL_EXIF_FAILED;
599                 tmp[i] = (unsigned char)tmp_exif;
600         }
601
602         /* JFIF0 */
603         if (tmp[0] != 0x4A || tmp[1] != 0x46 || tmp[2] != 0x49 ||
604             tmp[3] != 0x46 || tmp[4] != 0x00) {
605                 gl_dbgE("Not met Jfif!");
606                 goto GL_EXIF_FAILED;
607         }
608
609         for (i = 0; i < 2; i++) {
610                 tmp_exif = __gl_exif_read_1_byte(fd);
611                 if (tmp_exif < 0)
612                         goto GL_EXIF_FAILED;
613                 tmp[i] = (unsigned char)tmp_exif;
614         }
615
616         /* Check JFIF version */
617         if (tmp[0] == 0x01 && tmp[1] == GL_EXIF_JFIF_00) {
618                 gl_dbg("Jfif 1.00");
619         } else if (tmp[0] == 0x01 && tmp[1] == GL_EXIF_JFIF_01) {
620                 gl_dbg("Jfif 1.01");
621         } else if (tmp[0] == 0x01 && tmp[1] == GL_EXIF_JFIF_02) {
622                 gl_dbg("Jfif 1.02");
623         } else {
624                 gl_dbgE("Unknow Jfif version[%d.%d]!", tmp[0], tmp[1]);
625                 goto GL_EXIF_FAILED;
626         }
627
628         /* Save version */
629         version = tmp[1];
630
631         /* Find APP1 */
632         bool b_tag_ff = false;
633         while(1) {
634                 tmp_exif = __gl_exif_read_1_byte(fd);
635                 if (tmp_exif < 0)
636                         goto GL_EXIF_FAILED;
637
638                 tmp[0] = (unsigned char)tmp_exif;
639
640                 gl_dbg("- %02X", tmp[0]);
641                 if (!b_tag_ff) {
642                         /* Get first tag */
643                         if (tmp[0] == GL_EXIF_TAG) {
644                                 gl_dbgW("0xFF!");
645                                 b_tag_ff = true;
646                         }
647                         continue;
648                 }
649
650                 /* Get APP1 */
651                 if (tmp[0] == GL_EXIF_APP1) {
652                         gl_dbgW("Exif in APP1!");
653                         break;
654                 }
655
656                 gl_dbgW("No Exif in APP1!");
657
658                 /* Close file */
659                 fclose(fd);
660                 if (!b_write) {
661                         /* Normal orientation = 0degree = 1 */
662                         *orientation = 1;
663                         return 0;
664                 }
665
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);
670                 } else {
671                         return __gl_exif_rw_jfif_1dot02(file_path, orientation);
672                 }
673         }
674
675         /* Find Exif */
676         while(1) {
677                 tmp_exif = __gl_exif_read_1_byte(fd);
678                 if (tmp_exif < 0)
679                         goto GL_EXIF_FAILED;
680
681                 tmp[0] = (unsigned char)tmp_exif;
682                 if (tmp[0] != 0x45)
683                         continue;
684
685                 for (i = 0; i < 5; i++) {
686                         tmp_exif = __gl_exif_read_1_byte(fd);
687                         if (tmp_exif < 0)
688                                 goto GL_EXIF_FAILED;
689
690                         tmp[i] = (unsigned char)tmp_exif;
691                         gl_dbg("- %02X", tmp[i]);
692                 }
693                 if (tmp[0] == 0x78 && tmp[1] == 0x69 && tmp[2] == 0x66 &&
694                     tmp[3] == 0x00 && tmp[4] == 0x00) {
695                         gl_dbgW("Met Exif!");
696                         break;
697                 } else {
698                         gl_dbgW("Not met Exif!");
699                         goto GL_EXIF_FAILED;
700                 }
701         }
702
703         /* Read Exif body */
704         for (i = 0; i < 4; i++) {
705                 tmp_exif = __gl_exif_read_1_byte(fd);
706                 if (tmp_exif < 0)
707                         goto GL_EXIF_FAILED;
708                 tmp[i] = (unsigned char)tmp_exif;
709         }
710
711         /* Check byte order and Tag Mark , "II(0x4949)" or "MM(0x4d4d)" */
712         if (tmp[0] == 0x49 && tmp[1] == 0x49 && tmp[2] == 0x2A &&
713             tmp[3] == 0x00) {
714                 gl_dbg("Intel");
715                 is_motorola = false;
716         } else if (tmp[0] == 0x4D && tmp[1] == 0x4D && tmp[2] == 0x00 &&
717                    tmp[3] == 0x2A) {
718                 gl_dbg("Motorola");
719                 is_motorola = true;
720         } else {
721                 goto GL_EXIF_FAILED;
722         }
723
724         for (i = 0; i < 4; i++) {
725                 tmp_exif = __gl_exif_read_1_byte(fd);
726                 if (tmp_exif < 0)
727                         goto GL_EXIF_FAILED;
728
729                 tmp[i] = (unsigned char)tmp_exif;
730                 gl_dbg("- %02X", tmp[i]);
731         }
732
733         /* Get first IFD offset (offset to IFD0) , MM-08000000, II-00000008 */
734         if (is_motorola) {
735                 if (tmp[4] != 0 && tmp[5] != 0)
736                         goto GL_EXIF_FAILED;
737                 offset = tmp[6];
738                 offset <<= 8;
739                 offset += tmp[7];
740         } else {
741                 if (tmp[7] != 0 && tmp[6] != 0)
742                         goto GL_EXIF_FAILED;
743                 offset = tmp[5];
744                 offset <<= 8;
745                 offset += tmp[4];
746         }
747         gl_dbg("offset: %d", offset);
748
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);
754                 if (tmp_exif < 0)
755                         goto GL_EXIF_FAILED;
756
757                 tmp[i] = (unsigned char)tmp_exif;
758         }
759         if (is_motorola) {
760                 tags_cnt = tmp[0];
761                 tags_cnt <<= 8;
762                 tags_cnt += tmp[1];
763         } else {
764                 tags_cnt = tmp[1];
765                 tags_cnt <<= 8;
766                 tags_cnt += tmp[0];
767         }
768         gl_dbg("tags_cnt: %d", tags_cnt);
769         if (tags_cnt == 0) {
770                 gl_dbgE("tags_cnt == 0 - 2");
771                 goto GL_EXIF_FAILED;
772         }
773
774         /* Search for Orientation Tag in IFD0 */
775         unsigned int tag_num = 0;
776         while (1) {
777                 /* Every directory entry size is 12 */
778                 for (i = 0; i < 12; i++) {
779                         tmp_exif = __gl_exif_read_1_byte(fd);
780                         if (tmp_exif < 0)
781                                 goto GL_EXIF_FAILED;
782
783                         tmp[i] = (unsigned char)tmp_exif;
784                 }
785                 /* Get Tag number */
786                 if (is_motorola) {
787                         tag_num = tmp[0];
788                         tag_num <<= 8;
789                         tag_num += tmp[1];
790                 } else {
791                         tag_num = tmp[1];
792                         tag_num <<= 8;
793                         tag_num += tmp[0];
794                 }
795                 /* found Orientation Tag */
796                 if (tag_num == 0x0112) {
797                         gl_dbgW("Found orientation tag!");
798                         break;
799                 }
800                 if (--tags_cnt == 0) {
801                         gl_dbgE("tags_cnt == 0");
802                         goto GL_EXIF_FAILED;
803                 }
804         }
805
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 */
808         if (b_write) {
809                 gl_dbg("Write: %d", *orientation);
810                 /* Set the Orientation value */
811                 if (is_motorola)
812                         tmp[9] = (unsigned char)(*orientation);
813                 else
814                         tmp[8] = (unsigned char)(*orientation);
815
816                 /* Move pointer back to the entry start point */
817                 fseek(fd, -12, SEEK_CUR);
818                 fwrite(tmp, 1, 10, fd);
819         } else {
820                 /* Get the Orientation value */
821                 if (is_motorola) {
822                         if (tmp[8] != 0) {
823                                 gl_dbgE("tmp[8] != 0");
824                                 goto GL_EXIF_FAILED;
825                         }
826                         *orientation = (unsigned int)tmp[9];
827                 } else {
828                         if (tmp[9] != 0) {
829                                 gl_dbgE("tmp[9] != 0");
830                                 goto GL_EXIF_FAILED;
831                         }
832                         *orientation = (unsigned int)tmp[8];
833                 }
834                 if (*orientation > 8) {
835                         gl_dbgE("*orient > 8");
836                         goto GL_EXIF_FAILED;
837                 }
838                 gl_dbg("Read: %d", *orientation);
839         }
840
841         ret = 0;
842
843  GL_EXIF_FAILED:
844
845         fclose(fd);
846         gl_dbg("All done");
847         return ret;
848 }
849
850 static int __gl_exif_rw_orient(char *file_path, unsigned int *orient, bool b_write)
851 {
852         GL_CHECK_VAL(file_path, -1);
853         gl_dbg("b_write: %d", b_write);
854         unsigned int length = 0;
855         unsigned int i = 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;
861         int tmp_exif = -1;
862         unsigned char exif_data[GL_EXIF_BUF_LEN_MAX] = { 0, };
863         FILE *fd = NULL;
864         int ret = -1;
865
866         if (b_write) {
867                 if ((fd = fopen(file_path, "rb+")) == NULL) {
868                         gl_dbgE("Can't open %s!", file_path);
869                         return -1;
870                 }
871         } else {
872                 if ((fd = fopen(file_path, "rb")) == NULL) {
873                         gl_dbgE("Can't open %s!", file_path);
874                         return -1;
875                 }
876         }
877
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);
881                 if (tmp_exif < 0)
882                         goto GL_EXIF_FAILED;
883
884                 exif_data[i] = (unsigned char)tmp_exif;
885         }
886
887         if (exif_data[0] == GL_EXIF_TAG && exif_data[1] == GL_EXIF_SOI) {
888                 gl_dbg("JPEG file");
889         } else {
890                 gl_dbgE("Not a JPEG file!");
891                 goto GL_EXIF_FAILED;
892         }
893
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);
900                 return ret;
901         } else {
902                 gl_dbgE("Not a Exif in APP1 or Jiff in APP2[%d]!", exif_data[3]);
903                 goto GL_EXIF_FAILED;
904         }
905
906         /* Get the marker parameter length count */
907         if (__gl_exif_read_2_bytes(fd, &length) < 0)
908                 goto GL_EXIF_FAILED;
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 */
912         if (length < 8) {
913                 gl_dbgE("length < 8");
914                 goto GL_EXIF_FAILED;
915         }
916         length -= 8;
917
918          /* Length of an IFD entry */
919         if (length < 12) {
920                 gl_dbgE("length < 12");
921                 goto GL_EXIF_FAILED;
922         }
923
924         /* Read Exif head, check for "Exif" */
925         for (i = 0; i < 6; i++) {
926                 tmp_exif = __gl_exif_read_1_byte(fd);
927                 if (tmp_exif < 0)
928                         goto GL_EXIF_FAILED;
929
930                 exif_data[i] = (unsigned char)tmp_exif;
931                 gl_dbg("- %02X", exif_data[i]);
932         }
933
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!");
938                 goto GL_EXIF_FAILED;
939         }
940
941         /* Read Exif body */
942         for (i = 0; i < length; i++) {
943                 tmp_exif = __gl_exif_read_1_byte(fd);
944                 if (tmp_exif < 0)
945                         goto GL_EXIF_FAILED;
946                 exif_data[i] = (unsigned char)tmp_exif;
947         }
948
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) {
952                 gl_dbg("Intel");
953                 is_motorola = false;
954         } else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D &&
955                  exif_data[2] == 0x00 && exif_data[3] == 0x2A) {
956                 gl_dbg("Motorola");
957                 is_motorola = true;
958         } else {
959                 goto GL_EXIF_FAILED;
960         }
961
962         /* Get first IFD offset (offset to IFD0) , MM-00000008, II-08000000 */
963         if (is_motorola) {
964                 if (exif_data[4] != 0 && exif_data[5] != 0)
965                         goto GL_EXIF_FAILED;
966                 offset = exif_data[6];
967                 offset <<= 8;
968                 offset += exif_data[7];
969         } else {
970                 if (exif_data[7] != 0 && exif_data[6] != 0)
971                         goto GL_EXIF_FAILED;
972                 offset = exif_data[5];
973                 offset <<= 8;
974                 offset += exif_data[4];
975         }
976         /* check end of data segment */
977         if (offset > length - 2) {
978                 gl_dbgE("offset > length - 2");
979                 goto GL_EXIF_FAILED;
980         }
981         /* IFD: Image File Directory */
982         /* Get the number of directory entries contained in this IFD, - EEEE */
983         if (is_motorola) {
984                 tags_cnt = exif_data[offset];
985                 tags_cnt <<= 8;
986                 tags_cnt += exif_data[offset+1];
987         } else {
988                 tags_cnt = exif_data[offset+1];
989                 tags_cnt <<= 8;
990                 tags_cnt += exif_data[offset];
991         }
992         if (tags_cnt == 0) {
993                 gl_dbgE("tags_cnt == 0 - 2");
994                 goto GL_EXIF_FAILED;
995         }
996         offset += 2;
997
998         /* check end of data segment */
999         if (offset > length - 12) {
1000                 gl_dbgE("offset > length - 12");
1001                 goto GL_EXIF_FAILED;
1002         }
1003
1004         /* Search for Orientation Tag in IFD0 */
1005         while (1) {
1006                 /* Get Tag number */
1007                 if (is_motorola) {
1008                         tag_num = exif_data[offset];
1009                         tag_num <<= 8;
1010                         tag_num += exif_data[offset+1];
1011                 } else {
1012                         tag_num = exif_data[offset+1];
1013                         tag_num <<= 8;
1014                         tag_num += exif_data[offset];
1015                 }
1016                 /* found Orientation Tag */
1017                 if (tag_num == 0x0112) {
1018                         gl_dbgW("Found orientation tag!");
1019                         break;
1020                 }
1021                 if (--tags_cnt == 0) {
1022                         gl_dbgE("tags_cnt == 0");
1023                         goto GL_EXIF_FAILED;
1024                 }
1025                 /* Every directory entry size is 12 */
1026                 offset += 12;
1027         }
1028
1029         if (b_write) {
1030                 gl_dbg("Write: %d", *orient);
1031                 /* Set the Orientation value */
1032                 if (is_motorola)
1033                         exif_data[offset+9] = (unsigned char)(*orient);
1034                 else
1035                         exif_data[offset+8] = (unsigned char)(*orient);
1036
1037                 fseek(fd, jfif_offset + (4 + 2 + 6 + 2) + offset, SEEK_SET);
1038                 fwrite(exif_data + 2 + offset, 1, 10, fd);
1039         } else {
1040                 /* Get the Orientation value */
1041                 if (is_motorola) {
1042                         if (exif_data[offset+8] != 0) {
1043                                 gl_dbgE("exif_data[offset+8] != 0");
1044                                 goto GL_EXIF_FAILED;
1045                         }
1046                         *orient = (unsigned int)exif_data[offset+9];
1047                 } else {
1048                         if (exif_data[offset+9] != 0) {
1049                                 gl_dbgE("exif_data[offset+9] != 0");
1050                                 goto GL_EXIF_FAILED;
1051                         }
1052                         *orient = (unsigned int)exif_data[offset+8];
1053                 }
1054                 if (*orient > 8) {
1055                         gl_dbgE("*orient > 8");
1056                         goto GL_EXIF_FAILED;
1057                 }
1058                 gl_dbg("Read: %d", *orient);
1059         }
1060
1061         ret = 0;
1062
1063  GL_EXIF_FAILED:
1064
1065         fclose(fd);
1066         gl_dbg("All done");
1067         return ret;
1068 }
1069
1070 int _gl_exif_get_orientation(char *file_path, unsigned int *orientation)
1071 {
1072         GL_CHECK_VAL(orientation, -1);
1073         GL_CHECK_VAL(file_path, -1);
1074         gl_dbg("file_path: %s", file_path);
1075
1076         return __gl_exif_rw_orient(file_path, orientation, false);
1077 }
1078
1079 int _gl_exif_set_orientation(char *file_path, unsigned int orientation)
1080 {
1081         GL_CHECK_VAL(file_path, -1);
1082         gl_dbg("file_path: %s", file_path);
1083
1084         return __gl_exif_rw_orient(file_path, &orientation, true);
1085 }
1086
1087 int _gl_exif_get_rotated_orientation(unsigned int orientation, bool b_left)
1088 {
1089         int rotated_orientataion;
1090         gl_dbg("b_left: %d", b_left);
1091
1092         switch (orientation){
1093         case GL_ORIENTATION_ROT_0:
1094                 /* true: 0 -> 270, false: 0 -> 90 */
1095                 if (b_left)
1096                         rotated_orientataion = GL_ORIENTATION_ROT_270;
1097                 else
1098                         rotated_orientataion = GL_ORIENTATION_ROT_90;
1099                 break;
1100         case GL_ORIENTATION_ROT_90:
1101                 /* true: 90 -> 0, false: 90 -> 180 */
1102                 if (b_left)
1103                         rotated_orientataion = GL_ORIENTATION_ROT_0;
1104                 else
1105                         rotated_orientataion = GL_ORIENTATION_ROT_180;
1106                 break;
1107         case GL_ORIENTATION_ROT_180:
1108                 /* true: 180 -> 90, false: 180 -> 270 */
1109                 if (b_left)
1110                         rotated_orientataion = GL_ORIENTATION_ROT_90;
1111                 else
1112                         rotated_orientataion = GL_ORIENTATION_ROT_270;
1113                 break;
1114         case GL_ORIENTATION_ROT_270:
1115                 /* true: 270 -> 180, false: 270 -> 0 */
1116                 if (b_left)
1117                         rotated_orientataion = GL_ORIENTATION_ROT_180;
1118                 else
1119                         rotated_orientataion = GL_ORIENTATION_ROT_0;
1120                 break;
1121         default:
1122                 gl_dbgE("Wrong oriectation: %d!", orientation);
1123                 rotated_orientataion = GL_ORIENTATION_ROT_ERR;
1124                 break;
1125         }
1126
1127         gl_dbg("New orientation: %d", rotated_orientataion);
1128         return rotated_orientataion;
1129 }
1130
1131 #endif
1132