Flora license update
[apps/core/preloaded/ug-camera-efl.git] / src / cam_exif_info.c
1 /*\r
2  * Copyright 2012  Samsung Electronics Co., Ltd\r
3  *\r
4  * Licensed under the Flora License, Version 1.1 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *        http://floralicense.org/license/\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 \r
18 #include "cam_debug.h"\r
19 #include "cam_exif_info.h"\r
20 #include <libexif/exif-loader.h>\r
21 #include <string.h>\r
22 \r
23 \r
24 \r
25 //#include <libexif/exif-data.h>\r
26 \r
27 static void _set_uint16 (int is_motorola, void * out, unsigned short in)\r
28 {\r
29         if (is_motorola) {\r
30                 ((unsigned char *)out)[0] = in & 0x00ff;\r
31                 ((unsigned char *)out)[1] = in >> 8;\r
32         } else {\r
33                 ((unsigned char *)out)[0] = in >> 8;\r
34                 ((unsigned char *)out)[1] = in & 0x00ff;\r
35         }\r
36 }\r
37 \r
38 \r
39 ExifData* cam_exif_get_exif_from_data(unsigned char *data, unsigned int data_size)\r
40 {\r
41         ExifData *exif = NULL;\r
42         ExifLoader *loader = NULL;\r
43         unsigned char size[2];\r
44         unsigned int i;\r
45 \r
46         loader = exif_loader_new();\r
47 \r
48         if (loader != NULL) {\r
49                 size[0] = (unsigned char) (data_size);\r
50                 size[1] = (unsigned char) (data_size >> 8);\r
51                 exif_loader_write (loader, size, 2);\r
52 \r
53                 for (i = 0; i < data_size && exif_loader_write (loader, data + i, 1); i++);\r
54 \r
55                 exif = exif_loader_get_data (loader);\r
56                 if (exif == NULL)\r
57                         cam_critical(LOG_CAM, "exif_loader_get_data() fail");\r
58 \r
59                 exif_loader_unref (loader);\r
60 \r
61         } else\r
62                 cam_critical(LOG_CAM, "exif_loader_new() fail");\r
63 \r
64         return exif;\r
65 }\r
66 \r
67 gboolean cam_exif_set_entry(ExifData *in_exif, ExifIfd ifd, ExifTag tag, ExifFormat format, unsigned long components, unsigned char *data)\r
68 {\r
69         ExifData *exif = (ExifData *)in_exif;\r
70         ExifEntry *entry = NULL;\r
71
72         if (in_exif == NULL || format <= 0 || components <= 0 || data == NULL) {\r
73                 cam_critical(LOG_CAM, "invalid input!! (exif:%p format:%d component=%lu data:%p)", in_exif, format, components, data);\r
74                 return FALSE;\r
75         }\r
76
77         exif_content_remove_entry(exif->ifd[ifd], exif_content_get_entry(exif->ifd[ifd], tag));\r
78
79         entry = exif_entry_new();\r
80         if (entry == NULL) {\r
81                 cam_critical(LOG_CAM, "exif_entry_new() return NULL");\r
82                 return FALSE;\r
83         }\r
84
85         exif_entry_initialize(entry, tag);\r
86
87         entry->tag = tag;\r
88         entry->format = format;\r
89         entry->components = components;\r
90
91         if (entry->size == 0) {\r
92                 entry->data = NULL;\r
93                 entry->data = malloc(exif_format_get_size(format) * entry->components);\r
94                 if (!entry->data) {\r
95                         exif_entry_unref(entry);\r
96                         cam_critical(LOG_CAM, "entry->data malloc fail");\r
97                         return FALSE;\r
98                 }
99
100                 if (format == EXIF_FORMAT_ASCII) {
101                         memset(entry->data, '\0', exif_format_get_size(format) * entry->components);\r
102                 }
103         }
104
105         entry->size = exif_format_get_size(format) * entry->components;\r
106         memcpy(entry->data,data,entry->size);\r
107         exif_content_add_entry(exif->ifd[ifd], entry);\r
108         exif_entry_unref(entry);\r
109
110         return TRUE;\r
111 \r
112 \r
113 }\r
114 \r
115 gboolean cam_exif_get_data_from_exif(unsigned char *out_data, unsigned int out_size, ExifData *in_exif)\r
116 {\r
117         unsigned char *exif_raw = NULL;\r
118         unsigned int size = 0;\r
119 \r
120         if (in_exif == NULL) {\r
121                 cam_critical(LOG_CAM, "in_exif is NULL");\r
122                 return FALSE;\r
123         }\r
124 \r
125         cam_debug(LOG_CAM, "exif->ifd:%p", in_exif->ifd);\r
126 \r
127         exif_data_save_data(in_exif, &exif_raw, &size);\r
128 \r
129         if (exif_raw == NULL) {\r
130                 cam_critical(LOG_CAM, "exif_data_save_data() is fail");\r
131                 return FALSE;\r
132         }\r
133 \r
134         if (out_data) {\r
135                 free (out_data);\r
136                 out_data = NULL;\r
137                 out_size = 0;\r
138         }\r
139 \r
140         out_data = exif_raw;\r
141         out_size = size;\r
142 \r
143         return TRUE;\r
144 \r
145 }\r
146 \r
147 gboolean cam_exif_change_thumb_info(unsigned char *exif_raw, unsigned int exif_raw_size, unsigned char *thumb_data\r
148                                                                                         , int thumb_w, int thumb_h, unsigned int thumb_size)\r
149 {\r
150         ExifData *exif = NULL;\r
151         static ExifLong elong[10];\r
152 \r
153         unsigned char *p_compressed = NULL;\r
154         int cntl = 0;\r
155 \r
156         exif = cam_exif_get_exif_from_data(exif_raw, exif_raw_size);\r
157         exif->data = thumb_data;\r
158         exif->size = thumb_size;\r
159 \r
160         // set thumbnail data\r
161         p_compressed = malloc(sizeof(ExifShort));\r
162         if (p_compressed != NULL) {\r
163                 exif_set_short(p_compressed, exif_data_get_byte_order(exif), 6);\r
164 \r
165                 if (!cam_exif_set_entry(exif, EXIF_IFD_1, EXIF_TAG_COMPRESSION, EXIF_FORMAT_SHORT, 1, p_compressed)) {\r
166                         cam_critical(LOG_CAM, "cam_exif_set_entry(tag:EXIF_TAG_COMPRESSION) fail");\r
167                         goto exit;\r
168                 }\r
169         } else {\r
170                 cam_critical(LOG_CAM, "p_compressed is NULL");\r
171                 goto exit;\r
172         }\r
173 \r
174         // set thumbnail size\r
175         exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(exif), thumb_w);\r
176         if( !cam_exif_set_entry(exif, EXIF_IFD_1, EXIF_TAG_IMAGE_WIDTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++])) {\r
177                 cam_critical(LOG_CAM, "cam_exif_set_entry(tag:EXIF_TAG_IMAGE_WIDTH) fail");\r
178                 goto exit;\r
179         }\r
180         exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(exif), thumb_h);\r
181         if (!cam_exif_set_entry(exif, EXIF_IFD_1, EXIF_TAG_IMAGE_LENGTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++])) {\r
182                 cam_critical(LOG_CAM, "cam_exif_set_entry(tag:EXIF_TAG_IMAGE_LENGTH) fail");\r
183                 goto exit;\r
184         }\r
185 \r
186         cam_debug(LOG_CAM, "exif:%p exif_size:%d", exif, exif->size);\r
187 \r
188         if (!cam_exif_get_data_from_exif (exif_raw, exif_raw_size, exif)) {\r
189                 cam_critical(LOG_CAM, "cam_exif_get_data_from_exif() fail");\r
190                 goto exit;\r
191         }\r
192 \r
193         exif->data = NULL;\r
194         exif->size = 0;\r
195         exif_data_unref (exif);\r
196 \r
197         if(p_compressed != NULL)\r
198                 free(p_compressed);\r
199         p_compressed = NULL;\r
200 \r
201         return TRUE;\r
202 \r
203         exit :\r
204         if(p_compressed != NULL)\r
205                 free(p_compressed);\r
206         p_compressed = NULL;\r
207 \r
208         return FALSE;\r
209 \r
210 }\r
211 \r
212 gboolean cam_exif_write_to_jpeg(unsigned char *in_data, unsigned int in_size, unsigned char *exif_data, unsigned int exif_size\r
213                                                                                   ,unsigned char **out_data, unsigned int *out_size)\r
214 {\r
215         unsigned char *data = NULL;\r
216         int data_size = 0;\r
217         unsigned short head[2] = {0,};\r
218         unsigned short head_len = 0;\r
219 \r
220         data_size = 2 + 2 + 2 + exif_size + (in_size - 2);\r
221 \r
222         data = (unsigned char*)malloc(sizeof(unsigned char)*data_size);\r
223         if (!data) {\r
224                 cam_critical(LOG_SYS, "alloc fail");\r
225                 goto exit;\r
226         }\r
227 \r
228         _set_uint16(0, &head[0], 0xffd8);\r
229         _set_uint16(0, &head[1], 0xffe1);\r
230         _set_uint16(0, &head_len, (unsigned short)(exif_size + 2));\r
231 \r
232 \r
233         if (head[0] == 0 || head[1] == 0 || head_len == 0) {\r
234                 cam_critical(LOG_SYS, "set header fail");\r
235                 goto exit;\r
236         }\r
237 \r
238         // Complete JPEG+EXIF //\r
239         // SOI marker //\r
240         memcpy(data, &head[0], 2);\r
241 \r
242         //APP1 marker\r
243         memcpy(data + 2, &head[1], 2);\r
244         //length of APP1\r
245         memcpy(data + 2 + 2, &head_len, 2);\r
246         //EXIF\r
247         memcpy(data + 2 + 2 + 2, exif_data, exif_size);\r
248         //IMAGE\r
249         memcpy(data + 2 + 2 + 2 + exif_size, in_data + 2, in_size - 2);\r
250 \r
251         if (data != NULL) {\r
252                 *out_data = data;\r
253                 *out_size = data_size;\r
254         }\r
255 \r
256         return TRUE;\r
257 \r
258         exit:\r
259                 if (data)\r
260                         free(data);\r
261                 data = NULL;\r
262                 return FALSE;\r
263 \r
264 }\r