Tizen 2.0 Release
[apps/core/preloaded/ug-image-viewer-efl.git] / common / src / ivug-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://floralicense.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
19 /**
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:
27  *
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.
30  *
31  * Value         0th Row                0th Column
32  *   1    top             left side
33  *   2    top             right side
34  *   3    bottom                  right side
35  *   4    bottom                  left side
36  *   5    left side          top
37  *   6    right side        top
38  *   7    right side        bottom
39  *   8    left side          bottom
40  *
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
44  * the captured scene.
45  *
46  * Here is another description given by Adam M. Costello:
47  *
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):
51  *
52  *       1             2         3      4            5                 6                   7                  8
53  *
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
57  *  88               88        88    88
58  *  88               88  888888   888888
59 */
60
61 #include "ivug-debug.h"
62 #include "ivug-exif.h"
63
64 #undef LOG_LVL
65 #define LOG_LVL (DBG_MSG_LVL_HIGH | DBG_MSG_LVL_DEBUG)
66
67 #undef LOG_CAT
68 #define LOG_CAT "IV-EXIF"
69
70 #define gl_dbgE MSG_ERROR
71 #define gl_dbgW MSG_WARN
72
73 #define gl_dbg MSG_MED
74
75 #define GL_CHECK_VAL(expr, val) \
76         do { \
77                 if(!expr) { \
78                         MSG_ERROR("[%s] Return value %d", #expr, val );\
79                         return (val); \
80                 } \
81         } while (0)
82
83
84 #include <stdlib.h>
85 #include <string.h>
86 #include <time.h>
87 #include <Elementary.h>
88
89 #define GL_EXIF_BUF_LEN_MAX 65536L
90 #define GL_EXIF_BUF_TIME_LEN_MAX 20
91 #define GL_EXIF_DEFAULT_YEAR 1900
92
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
100
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
113
114 #define GL_EXI_TMP_JPEG_FILE "/opt/usr/media/.gallery_tmp_write_exif.jpg"
115
116 /* Write one byte, testing for EOF */
117 static int __gl_exif_write_1_byte(FILE *fd, int c)
118 {
119         if (fputc(c, fd) < 0) {
120                 gl_dbgE("fputc failed!");
121                 return -1;
122         }
123
124         return 0;
125 }
126
127 /* Read one byte, testing for EOF */
128 static int __gl_exif_read_1_byte(FILE *fd)
129 {
130         int c = 0;
131
132         /* Return next input byte, or EOF if no more */
133         c = getc(fd);
134         if (c == EOF) {
135                 gl_dbgE("Premature EOF in JPEG file!");
136                 return -1;
137         }
138
139         return c;
140 }
141
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)
145 {
146         int c1 = 0;
147         int c2 = 0;
148
149         /* Return next input byte, or EOF if no more */
150         c1 = getc(fd);
151         if (c1 == EOF) {
152                 gl_dbgE("Premature EOF in JPEG file!");
153                 return -1;
154         }
155
156         /* Return next input byte, or EOF if no more */
157         c2 = getc(fd);
158         if (c2 == EOF) {
159                 gl_dbgE("Premature EOF in JPEG file!");
160                 return -1;
161         }
162
163         if (len)
164                 *len = (((unsigned int)c1) << 8) + ((unsigned int)c2);
165
166         return 0;
167 }
168
169 /* Add raw exif tag and data */
170 static int __gl_exif_add_header(FILE *fd, unsigned int *orientation)
171 {
172         GL_CHECK_VAL(orientation, -1);
173         GL_CHECK_VAL(fd, -1);
174         int i = 0;
175         int ret = -1;
176         char *time_buf = NULL;
177         unsigned int offset = 0;
178
179         /* raw EXIF header data */
180         const unsigned char exif1[] = {
181                 GL_EXIF_TAG, GL_EXIF_SOI, GL_EXIF_TAG, GL_EXIF_APP1
182         };
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)
186                         goto GL_EXIF_FAILED;
187         }
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)
194                         goto GL_EXIF_FAILED;
195         }
196
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)
201                         goto GL_EXIF_FAILED;
202         }
203
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)
208                         goto GL_EXIF_FAILED;
209         }
210         offset += 4;
211
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)
216                         goto GL_EXIF_FAILED;
217         }
218         offset += 4;
219
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)
226                         goto GL_EXIF_FAILED;
227         }
228         offset += 2;
229
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)
234                         goto GL_EXIF_FAILED;
235         }
236         offset += 2;
237
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)
242                         goto GL_EXIF_FAILED;
243         }
244         offset += 6;
245
246         /* Set the Orientation value */
247         if (__gl_exif_write_1_byte(fd, (unsigned char)(*orientation)) < 0)
248                 goto GL_EXIF_FAILED;
249
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)
253                         goto GL_EXIF_FAILED;
254         }
255         offset += 4;
256
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)
261                         goto GL_EXIF_FAILED;
262         }
263         offset += 2;
264
265         /* Type: strings */
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)
269                         goto GL_EXIF_FAILED;
270         }
271         offset += 2;
272
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)
277                         goto GL_EXIF_FAILED;
278         }
279         offset += 8;
280
281         /* 20 bytes larger than 4 bytes,
282           * so next 4 bytes is data offset start from "II"(0x4949)*/
283
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)
287                 goto GL_EXIF_FAILED;
288
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)
292                         goto GL_EXIF_FAILED;
293         }
294
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)
301                         goto GL_EXIF_FAILED;
302         }
303
304         /* Date Time of image was last modified.
305           * Data format is "YYYY:MM:DD HH:MM:SS"+0x00, total 20bytes
306           */
307         time_t t;
308         struct tm tms;
309         struct tm *tm;
310
311         t = time (NULL);
312         tm = localtime_r(&t, &tms);
313
314         time_buf = (char *)calloc(1, GL_EXIF_BUF_TIME_LEN_MAX);
315         if (time_buf == NULL) {
316                 gl_dbgE("Faild to allocate memory!");
317                 goto GL_EXIF_FAILED;
318         }
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);
323
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!");
327                 goto GL_EXIF_FAILED;
328         }
329
330         ret = 0;
331
332  GL_EXIF_FAILED:
333
334         gl_dbg("All done");
335         if (time_buf)
336                 free(time_buf);
337         return ret;
338 }
339
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)
342 {
343         GL_CHECK_VAL(orientation, -1);
344         GL_CHECK_VAL(file_path, -1);
345         unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
346         FILE *fd = NULL;
347         int ret = -1;
348
349         if ((fd = fopen(file_path, "rb+")) == NULL) {
350                 gl_dbgE("Can't open %s!", file_path);
351                 return -1;
352         }
353
354         char *tmp_file = GL_EXI_TMP_JPEG_FILE;
355         FILE *tmp_fd = NULL;
356         if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
357                 gl_dbgE("Can't open %s!", tmp_file);
358                 goto GL_EXIF_FAILED;
359         }
360
361         /* Add raw EXIF header data */
362         if (__gl_exif_add_header(tmp_fd, orientation) < 0)
363                 goto GL_EXIF_FAILED;
364
365         size_t r_size = 0;
366         /* Remove start of JPEG image data section, 20 bytes */
367         r_size = fread(tmp, sizeof(char), 20, fd);
368
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!");
375
376                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
377         }
378
379         fclose(fd);
380         fd = fopen(file_path, "wb");
381         if (!fd) {
382                 gl_dbgE("Error creating file %s!", file_path);
383                         goto GL_EXIF_FAILED;
384         }
385
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!");
393
394                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
395         }
396
397         ret = 0;
398
399  GL_EXIF_FAILED:
400
401         if (fd)
402                 fclose(fd);
403         if (tmp_fd)
404                 fclose(tmp_fd);
405
406         /* Delete tmp file */
407         if (!ecore_file_unlink(tmp_file))
408                 gl_dbgE("Delete file failed");
409
410         gl_dbg("All done");
411         return ret;
412                         }
413
414 #if 0
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)
417 {
418         GL_CHECK_VAL(orientation, -1);
419         GL_CHECK_VAL(file_path, -1);
420         unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
421         FILE *fd = NULL;
422         int ret = -1;
423         int tmp_exif = -1;
424
425         if ((fd = fopen(file_path, "rb+")) == NULL) {
426                 gl_dbgE("Can't open %s!", file_path);
427                 return -1;
428                 }
429
430         char *tmp_file = GL_EXI_TMP_JPEG_FILE;
431         FILE *tmp_fd = NULL;
432         if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
433                 gl_dbgE("Can't open %s!", tmp_file);
434                 goto GL_EXIF_FAILED;
435         }
436
437         /* Add raw EXIF header data */
438         if (__gl_exif_add_header(tmp_fd, orientation) < 0)
439                 goto GL_EXIF_FAILED;
440
441         size_t r_size = 0;
442         /* Remove start of JPEG image data section, 20 bytes */
443         r_size = fread(tmp, sizeof(char), 20, fd);
444
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!");
451
452                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
453         }
454
455         fclose(fd);
456         fd = fopen(file_path, "wb");
457         if (!fd) {
458                 gl_dbgE("Error creating file %s!", file_path);
459                 goto GL_EXIF_FAILED;
460         }
461
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!");
469
470                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
471         }
472
473         ret = 0;
474
475  GL_EXIF_FAILED:
476
477         if (fd)
478                 fclose(fd);
479         if (tmp_fd)
480                 fclose(tmp_fd);
481
482                 /* Delete tmp file */
483                 if (!ecore_file_unlink(tmp_file))
484                         gl_dbgE("Delete file failed");
485
486         gl_dbg("All done");
487         return ret;
488 }
489
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)
492 {
493         GL_CHECK_VAL(orientation, -1);
494         GL_CHECK_VAL(file_path, -1);
495         unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
496         FILE *fd = NULL;
497         int ret = -1;
498
499         if ((fd = fopen(file_path, "rb+")) == NULL) {
500                 gl_dbgE("Can't open %s!", file_path);
501                 return -1;
502         }
503
504         char *tmp_file = GL_EXI_TMP_JPEG_FILE;
505         FILE *tmp_fd = NULL;
506         if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
507                 gl_dbgE("Can't open %s!", tmp_file);
508                 goto GL_EXIF_FAILED;
509         }
510
511         /* Add raw EXIF header data */
512         if (__gl_exif_add_header(tmp_fd, orientation) < 0)
513                 goto GL_EXIF_FAILED;
514
515         size_t r_size = 0;
516         /* Remove start of JPEG image data section, 20 bytes */
517         r_size = fread(tmp, sizeof(char), 20, fd);
518
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!");
525
526                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
527         }
528
529         fclose(fd);
530         fd = fopen(file_path, "wb");
531         if (!fd) {
532                 gl_dbgE("Error creating file %s!", file_path);
533                 goto GL_EXIF_FAILED;
534         }
535
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!");
543
544                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
545         }
546
547         ret = 0;
548
549  GL_EXIF_FAILED:
550
551         if (fd)
552                 fclose(fd);
553         if (tmp_fd)
554                 fclose(tmp_fd);
555
556                 /* Delete tmp file */
557                 if (!ecore_file_unlink(tmp_file))
558                         gl_dbgE("Delete file failed");
559
560         gl_dbg("All done");
561         return ret;
562 }
563
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)
566 {
567         GL_CHECK_VAL(orientation, -1);
568         GL_CHECK_VAL(file_path, -1);
569         unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
570         FILE *fd = NULL;
571         int ret = -1;
572         int tmp_exif = -1;
573
574         if ((fd = fopen(file_path, "rb+")) == NULL) {
575                 gl_dbgE("Can't open %s!", file_path);
576                 return -1;
577         }
578
579         char *tmp_file = GL_EXI_TMP_JPEG_FILE;
580         FILE *tmp_fd = NULL;
581         if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
582                 gl_dbgE("Can't open %s!", tmp_file);
583                 goto GL_EXIF_FAILED;
584         }
585
586         /* Add raw EXIF header data */
587         if (__gl_exif_add_header(tmp_fd, orientation) < 0)
588                 goto GL_EXIF_FAILED;
589
590         size_t r_size = 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!");
599
600                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
601         }
602
603         fclose(fd);
604         fd = fopen(file_path, "wb");
605         if (!fd) {
606                 gl_dbgE("Error creating file %s!", file_path);
607                 goto GL_EXIF_FAILED;
608         }
609
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!");
617
618                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
619         }
620
621         ret = 0;
622
623  GL_EXIF_FAILED:
624
625         if (fd)
626                 fclose(fd);
627         if (tmp_fd)
628                 fclose(tmp_fd);
629         /* Delete tmp file */
630         if (!ecore_file_unlink(tmp_file))
631                 gl_dbgE("Delete file failed");
632
633         gl_dbg("All done");
634         return ret;
635 }
636 #endif
637
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){
641
642         GL_CHECK_VAL(orientation, -1);
643         GL_CHECK_VAL(file_path, -1);
644         unsigned char tmp[GL_EXIF_BUF_LEN_MAX] = { 0, };
645         FILE *fd = NULL;
646         int ret = -1;
647         int tmp_exif = -1;
648         int i = 0;
649         unsigned int length = 0;
650         bool is_motorola = false; /* Flag for byte order */
651         unsigned int offset = 0;
652         size_t r_size = 0;
653         const unsigned char ifd_data_format[13] = {
654                 /*add 0 to ifd_data_format[0] ,for  easy to use*/
655                 0,
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
668
669         };
670
671         if ((fd = fopen(file_path, "rb+")) == NULL) {
672                 gl_dbgE("Can't open %s!", file_path);
673                 return -1;
674         }
675
676         char *tmp_file = GL_EXI_TMP_JPEG_FILE;
677         FILE *tmp_fd = NULL;
678         if ((tmp_fd = fopen(tmp_file, "wb+")) == NULL) {
679                 gl_dbgE("Can't open %s!", tmp_file);
680                 goto GL_EXIF_FAILED;
681         }
682         /* Find APP1 */
683         bool b_tag_ff = false;
684         while(1) {
685                 tmp_exif = __gl_exif_read_1_byte(fd);
686                 if (tmp_exif < 0)
687                         goto GL_EXIF_FAILED;
688
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)
691                         goto GL_EXIF_FAILED;
692
693                 tmp[0] = (unsigned char)tmp_exif;
694
695                 gl_dbg("- %02X", tmp[0]);
696                 if (!b_tag_ff) {
697                         /* Get first tag */
698                         if (tmp[0] == GL_EXIF_TAG) {
699                                 gl_dbgW("0xFF!");
700                                 b_tag_ff = true;
701                         }
702                         continue;
703                 }
704
705                 /* Get APP1 */
706                 if (tmp[0] == GL_EXIF_APP1) {
707                         gl_dbgW("Exif in APP1!");
708                         break;
709                 } else {
710                         gl_dbgW("0x%02X!",tmp[0]);
711                         b_tag_ff = false;
712                 }
713         }
714
715         /* Get the marker parameter length count */
716         if (__gl_exif_read_2_bytes(fd, &length) < 0)
717                 goto GL_EXIF_FAILED;
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 */
721         if (length < 8) {
722                 gl_dbgE("length < 8");
723                 goto GL_EXIF_FAILED;
724         }
725         /*modify  the marker parameter length, orientation tag is 12*/
726         length += 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)
732                         goto GL_EXIF_FAILED;
733         }
734
735         for (i = 0; i < 6; i++) {
736                 tmp_exif = __gl_exif_read_1_byte(fd);
737                 if (tmp_exif < 0)
738                         goto GL_EXIF_FAILED;
739
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)
743                         goto GL_EXIF_FAILED;
744         }
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!");
748         } else {
749                 gl_dbgW("Not met Exif!");
750                         goto GL_EXIF_FAILED;
751         }
752         /* Read Exif body */
753         for (i = 0; i < 4; i++) {
754                 tmp_exif = __gl_exif_read_1_byte(fd);
755                 if (tmp_exif < 0)
756                         goto GL_EXIF_FAILED;
757                 tmp[i] = (unsigned char)tmp_exif;
758                 if (__gl_exif_write_1_byte(tmp_fd, tmp[i]) < 0)
759                         goto GL_EXIF_FAILED;
760         }
761
762         /* Check byte order and Tag Mark , "II(0x4949)" or "MM(0x4d4d)" */
763         if (tmp[0] == 0x49 && tmp[1] == 0x49 && tmp[2] == 0x2A &&
764             tmp[3] == 0x00) {
765                 gl_dbg("Intel");
766                 is_motorola = false;
767         } else if (tmp[0] == 0x4D && tmp[1] == 0x4D && tmp[2] == 0x00 &&
768                    tmp[3] == 0x2A) {
769                 gl_dbg("Motorola");
770                 is_motorola = true;
771         } else {
772                 goto GL_EXIF_FAILED;
773         }
774
775         for (i = 0; i < 4; i++) {
776                 tmp_exif = __gl_exif_read_1_byte(fd);
777                 if (tmp_exif < 0)
778                         goto GL_EXIF_FAILED;
779
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)
783                 goto GL_EXIF_FAILED;
784         }
785
786         /* Get first IFD offset (offset to IFD0) , MM-08000000, II-00000008 */
787         if (is_motorola) {
788                 if (tmp[0] != 0 && tmp[1] != 0)
789                         goto GL_EXIF_FAILED;
790                 offset = tmp[2];
791                 offset <<= 8;
792                 offset += tmp[3];
793         } else {
794                 if (tmp[3] != 0 && tmp[2] != 0)
795                         goto GL_EXIF_FAILED;
796                 offset = tmp[1];
797                 offset <<= 8;
798                 offset += tmp[0];
799         }
800         gl_dbg("offset: %d", offset);
801         /*if offset >8, copy data from there to IFD start position*/
802         if(offset > 8){
803                 for (i = 0; i < (offset - 8); i++) {
804                         tmp_exif = __gl_exif_read_1_byte(fd);
805                         if (tmp_exif < 0)
806                         goto GL_EXIF_FAILED;
807
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)
811                         goto GL_EXIF_FAILED;
812                 }
813         }
814
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);
820                 if (tmp_exif < 0)
821                         goto GL_EXIF_FAILED;
822
823                 tmp[i] = (unsigned char)tmp_exif;
824         }
825         if (is_motorola) {
826                 tags_cnt = tmp[0];
827                 tags_cnt <<= 8;
828                 tags_cnt += tmp[1];
829         } else {
830                 tags_cnt = tmp[1];
831                 tags_cnt <<= 8;
832                 tags_cnt += tmp[0];
833         }
834         gl_dbg("tags_cnt: %d", tags_cnt);
835         /*modify tags num,add orientation tag */
836         tags_cnt += 1;
837         gl_dbg("modified tags_cnt: %d", tags_cnt);
838         if (is_motorola) {
839                 tmp[0] = (tags_cnt >> 8) & 0xff;
840                 tmp[1] = tags_cnt & 0xff;
841         } else {
842                 tmp[0] = tags_cnt & 0xff;
843                 tmp[1] = (tags_cnt >> 8) & 0xff;
844         }
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)
848                 goto GL_EXIF_FAILED;
849
850         }
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;
855         int j = 0;
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*/
861         if (is_motorola) {
862                 orientation_tag[0] = 0x01;
863                 orientation_tag[1] = 0x12;
864
865                 orientation_tag[2] = 0x00;
866                 orientation_tag[3] = 0x03;
867
868                 orientation_tag[4] = 0x00;
869                 orientation_tag[5] = 0x00;
870                 orientation_tag[6] = 0x00;
871                 orientation_tag[7] = 0x01;
872
873                 orientation_tag[8] = 0x00;
874                 orientation_tag[9] = (unsigned char)(*orientation);
875                 orientation_tag[10] = 0x00;
876                 orientation_tag[11] = 0x00;
877
878         } else {
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;
891         }
892         /*if there is no other tag, then only insert orientation_tag,don't go to the while(1)*/
893         if(tags_cnt == 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)
897                                 goto GL_EXIF_FAILED;
898                 }
899         }
900         while(1){
901                 if (--tags_cnt == 0) {
902                         break;
903                 }
904
905                 /* Every directory entry size is 12 */
906                 for (i = 0; i < 12; i++) {
907                         tmp_exif = __gl_exif_read_1_byte(fd);
908                         if (tmp_exif < 0)
909                                 goto GL_EXIF_FAILED;
910
911                         tmp[i] = (unsigned char)tmp_exif;
912                 }
913                 /* Get Tag number */
914                 if (is_motorola) {
915                         tag_num = tmp[0];
916                         tag_num <<= 8;
917                         tag_num += tmp[1];
918                 } else {
919                         tag_num = tmp[1];
920                         tag_num <<= 8;
921                         tag_num += tmp[0];
922                 }
923                 gl_dbgW("tag num %02X!" , tag_num);
924                 /* to find Orientation Tag position */
925                 if (tag_num < 0x0112) {
926
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)
932                                         goto GL_EXIF_FAILED;
933                                 }
934                                 b_found_position = true;
935                         }
936                         if (is_motorola) {
937                                 data_type = tmp[2];
938                                 data_type <<= 8;
939                                 data_type += tmp[3];
940
941                                 unit_num = tmp[4];
942                                 unit_num <<= 8;
943                                 unit_num += tmp[5];
944                                 unit_num <<= 8;
945                                 unit_num += tmp[6];
946                                 unit_num <<= 8;
947                                 unit_num += tmp[7];
948                         } else {
949                                 data_type = tmp[3];
950                                 data_type <<= 8;
951                                 data_type += tmp[2];
952
953                                 unit_num = tmp[7];
954                                 unit_num <<= 8;
955                                 unit_num += tmp[6];
956                                 unit_num <<= 8;
957                                 unit_num += tmp[5];
958                                 unit_num <<= 8;
959                                 unit_num += tmp[4];
960                         }
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!");
965                         goto GL_EXIF_FAILED;
966                         }
967
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*/
971                         if(data_length > 4){
972                                 if (is_motorola) {
973                                         offset_value = tmp[8];
974                                         offset_value <<= 8;
975                                         offset_value += tmp[9];
976                                         offset_value <<= 8;
977                                         offset_value += tmp[10];
978                                         offset_value <<= 8;
979                                         offset_value += tmp[11];
980                                         gl_dbgW("offset_value %02X!" , offset_value);
981                                         /*add orientation offset*/
982                                         offset_value += 12;
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]);
992                                 } else {
993                                         offset_value = tmp[11];
994                                         offset_value <<= 8;
995                                         offset_value += tmp[10];
996                                         offset_value <<= 8;
997                                         offset_value += tmp[9];
998                                         offset_value <<= 8;
999                                         offset_value += tmp[8];
1000                                         gl_dbgW("offset_value %02X!" , offset_value);
1001                                         /*add orientation offset*/
1002                                         offset_value += 12;
1003                                         gl_dbgW("changed offset_value %02X!" , offset_value);
1004
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]);
1013
1014         }
1015
1016                         }
1017
1018                 }
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;
1023
1024                 }
1025                 memset(tmp, 0x00, 12);
1026
1027         }
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!");
1034
1035                 memset(tmp, 0x00, GL_EXIF_BUF_LEN_MAX);
1036         }
1037         fclose(fd);
1038         fd = NULL;
1039         fd = fopen(file_path, "wb");
1040         if (!fd) {
1041                 gl_dbgE("Error creating file %s!", file_path);
1042                 goto GL_EXIF_FAILED;
1043         }
1044
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);
1053         }
1054
1055         ret = 0;
1056
1057  GL_EXIF_FAILED:
1058
1059         if (fd){
1060                 fclose(fd);
1061                 fd = NULL;
1062         }
1063
1064         if (tmp_fd){
1065                 fclose(tmp_fd);
1066                 tmp_fd = NULL;
1067         }
1068
1069                 /* Delete tmp file */
1070                 if (!ecore_file_unlink(tmp_file))
1071                         gl_dbgE("Delete file failed");
1072
1073         gl_dbg("All done");
1074         return ret;
1075 }
1076
1077 static int __gl_exif_rw_jfif(FILE *fd, const char *file_path,
1078                              unsigned int *orientation, bool b_write)
1079 {
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, };
1084         int i = 0;
1085         unsigned int length = 0;
1086         int tmp_exif = -1;
1087         bool is_motorola = false; /* Flag for byte order */
1088         unsigned int offset = 0;
1089         int ret = -1;
1090         /*unsigned char version = 0x00; */
1091
1092         if (__gl_exif_read_2_bytes(fd, &length) < 0)
1093                 goto GL_EXIF_FAILED;
1094         gl_dbg("length: %d", length);
1095
1096         for (i = 0; i < 5; i++) {
1097                 tmp_exif = __gl_exif_read_1_byte(fd);
1098                 if (tmp_exif < 0)
1099                         goto GL_EXIF_FAILED;
1100                 tmp[i] = (unsigned char)tmp_exif;
1101         }
1102
1103         /* JFIF0 */
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;
1108         }
1109
1110         for (i = 0; i < 2; i++) {
1111                 tmp_exif = __gl_exif_read_1_byte(fd);
1112                 if (tmp_exif < 0)
1113                         goto GL_EXIF_FAILED;
1114                 tmp[i] = (unsigned char)tmp_exif;
1115         }
1116
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");
1124         } else {
1125                 gl_dbgE("Unknow Jfif version[%d.%d]!", tmp[0], tmp[1]);
1126                 goto GL_EXIF_FAILED;
1127         }
1128
1129         /* Save version */
1130         /*version = tmp[1]; */
1131
1132         /* Find APP1 */
1133         bool b_tag_ff = false;
1134         while(1) {
1135                 tmp_exif = __gl_exif_read_1_byte(fd);
1136                 if (tmp_exif < 0)
1137                         goto GL_EXIF_FAILED;
1138
1139                 tmp[0] = (unsigned char)tmp_exif;
1140
1141                 gl_dbg("- %02X", tmp[0]);
1142                 if (!b_tag_ff) {
1143                         /* Get first tag */
1144                         if (tmp[0] == GL_EXIF_TAG) {
1145                                 gl_dbgW("0xFF!");
1146                                 b_tag_ff = true;
1147                         }
1148                         continue;
1149                 }
1150
1151                 /* Get APP1 */
1152                 if (tmp[0] == GL_EXIF_APP1) {
1153                         gl_dbgW("Exif in APP1!");
1154                         break;
1155                 }
1156
1157                 gl_dbgW("No Exif in APP1!");
1158
1159                 /* Close file */
1160                 fclose(fd);
1161                 if (!b_write) {
1162                         /* Normal orientation = 0degree = 1 */
1163                         *orientation = 1;
1164                         return -1;
1165                 }
1166                 return __gl_exif_add_exif_to_jfif(file_path, orientation);
1167 #if 0
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);
1172                 } else {
1173                         return __gl_exif_rw_jfif_1dot02(file_path, orientation);
1174                 }
1175 #endif
1176         }
1177
1178         /* Find Exif */
1179         while(1) {
1180                 for (i = 0; i < 6; i++) {
1181                 tmp_exif = __gl_exif_read_1_byte(fd);
1182                         if (tmp_exif < 0) {
1183                                 gl_dbgW("Not met Exif!");
1184                                 goto GL_EXIF_FAILED;
1185                         }
1186
1187                         tmp[i] = (unsigned char)tmp_exif;
1188                         gl_dbg("- %02X", tmp[i]);
1189                 }
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!");
1193                         break;
1194                 } else {
1195                         gl_dbg("Not met Exif!");
1196                         fseek(fd, -5, SEEK_CUR);
1197                         continue;
1198                 }
1199         }
1200
1201         /* Read Exif body */
1202         for (i = 0; i < 4; i++) {
1203                 tmp_exif = __gl_exif_read_1_byte(fd);
1204                 if (tmp_exif < 0)
1205                         goto GL_EXIF_FAILED;
1206                 tmp[i] = (unsigned char)tmp_exif;
1207         }
1208
1209         /* Check byte order and Tag Mark , "II(0x4949)" or "MM(0x4d4d)" */
1210         if (tmp[0] == 0x49 && tmp[1] == 0x49 && tmp[2] == 0x2A &&
1211             tmp[3] == 0x00) {
1212                 gl_dbg("Intel");
1213                 is_motorola = false;
1214         } else if (tmp[0] == 0x4D && tmp[1] == 0x4D && tmp[2] == 0x00 &&
1215                    tmp[3] == 0x2A) {
1216                 gl_dbg("Motorola");
1217                 is_motorola = true;
1218         } else {
1219                 goto GL_EXIF_FAILED;
1220         }
1221
1222         for (i = 0; i < 4; i++) {
1223                 tmp_exif = __gl_exif_read_1_byte(fd);
1224                 if (tmp_exif < 0)
1225                         goto GL_EXIF_FAILED;
1226
1227                 tmp[i] = (unsigned char)tmp_exif;
1228                 gl_dbg("- %02X", tmp[i]);
1229         }
1230
1231         /* Get first IFD offset (offset to IFD0) , MM-08000000, II-00000008 */
1232         if (is_motorola) {
1233                 if (tmp[0] != 0 && tmp[1] != 0)
1234                         goto GL_EXIF_FAILED;
1235                 offset = tmp[2];
1236                 offset <<= 8;
1237                 offset += tmp[3];
1238         } else {
1239                 if (tmp[3] != 0 && tmp[2] != 0)
1240                         goto GL_EXIF_FAILED;
1241                 offset = tmp[1];
1242                 offset <<= 8;
1243                 offset += tmp[0];
1244         }
1245         gl_dbg("offset: %d", offset);
1246
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);
1252                 if (tmp_exif < 0)
1253                         goto GL_EXIF_FAILED;
1254
1255                 tmp[i] = (unsigned char)tmp_exif;
1256         }
1257         if (is_motorola) {
1258                 tags_cnt = tmp[0];
1259                 tags_cnt <<= 8;
1260                 tags_cnt += tmp[1];
1261         } else {
1262                 tags_cnt = tmp[1];
1263                 tags_cnt <<= 8;
1264                 tags_cnt += tmp[0];
1265         }
1266         gl_dbg("tags_cnt: %d", tags_cnt);
1267         if (tags_cnt == 0) {
1268                 gl_dbgE("tags_cnt == 0,no found orientation tag!");
1269                 if (b_write) {
1270                         gl_dbgW("to add an orientation tag!");
1271                         fclose(fd);
1272                         fd = NULL;
1273                         return __gl_exif_add_orientation_tag(file_path, orientation);
1274
1275                 } else{
1276                         /* Normal orientation = 0degree = 1 */
1277                         *orientation = 1;
1278                         ret = -1;
1279                 }
1280                 goto GL_EXIF_FAILED;
1281         }
1282
1283         /* Search for Orientation Tag in IFD0 */
1284         unsigned int tag_num = 0;
1285         while (1) {
1286                 /* Every directory entry size is 12 */
1287                 for (i = 0; i < 12; i++) {
1288                         tmp_exif = __gl_exif_read_1_byte(fd);
1289                         if (tmp_exif < 0)
1290                                 goto GL_EXIF_FAILED;
1291
1292                         tmp[i] = (unsigned char)tmp_exif;
1293                 }
1294                 /* Get Tag number */
1295                 if (is_motorola) {
1296                         tag_num = tmp[0];
1297                         tag_num <<= 8;
1298                         tag_num += tmp[1];
1299                 } else {
1300                         tag_num = tmp[1];
1301                         tag_num <<= 8;
1302                         tag_num += tmp[0];
1303                 }
1304                 /* found Orientation Tag */
1305                 if (tag_num == 0x0112) {
1306                         gl_dbgW("Found orientation tag!");
1307                         break;
1308                 }
1309                 if (--tags_cnt == 0) {
1310                         gl_dbgW("tags_cnt == 0, no found orientation tag!");
1311                         if (b_write) {
1312                                 gl_dbgW("to add an orientation tag!");
1313                                 fclose(fd);
1314                                 fd = NULL;
1315                                 return __gl_exif_add_orientation_tag(file_path, orientation);
1316
1317                         } else{
1318                                 /* Normal orientation = 0degree = 1 */
1319                                 *orientation = 1;
1320                                 ret = -1;
1321                         }
1322                         goto GL_EXIF_FAILED;
1323                 }
1324         }
1325
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 */
1328         if (b_write) {
1329                 gl_dbg("Write: %d", *orientation);
1330                 /* Set the Orientation value */
1331                 if (is_motorola)
1332                         tmp[9] = (unsigned char)(*orientation);
1333                 else
1334                         tmp[8] = (unsigned char)(*orientation);
1335
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;
1340                 }
1341                 fwrite(tmp, 1, 10, fd);
1342         } else {
1343                 /* Get the Orientation value */
1344                 if (is_motorola) {
1345                         if (tmp[8] != 0) {
1346                                 gl_dbgE("tmp[8] != 0");
1347                                 goto GL_EXIF_FAILED;
1348                         }
1349                         *orientation = (unsigned int)tmp[9];
1350                 } else {
1351                         if (tmp[9] != 0) {
1352                                 gl_dbgE("tmp[9] != 0");
1353                                 goto GL_EXIF_FAILED;
1354                         }
1355                         *orientation = (unsigned int)tmp[8];
1356                 }
1357                 if (*orientation > 8) {
1358                         gl_dbgE("*orient > 8");
1359                         goto GL_EXIF_FAILED;
1360                 }
1361                 gl_dbg("Read: %d", *orientation);
1362         }
1363
1364         ret = 0;
1365
1366  GL_EXIF_FAILED:
1367
1368         fclose(fd);
1369         gl_dbg("All done");
1370         return ret;
1371 }
1372 bool _gl_exif_check_img_type(char *file_path)
1373 {
1374         GL_CHECK_VAL(file_path, -1);
1375         int tmp_exif = -1;
1376         unsigned int i = 0;
1377         unsigned char exif_data[4] = { 0, };
1378         FILE *fd = NULL;
1379         bool ret = false;
1380
1381         if ((fd = fopen(file_path, "rb")) == NULL) {
1382                 gl_dbgE("Can't open %s!", file_path);
1383                 return -1;
1384         }
1385
1386
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);
1390                 if (tmp_exif < 0)
1391                         goto GL_EXIF_FAILED;
1392
1393                 exif_data[i] = (unsigned char)tmp_exif;
1394         }
1395
1396         if (exif_data[0] == GL_EXIF_TAG && exif_data[1] == GL_EXIF_SOI) {
1397                 gl_dbg("JPEG file");
1398         } else {
1399                 gl_dbgE("Not a JPEG file!");
1400                 goto GL_EXIF_FAILED;
1401         }
1402
1403         if (exif_data[2] == GL_EXIF_TAG && exif_data[3] == GL_EXIF_APP1) {
1404                 gl_dbgW("Exif in APP1!");
1405                 ret = true;
1406         } else if (exif_data[2] == GL_EXIF_TAG &&
1407                    exif_data[3] == GL_EXIF_APP0) {
1408                 gl_dbgW("Jfif in APP0!");
1409                 ret = true;
1410         } else {
1411                 gl_dbgE("Not a Exif in APP1 or Jiff in APP2[%d]!", exif_data[3]);
1412                 ret = false;
1413         }
1414  GL_EXIF_FAILED:
1415
1416         fclose(fd);
1417         gl_dbg("");
1418         return ret;
1419 }
1420
1421 static int __gl_exif_rw_orient(const char *file_path, unsigned int *orient, bool b_write)
1422 {
1423         GL_CHECK_VAL(file_path, -1);
1424         gl_dbg("b_write: %d", b_write);
1425         unsigned int length = 0;
1426         unsigned int i = 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;
1432         int tmp_exif = -1;
1433         unsigned char exif_data[GL_EXIF_BUF_LEN_MAX] = { 0, };
1434         FILE *fd = NULL;
1435         int ret = -1;
1436
1437         if (b_write) {
1438                 if ((fd = fopen(file_path, "rb+")) == NULL) {
1439                         gl_dbgE("Can't open %s!", file_path);
1440                         return -1;
1441                 }
1442         } else {
1443                 if ((fd = fopen(file_path, "rb")) == NULL) {
1444                         gl_dbgE("Can't open %s!", file_path);
1445                         return -1;
1446                 }
1447         }
1448
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);
1452                 if (tmp_exif < 0)
1453                         goto GL_EXIF_FAILED;
1454
1455                 exif_data[i] = (unsigned char)tmp_exif;
1456         }
1457
1458         if (exif_data[0] == GL_EXIF_TAG && exif_data[1] == GL_EXIF_SOI) {
1459                 gl_dbg("JPEG file");
1460         } else {
1461                 gl_dbgE("Not a JPEG file!");
1462                 goto GL_EXIF_FAILED;
1463         }
1464
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);
1471                 return ret;
1472         } else {
1473                 gl_dbgE("Not a Exif in APP1 or Jiff in APP2[%d]!", exif_data[3]);
1474                 goto GL_EXIF_FAILED;
1475         }
1476
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 */
1483         if (length < 8) {
1484                 gl_dbgE("length < 8");
1485                 goto GL_EXIF_FAILED;
1486         }
1487         length -= 8;
1488
1489          /* Length of an IFD entry */
1490         if (length < 12) {
1491                 gl_dbgE("length < 12");
1492                 goto GL_EXIF_FAILED;
1493         }
1494
1495         /* Read Exif head, check for "Exif" */
1496         for (i = 0; i < 6; i++) {
1497                 tmp_exif = __gl_exif_read_1_byte(fd);
1498                 if (tmp_exif < 0)
1499                         goto GL_EXIF_FAILED;
1500
1501                 exif_data[i] = (unsigned char)tmp_exif;
1502                 gl_dbg("- %02X", exif_data[i]);
1503         }
1504
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;
1510         }
1511
1512         /* Read Exif body */
1513         for (i = 0; i < length; i++) {
1514                 tmp_exif = __gl_exif_read_1_byte(fd);
1515                 if (tmp_exif < 0)
1516                         goto GL_EXIF_FAILED;
1517                 exif_data[i] = (unsigned char)tmp_exif;
1518         }
1519
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) {
1523                 gl_dbg("Intel");
1524                 is_motorola = false;
1525         } else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D &&
1526                  exif_data[2] == 0x00 && exif_data[3] == 0x2A) {
1527                 gl_dbg("Motorola");
1528                 is_motorola = true;
1529         } else {
1530                 goto GL_EXIF_FAILED;
1531         }
1532
1533         /* Get first IFD offset (offset to IFD0) , MM-00000008, II-08000000 */
1534         if (is_motorola) {
1535                 if (exif_data[4] != 0 && exif_data[5] != 0)
1536                         goto GL_EXIF_FAILED;
1537                 offset = exif_data[6];
1538                 offset <<= 8;
1539                 offset += exif_data[7];
1540         } else {
1541                 if (exif_data[7] != 0 && exif_data[6] != 0)
1542                         goto GL_EXIF_FAILED;
1543                 offset = exif_data[5];
1544                 offset <<= 8;
1545                 offset += exif_data[4];
1546         }
1547         /* check end of data segment */
1548         if (offset > length - 2) {
1549                 gl_dbgE("offset > length - 2");
1550                 goto GL_EXIF_FAILED;
1551         }
1552
1553         /* IFD: Image File Directory */
1554         /* Get the number of directory entries contained in this IFD, - EEEE */
1555         if (is_motorola) {
1556                 tags_cnt = exif_data[offset];
1557                 tags_cnt <<= 8;
1558                 tags_cnt += exif_data[offset+1];
1559         } else {
1560                 tags_cnt = exif_data[offset+1];
1561                 tags_cnt <<= 8;
1562                 tags_cnt += exif_data[offset];
1563         }
1564         if (tags_cnt == 0) {
1565                 gl_dbgE("tags_cnt == 0 - 2");
1566                 goto GL_EXIF_FAILED;
1567         }
1568         offset += 2;
1569
1570         /* check end of data segment */
1571         if (offset > length - 12) {
1572                 gl_dbgE("offset > length - 12");
1573                 goto GL_EXIF_FAILED;
1574         }
1575
1576         /* Search for Orientation Tag in IFD0 */
1577         while (1) {
1578                 /* Get Tag number */
1579                 if (is_motorola) {
1580                         tag_num = exif_data[offset];
1581                         tag_num <<= 8;
1582                         tag_num += exif_data[offset+1];
1583                 } else {
1584                         tag_num = exif_data[offset+1];
1585                         tag_num <<= 8;
1586                         tag_num += exif_data[offset];
1587                 }
1588                 /* found Orientation Tag */
1589                 if (tag_num == 0x0112) {
1590                         gl_dbgW("Found orientation tag!");
1591                         break;
1592                 }
1593                 if (--tags_cnt == 0) {
1594                         gl_dbgW("tags_cnt == 0, no found orientation tag!");
1595                         if (b_write) {
1596                                 gl_dbgW("to add an orientation tag!");
1597                                 fclose(fd);
1598                                 fd = NULL;
1599                                 return __gl_exif_add_orientation_tag(file_path, orient);
1600
1601                         } else{
1602                                 /* Normal orientation = 0degree = 1 */
1603                                 *orient = 1;
1604                                 ret = -1;
1605                         }
1606                         goto GL_EXIF_FAILED;
1607                 }
1608
1609                 /* Every directory entry size is 12 */
1610                 offset += 12;
1611         }
1612
1613         if (b_write) {
1614                 gl_dbg("Write: %d", *orient);
1615                 /* Set the Orientation value */
1616                 if (is_motorola)
1617                         exif_data[offset+9] = (unsigned char)(*orient);
1618                 else
1619                         exif_data[offset+8] = (unsigned char)(*orient);
1620
1621                 if (fseek(fd, jfif_offset + (4 + 2 + 6 + 2) + offset, SEEK_SET) < 0) {
1622                         gl_dbgE("fseek failed!");
1623                         goto GL_EXIF_FAILED;
1624                 }
1625                 fwrite(exif_data + 2 + offset, 1, 10, fd);
1626         } else {
1627                 /* Get the Orientation value */
1628                 if (is_motorola) {
1629                         if (exif_data[offset+8] != 0) {
1630                                 gl_dbgE("exif_data[offset+8] != 0");
1631                                 goto GL_EXIF_FAILED;
1632                         }
1633                         *orient = (unsigned int)exif_data[offset+9];
1634                 } else {
1635                         if (exif_data[offset+9] != 0) {
1636                                 gl_dbgE("exif_data[offset+9] != 0");
1637                                 goto GL_EXIF_FAILED;
1638                         }
1639                         *orient = (unsigned int)exif_data[offset+8];
1640                 }
1641                 if (*orient > 8) {
1642                         gl_dbgE("*orient > 8");
1643                         goto GL_EXIF_FAILED;
1644                 }
1645                 gl_dbg("Read: %d", *orient);
1646         }
1647
1648         ret = 0;
1649
1650  GL_EXIF_FAILED:
1651
1652         fclose(fd);
1653         gl_dbg("All done");
1654         return ret;
1655 }
1656
1657
1658
1659 /* 1 : top left
1660    2 : top right
1661    3 : bottom right
1662    4 : bottom left
1663    5 : left top
1664    6 : right top
1665    7 : right bottom
1666    8 : left bottom */
1667
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)
1672
1673
1674 int ivug_exif_get_rotate(const char *file, int *degree)
1675 {
1676         MSG_ASSERT(file != NULL);
1677
1678         unsigned int orientation = 0;
1679
1680         int ret = __gl_exif_rw_orient(file, &orientation, false);
1681         if (-1 != ret && 0 != orientation)
1682         {
1683                 switch (orientation)
1684                 {
1685                 case IVUG_EXIF_ROTATE_0:
1686                         *degree = 0;
1687                         break;
1688                 case IVUG_EXIF_ROTATE_90:
1689                         *degree = 90;
1690                         break;
1691                 case IVUG_EXIF_ROTATE_180:
1692                         *degree = 180;
1693                         break;
1694                 case IVUG_EXIF_ROTATE_270:
1695                         *degree = 270;
1696                         break;
1697                 default:
1698                         *degree = 0;
1699                         gl_dbgE("Invalid Orientation : %d", orientation);
1700                         break;
1701                 }
1702
1703                 gl_dbg("Get Degree: %d' %s", *degree, file);
1704                 return 0;
1705
1706         }
1707
1708         gl_dbgE("Unknown Degree: %s", file);
1709         return -1;
1710 }
1711
1712
1713
1714 int ivug_exif_set_rotate(const char *file, int degree)
1715 {
1716         MSG_ASSERT(file != NULL);
1717
1718         gl_dbg("Set Degree: %d' %s", degree, file);
1719
1720         unsigned int orientation;
1721
1722         switch (degree){
1723         case 0:
1724         case 360:
1725                 orientation = IVUG_EXIF_ROTATE_0;
1726                 break;
1727         case 90:
1728         case -270:
1729                 orientation = IVUG_EXIF_ROTATE_90;
1730                 break;
1731         case 180:
1732         case -180:
1733                 orientation = IVUG_EXIF_ROTATE_180;
1734                 break;
1735         case 270:
1736         case -90:
1737                 orientation = IVUG_EXIF_ROTATE_270;
1738                 break;
1739         default:
1740                 orientation = IVUG_EXIF_ROTATE_0;;
1741                 gl_dbgE("Invalid Degree : %d", degree);
1742                 break;
1743         }
1744
1745         int ret = __gl_exif_rw_orient(file, &orientation, true);
1746
1747         return ret;
1748 }
1749