a1a2f2e51ae606d8eaacb6fc4fe72ad77abbcc2c
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_exifinfo.c
1 /*
2  * libmm-camcorder
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jeongmo Yang <jm80.yang@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21  
22 #include "mm_camcorder_exifinfo.h"
23 #include "mm_camcorder_exifdef.h"
24
25 #include <libexif/exif-loader.h>
26 #include <libexif/exif-utils.h>
27 #include <libexif/exif-data.h>
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <time.h>
32 #include <mm_debug.h>
33 #include <mm_error.h>
34 #include <glib.h>
35
36 #define MM_EXIFINFO_USE_BINARY_EXIFDATA         1
37 #define JPEG_MAX_SIZE 20000000
38 #define JPEG_THUMBNAIL_MAX_SIZE (128*1024)
39 #if MM_EXIFINFO_USE_BINARY_EXIFDATA
40 /**
41  * Exif Binary Data.
42  */
43 #include <string.h>
44 #define _EXIF_BIN_SIZE_         ((unsigned int)174)
45 unsigned char g_exif_bin [_EXIF_BIN_SIZE_] = {
46    0x45 , 0x78 , 0x69 , 0x66 , 0x00 , 0x00 , 0x49 , 0x49 , 0x2a , 0x00 , 0x08 , 0x00 , 0x00 , 0x00 , 0x05 , 0x00
47  , 0x1a , 0x01 , 0x05 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x4a , 0x00 , 0x00 , 0x00 , 0x1b , 0x01 , 0x05 , 0x00
48  , 0x01 , 0x00 , 0x00 , 0x00 , 0x52 , 0x00 , 0x00 , 0x00 , 0x28 , 0x01 , 0x03 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
49  , 0x02 , 0x00 , 0x00 , 0x00 , 0x13 , 0x02 , 0x03 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
50  , 0x69 , 0x87 , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x5a , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
51  , 0x48 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x48 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
52  , 0x06 , 0x00 , 0x00 , 0x90 , 0x07 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x30 , 0x32 , 0x31 , 0x30 , 0x01 , 0x91
53  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xa0 , 0x07 , 0x00 , 0x04 , 0x00
54  , 0x00 , 0x00 , 0x30 , 0x31 , 0x30 , 0x30 , 0x01 , 0xa0 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
55  , 0x00 , 0x00 , 0x02 , 0xa0 , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x03 , 0xa0
56  , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
57 };
58 #endif
59
60 /**
61  * Structure for exif entry.
62  */
63 typedef struct  _mm_exif_entry_t
64 {
65         ExifTag                 tag;                    /**< exif tag*/
66         ExifFormat              format;                 /**< exif format*/
67         unsigned long   components;             /**< number of components*/
68         unsigned char   *data;                  /**< data*/
69         unsigned int    size;                   /**< size of data*/
70 } mm_exif_entry_type;
71
72
73 /**
74  * local functions.
75  */
76 static void
77 _exif_set_uint16 (int is_motorola, void * out, unsigned short in)
78 {
79         if (is_motorola) {
80                 ((unsigned char *)out)[0] = in & 0x00ff;
81                 ((unsigned char *)out)[1] = in >> 8;
82         } else {
83                 ((unsigned char *)out)[0] = in >> 8;
84                 ((unsigned char *)out)[1] = in & 0x00ff;
85         }
86 }
87
88
89 static unsigned long
90 _exif_get_jpeg_marker_offset (void *jpeg, int jpeg_size, unsigned short marker)
91 {
92         unsigned char   *p = NULL;
93         unsigned char   *src = jpeg;
94         int                             src_sz = jpeg_size;
95         unsigned char   m[2];
96         unsigned long   ret;
97         int i;
98
99         // mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
100
101         m[0] = marker >> 8;
102         m[1] = marker & 0x00FF;
103
104         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s] marker: 0x%02X 0x%02X\n\n", __LINE__, __func__,m[0], m[1]);
105
106         if (*src == 0xff && *(src + 1) == 0xd8) 
107         {
108                 p = src + 2; /* SOI(start of image) */
109         } 
110         else 
111         {
112                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid JPEG file.\n", __LINE__, __func__);
113                 return 0UL;
114         }
115
116         for (i = 0; i < src_sz - (1 + 2); i++, p++) 
117         {
118                 if (*p == 0xff) 
119                 {
120                         /*marker is 0xFFxx*/
121                         if (*(p + 1) == m[1]) 
122                         {
123                                 ret = p - src;
124                                 mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]marker offset: %lu %p %p.\n", __LINE__, __func__,ret, (p+1), src);
125                                 return ret;
126                         }
127                 } 
128         }
129         mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]Marker not found.\n", __LINE__, __func__);
130         return 0UL;
131 }
132
133
134 ExifData*
135 mm_exif_get_exif_data_from_data (mm_exif_info_t *info)
136 {
137         ExifData                *ed = NULL;
138
139         //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
140
141         ed = exif_data_new_from_data(info->data, info->size);
142         if( ed == NULL )
143         {
144                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]Null exif data. (ed:%p)\n", __LINE__, __func__, ed);
145         }
146
147         return ed;
148 }
149
150
151 ExifData*
152 mm_exif_get_exif_from_info (mm_exif_info_t *info)
153 {
154         ExifData                *ed = NULL;
155         ExifLoader              *loader = NULL;
156
157         unsigned char   size[2];
158         unsigned int    i;
159
160         //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
161         
162         /*get ExifData from info*/
163         loader = exif_loader_new ();
164
165         size[0] = (unsigned char) (info->size);
166         size[1] = (unsigned char) (info->size >> 8);
167         exif_loader_write (loader, size, 2);
168
169         for (i = 0; i < info->size && exif_loader_write (loader, info->data + i, 1); i++);
170
171         ed = exif_loader_get_data (loader);
172         exif_loader_unref (loader);
173         return ed;
174 }
175
176
177 int
178 mm_exif_set_exif_to_info (mm_exif_info_t *info, ExifData *exif)
179 {
180         unsigned char   *eb = NULL;
181         unsigned int    ebs;
182
183         if (!exif)
184         {
185                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]exif Null\n", __LINE__, __func__);
186                 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
187         }
188
189         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]exif(ifd :%p)\n", __LINE__, __func__, exif->ifd);
190
191         if(info->data)
192         {
193                 free (info->data); 
194                 info->data = NULL; 
195                 info->size = 0; 
196         }
197
198         exif_data_save_data (exif, &eb, &ebs);
199         if(eb==NULL)
200         {
201                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]MM_ERROR_CAMCORDER_LOW_MEMORY\n", __LINE__, __func__);
202                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
203         }
204         info->data = eb;
205         info->size = ebs;
206         return MM_ERROR_NONE;
207 }
208
209
210 int
211 mm_exif_set_add_entry (ExifData *exif, ExifIfd ifd, ExifTag tag,ExifFormat format,unsigned long components,unsigned char* data)
212 {
213 //      mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
214         ExifData                *ed = (ExifData *)exif;
215         ExifEntry               *e = NULL;
216
217         if(exif==NULL || format<=0 || components<=0 || data==NULL)
218         {
219                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p format=%d, components=%lu data=%p!\n", __LINE__, __func__,exif,format,components,data);
220                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
221         }
222         /*remove same tag in EXIF*/
223         exif_content_remove_entry (ed->ifd[ifd], exif_content_get_entry(ed->ifd[ifd], tag));
224         /*create new tag*/
225         e = exif_entry_new ();
226         if(e==NULL)
227         {
228                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] entry create error!\n", __LINE__, __func__);
229                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
230         }
231         exif_entry_initialize (e, tag);
232
233         e->tag                  = tag;
234         e->format               = format;
235         e->components   = components;
236
237         if(e->size==0)
238         {
239                 e->data=NULL;
240                 e->data=malloc(exif_format_get_size(format)*e->components);
241                 if(!e->data)
242                 {
243                         exif_entry_unref(e);
244                         return MM_ERROR_CAMCORDER_LOW_MEMORY;
245                 }
246                 if(format==EXIF_FORMAT_ASCII)
247                         memset (e->data, '\0', exif_format_get_size(format)*e->components);
248         }
249         e->size                 = exif_format_get_size(format)*e->components;
250         memcpy(e->data,data,e->size);
251         exif_content_add_entry (ed->ifd[ifd], e);
252         exif_entry_unref(e);
253
254         return MM_ERROR_NONE;
255 }
256
257
258
259
260 /**
261  * global functions.
262  */
263
264
265 int
266 mm_exif_create_exif_info (mm_exif_info_t **info)
267 {
268         mm_exif_info_t  *x = NULL;
269 #if (MM_EXIFINFO_USE_BINARY_EXIFDATA == 0)
270         ExifData                        *ed = NULL;
271         unsigned char           *eb = NULL;
272         unsigned int            ebs;
273 #endif
274
275         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
276
277         x = malloc (sizeof (mm_exif_info_t));
278        if(!x)
279        {
280                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]malloc error\n", __LINE__, __func__);
281                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
282        }
283 #if MM_EXIFINFO_USE_BINARY_EXIFDATA
284         x->data=NULL; 
285         x->data = malloc (_EXIF_BIN_SIZE_);
286        if(!x->data)
287        {
288                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]malloc error\n", __LINE__, __func__);
289                 free(x);
290                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
291        }
292         memcpy (x->data, g_exif_bin, _EXIF_BIN_SIZE_);
293         x->size = _EXIF_BIN_SIZE_;
294 #else
295         ed = exif_data_new ();
296        if(!ed )
297        {
298                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]exif data new error\n", __LINE__, __func__);
299                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
300        }
301                 
302         exif_data_set_byte_order        (ed, EXIF_BYTE_ORDER_INTEL);
303         exif_data_set_data_type         (ed, EXIF_DATA_TYPE_COMPRESSED);
304         exif_data_set_option            (ed, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
305
306         exif_data_fix (ed);
307
308         exif_data_save_data (ed, &eb, &ebs);
309        if(eb==NULL)
310        {
311                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]exif_data_save_data error\n", __LINE__, __func__);
312                 free(x->data);
313                 free(x);
314                 exif_data_unref (ed);
315                 return MM_ERROR_CAMCORDER_INTERNAL;
316        }        
317         exif_data_unref (ed);
318
319         x->data = eb;
320         x->size = ebs;
321 #endif
322
323         *info = x;
324
325         //mmf_debug (MMF_DEBUG_LOG, "%s() Data:%p Size:%d\n", __func__, x->data, x->size); 
326
327         return MM_ERROR_NONE;
328 }
329
330 void
331 mm_exif_destory_exif_info (mm_exif_info_t *info)
332 {
333         //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
334
335 #if MM_EXIFINFO_USE_BINARY_EXIFDATA
336         if (info) {
337                 if (info->data) 
338                         free (info->data);
339                 free (info);
340         }
341 #else
342         if (info) {
343                 if (info->data) 
344                         exif_mem_free (info->data);
345                 free (info);
346         }
347 #endif
348 }
349
350
351 int
352 mm_exif_add_thumbnail_info (mm_exif_info_t *info, void *thumbnail, int width, int height, int len)
353 {
354         ExifData *ed = NULL;
355         static ExifLong elong[10];
356
357         unsigned char *p_compressed = NULL;
358         int ret = MM_ERROR_NONE;
359         int cntl = 0;
360
361         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s] Thumbnail size:%d, width:%d, height:%d\n", __LINE__, __func__, len, width, height);
362
363         if( len > JPEG_THUMBNAIL_MAX_SIZE )
364         {
365                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] Thumbnail size[%d] over!!! Skip inserting thumbnail...\n", __LINE__, __func__, len);
366                 return MM_ERROR_NONE;
367         }
368
369         /* get ExifData from info*/
370         ed = mm_exif_get_exif_from_info(info);
371         ed->data=thumbnail;
372         ed->size = len;
373
374         /* set thumbnail data */
375         p_compressed = malloc(sizeof(ExifShort));
376         if (p_compressed != NULL) {
377                 exif_set_short(p_compressed, exif_data_get_byte_order(ed), 6);
378                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_COMPRESSION, EXIF_FORMAT_SHORT, 1, p_compressed);
379                 if (ret != MM_ERROR_NONE) {
380                         goto exit;
381                 }
382         } else {
383                 ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
384                 goto exit;
385         }
386
387         /* set thumbnail size */
388         exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), width);
389         ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_IMAGE_WIDTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++]);
390         if (ret != MM_ERROR_NONE) {
391                 goto exit;
392         }
393         exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), height);
394         ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_IMAGE_LENGTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++]);
395         if (ret != MM_ERROR_NONE) {
396                 goto exit;
397         }
398
399         ret = mm_exif_set_exif_to_info (info, ed);
400         if (ret != MM_ERROR_NONE) {
401                 goto exit;
402         }
403         
404         ed->data = NULL;
405         ed->size = 0;
406         exif_data_unref (ed);   
407
408 exit :
409         if(p_compressed != NULL)
410                 free(p_compressed);
411         return ret;
412 }
413
414
415 int mm_exif_mnote_create (ExifData *exif)
416 {
417         ExifData* ed = exif;
418         ExifDataOption o = 0;
419         if(!ed){
420                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p \n", __LINE__, __func__,ed);
421                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
422         }
423
424         if(!exif_data_mnote_data_new(ed, MAKER_SAMSUNG,  o )){
425                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_mnote_data_samsung_new() failed. \n", __LINE__, __func__);
426                 return MM_ERROR_CAMCORDER_MNOTE_CREATION;
427         }
428
429         return MM_ERROR_NONE;
430 }
431
432
433 int mm_exif_mnote_set_add_entry (ExifData *exif, MnoteSamsungTag tag, int index, int subindex1, int subindex2)
434 {
435         ExifData *ed = exif;
436         ExifMnoteData *md;
437
438         ExifShort product_id = 32768;   //should be modified
439         char serialNum[] = "SerialNum123"; //should be modified
440
441         if(!ed){
442                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p \n", __LINE__, __func__,ed);
443                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
444         }
445
446         md = exif_data_get_mnote_data (ed);
447         if(!md){
448                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_get_mnote_data() failed. \n", __LINE__, __func__);
449                 return MM_ERROR_CAMCORDER_MNOTE_CREATION;
450         }
451
452         if(!exif_data_mnote_set_mem_for_adding_entry(md, MAKER_SAMSUNG)){
453                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_mem_for_adding_entry() failed. \n", __LINE__, __func__);
454                 return MM_ERROR_CAMCORDER_MNOTE_MALLOC;
455         }
456
457         exif_mnote_data_set_byte_order(md, (ExifByteOrder) exif_data_get_data_order(ed));
458
459         switch(tag){
460                 case MNOTE_SAMSUNG_TAG_MNOTE_VERSION:
461                         if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_UNDEFINED, 4, index)){
462                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
463                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
464                         }
465                         break;
466                 case MNOTE_SAMSUNG_TAG_DEVICE_ID:
467                         if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
468                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
469                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
470                         }
471                         break;
472                 case MNOTE_SAMSUNG_TAG_MODEL_ID:
473                         if(!exif_data_mnote_set_add_entry_subtag(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, MNOTE_SAMSUNG_SUBTAG_MODEL_ID_CLASS, subindex1, MNOTE_SAMSUNG_SUBTAG_MODEL_ID_DEVEL, subindex2, product_id )){
474                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry_subtag() failed. \n", __LINE__, __func__);
475                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
476                         }       
477                         break;
478                 case MNOTE_SAMSUNG_TAG_COLOR_INFO:
479                 case MNOTE_SAMSUNG_TAG_SERIAL_NUM:
480                         if(!exif_data_mnote_set_add_entry_string(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_ASCII, strlen(serialNum), serialNum)){
481                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry_string() failed. \n", __LINE__, __func__);
482                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
483                         }
484                         break;
485                 case MNOTE_SAMSUNG_TAG_IMAGE_COUNT:
486                 case MNOTE_SAMSUNG_TAG_GPS_INFO01:
487                 case MNOTE_SAMSUNG_TAG_GPS_INFO02:
488                 case MNOTE_SAMSUNG_TAG_PREVIEW_IMAGE:
489                 case MNOTE_SAMSUNG_TAG_FAVOR_TAGGING:
490                 case MNOTE_SAMSUNG_TAG_SRW_COMPRESS:
491                 case MNOTE_SAMSUNG_TAG_COLOR_SPACE:
492                         if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
493                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
494                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
495                         }
496                         break;
497                 case MNOTE_SAMSUNG_TAG_AE:
498                 case MNOTE_SAMSUNG_TAG_AF:
499                 case MNOTE_SAMSUNG_TAG_AWB01:
500                 case MNOTE_SAMSUNG_TAG_AWB02:
501                 case MNOTE_SAMSUNG_TAG_IPC:
502                 case MNOTE_SAMSUNG_TAG_SCENE_RESULT:
503                 case MNOTE_SAMSUNG_TAG_SADEBUG_INFO01:
504                 case MNOTE_SAMSUNG_TAG_SADEBUG_INFO02:
505                 case MNOTE_SAMSUNG_TAG_FACE_DETECTION:
506                         if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
507                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
508                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
509                         }
510                         break;
511                 case MNOTE_SAMSUNG_TAG_FACE_FEAT01:
512                 case MNOTE_SAMSUNG_TAG_FACE_FEAT02:
513                 case MNOTE_SAMSUNG_TAG_FACE_RECOG:
514                 case MNOTE_SAMSUNG_TAG_LENS_INFO:
515                 case MNOTE_SAMSUNG_TAG_THIRDPARTY:
516                         break;
517                 default:
518                         break;
519         }
520         return MM_ERROR_NONE;
521 }
522
523
524 int
525 mm_exif_write_exif_jpeg_to_file (char *filename, mm_exif_info_t *info,  void *jpeg, int jpeg_len)
526 {
527         FILE                    *fp = NULL;
528         unsigned long   offset_jpeg_start;
529         unsigned short  head[2]={0,};
530         unsigned short  head_len=0;
531         unsigned char   *eb = NULL;
532         unsigned int    ebs;
533
534         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
535
536         eb = info->data;
537         ebs = info->size;
538
539         /*get DQT*/
540         offset_jpeg_start = _exif_get_jpeg_marker_offset (jpeg, jpeg_len, 0xffdb);
541         if (offset_jpeg_start == 0) {
542                 return -1;
543         }
544
545         /*create file*/
546         fp = fopen (filename, "wb");
547         if (!fp) {
548                 mmf_debug (MMF_DEBUG_ERROR, "%s(), fopen() failed [%s].\n", __func__, filename);
549                 return MM_ERROR_IMAGE_FILEOPEN;
550         }
551
552         /*set SOI, APP1*/
553         _exif_set_uint16 (0, &head[0], 0xffd8);
554         _exif_set_uint16 (0, &head[1], 0xffe1);
555         /*set header length*/
556         _exif_set_uint16 (0, &head_len, (unsigned short)(ebs + 2));
557         
558         if(head[0]==0 || head[1]==0 || head_len==0)
559         {
560                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]setting error\n", __LINE__, __func__);
561                 fclose (fp);
562                 return -1;
563         }
564         
565         fwrite (&head[0], 1, 2, fp);                    /*SOI marker*/
566         fwrite (&head[1], 1, 2, fp);                    /*APP1 marker*/
567         fwrite (&head_len, 1, 2, fp);                   /*length of APP1*/
568         fwrite (eb, 1, ebs, fp);                                /*EXIF*/
569         fwrite (jpeg + offset_jpeg_start, 1, jpeg_len - offset_jpeg_start, fp); /*IMAGE*/
570
571         fclose (fp);
572
573         return MM_ERROR_NONE;
574 }
575
576 int
577 mm_exif_write_exif_jpeg_to_memory (void **mem, unsigned int *length, mm_exif_info_t *info,  void *jpeg, unsigned int jpeg_len)
578 {
579         /*output*/
580         unsigned char   *m = NULL;
581         int                             m_len = 0;      
582         /**/
583         unsigned long   offset_jpeg_start;
584         unsigned short  head[2]={0,};
585         unsigned short  head_len=0;
586         unsigned char   *eb = NULL;
587         unsigned int    ebs;
588         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
589
590         if(info==NULL || jpeg==NULL)
591         {
592                 mmf_debug (MMF_DEBUG_ERROR, "%s(), MM_ERROR_CAMCORDER_INVALID_ARGUMENT info=%p, jpeg=%p\n", __func__,info,jpeg);
593                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
594         }
595
596         if(jpeg_len>JPEG_MAX_SIZE)
597         {
598                 mmf_debug (MMF_DEBUG_ERROR, "%s(),jpeg_len is worng jpeg_len=%d\n", __func__,jpeg_len);
599                 return MM_ERROR_CAMCORDER_DEVICE_WRONG_JPEG;    
600         }
601
602         eb = info->data;
603         ebs = info->size;
604         /*get DQT*/
605         offset_jpeg_start = _exif_get_jpeg_marker_offset (jpeg, (int)jpeg_len, 0xffdb);
606         if (offset_jpeg_start == 0) {
607                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
608         }
609
610         /*length of output image*/
611         /*SOI + APP1 + length of APP1 + length of EXIF + IMAGE*/
612         m_len = 2 + 2 + 2 + ebs + (jpeg_len - offset_jpeg_start);
613         /*alloc output image*/
614         m = malloc (m_len);
615         if (!m) {
616                 mmf_debug (MMF_DEBUG_ERROR, "%s(), malloc() failed.\n", __func__);
617                 return MM_ERROR_CAMCORDER_LOW_MEMORY;   
618         }
619
620         /*set SOI, APP1*/
621         _exif_set_uint16 (0, &head[0], 0xffd8);
622         _exif_set_uint16 (0, &head[1], 0xffe1);
623         /*set header length*/
624         _exif_set_uint16 (0, &head_len, (unsigned short)(ebs + 2));
625         if(head[0]==0 || head[1]==0 || head_len==0)
626         {
627                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]setting error\n", __LINE__, __func__);
628                 free(m);
629                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
630         }       
631         memcpy (m,                                              &head[0],                                       2);     /*SOI marker*/
632         memcpy (m + 2,                                  &head[1],                                       2);     /*APP1 marker*/
633         memcpy (m + 2 + 2,                              &head_len,                                      2);     /*length of APP1*/
634         memcpy (m + 2 + 2 + 2,                  eb,                                                     ebs);   /*EXIF*/
635         memcpy (m + 2 + 2 + 2 + ebs,    jpeg + offset_jpeg_start,       jpeg_len - offset_jpeg_start);  /*IMAGE*/
636
637         /*set ouput param*/
638         *mem    = m;
639         *length = m_len;
640
641         return MM_ERROR_NONE;
642 }