4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jeongmo Yang <jm80.yang@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include "mm_camcorder_exifinfo.h"
23 #include "mm_camcorder_exifdef.h"
25 #include <libexif/exif-loader.h>
26 #include <libexif/exif-utils.h>
27 #include <libexif/exif-data.h>
36 #define MM_EXIFINFO_USE_BINARY_EXIFDATA 1
37 #define JPEG_MAX_SIZE 20000000
38 #define JPEG_THUMBNAIL_MAX_SIZE (128*1024)
39 #define JPEG_DATA_OFFSET 2
40 #define EXIF_MARKER_SOI_LENGTH 2
41 #define EXIF_MARKER_APP1_LENGTH 2
42 #define EXIF_APP1_LENGTH 2
44 #if MM_EXIFINFO_USE_BINARY_EXIFDATA
49 #define _EXIF_BIN_SIZE_ ((unsigned int)174)
50 unsigned char g_exif_bin [_EXIF_BIN_SIZE_] = {
51 0x45 , 0x78 , 0x69 , 0x66 , 0x00 , 0x00 , 0x49 , 0x49 , 0x2a , 0x00 , 0x08 , 0x00 , 0x00 , 0x00 , 0x05 , 0x00
52 , 0x1a , 0x01 , 0x05 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x4a , 0x00 , 0x00 , 0x00 , 0x1b , 0x01 , 0x05 , 0x00
53 , 0x01 , 0x00 , 0x00 , 0x00 , 0x52 , 0x00 , 0x00 , 0x00 , 0x28 , 0x01 , 0x03 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
54 , 0x02 , 0x00 , 0x00 , 0x00 , 0x13 , 0x02 , 0x03 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
55 , 0x69 , 0x87 , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x5a , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
56 , 0x48 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x48 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
57 , 0x06 , 0x00 , 0x00 , 0x90 , 0x07 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x30 , 0x32 , 0x31 , 0x30 , 0x01 , 0x91
58 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xa0 , 0x07 , 0x00 , 0x04 , 0x00
59 , 0x00 , 0x00 , 0x30 , 0x31 , 0x30 , 0x30 , 0x01 , 0xa0 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
60 , 0x00 , 0x00 , 0x02 , 0xa0 , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x03 , 0xa0
61 , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
66 * Structure for exif entry.
68 typedef struct _mm_exif_entry_t
70 ExifTag tag; /**< exif tag*/
71 ExifFormat format; /**< exif format*/
72 unsigned long components; /**< number of components*/
73 unsigned char *data; /**< data*/
74 unsigned int size; /**< size of data*/
82 _exif_set_uint16 (int is_motorola, void * out, unsigned short in)
85 ((unsigned char *)out)[0] = in & 0x00ff;
86 ((unsigned char *)out)[1] = in >> 8;
88 ((unsigned char *)out)[0] = in >> 8;
89 ((unsigned char *)out)[1] = in & 0x00ff;
94 #ifdef _MMCAMCORDER_EXIF_GET_JPEG_MARKER_OFFSET
96 _exif_get_jpeg_marker_offset (void *jpeg, int jpeg_size, unsigned short marker)
98 unsigned char *p = NULL;
99 unsigned char *src = jpeg;
100 int src_sz = jpeg_size;
105 // mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
108 m[1] = marker & 0x00FF;
110 mmf_debug (MMF_DEBUG_LOG,"[%05d][%s] marker: 0x%02X 0x%02X\n\n", __LINE__, __func__,m[0], m[1]);
112 if (*src == 0xff && *(src + 1) == 0xd8)
114 p = src + 2; /* SOI(start of image) */
118 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid JPEG file.\n", __LINE__, __func__);
122 for (i = 0; i < src_sz - (1 + 2); i++, p++)
127 if (*(p + 1) == m[1])
130 mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]marker offset: %lu %p %p.\n", __LINE__, __func__,ret, (p+1), src);
135 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]Marker not found.\n", __LINE__, __func__);
138 #endif /* _MMCAMCORDER_EXIF_GET_JPEG_MARKER_OFFSET */
142 mm_exif_get_exif_data_from_data (mm_exif_info_t *info)
146 //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
148 ed = exif_data_new_from_data(info->data, info->size);
151 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]Null exif data. (ed:%p)\n", __LINE__, __func__, ed);
159 mm_exif_get_exif_from_info (mm_exif_info_t *info)
162 ExifLoader *loader = NULL;
164 unsigned char size[2];
167 //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
169 /*get ExifData from info*/
170 loader = exif_loader_new ();
172 size[0] = (unsigned char) (info->size);
173 size[1] = (unsigned char) (info->size >> 8);
174 exif_loader_write (loader, size, 2);
176 for (i = 0; i < info->size && exif_loader_write (loader, info->data + i, 1); i++);
178 ed = exif_loader_get_data (loader);
179 exif_loader_unref (loader);
185 mm_exif_set_exif_to_info (mm_exif_info_t *info, ExifData *exif)
187 unsigned char *eb = NULL;
192 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]exif Null\n", __LINE__, __func__);
193 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
196 mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]exif(ifd :%p)\n", __LINE__, __func__, exif->ifd);
205 exif_data_save_data (exif, &eb, &ebs);
208 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]MM_ERROR_CAMCORDER_LOW_MEMORY\n", __LINE__, __func__);
209 return MM_ERROR_CAMCORDER_LOW_MEMORY;
213 return MM_ERROR_NONE;
218 mm_exif_set_add_entry (ExifData *exif, ExifIfd ifd, ExifTag tag,ExifFormat format,unsigned long components,unsigned char* data)
220 /*mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);*/
221 ExifData *ed = (ExifData *)exif;
224 if (exif == NULL || format <= 0 || components <= 0 || data == NULL) {
225 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p format=%d, components=%lu data=%p!\n",
226 __LINE__, __func__,exif,format,components,data);
227 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
230 /*remove same tag in EXIF*/
231 exif_content_remove_entry(ed->ifd[ifd], exif_content_get_entry(ed->ifd[ifd], tag));
234 e = exif_entry_new();
236 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s] entry create error!\n", __LINE__, __func__);
237 return MM_ERROR_CAMCORDER_LOW_MEMORY;
240 exif_entry_initialize(e, tag);
244 e->components = components;
248 e->data = malloc(exif_format_get_size(format) * e->components);
251 return MM_ERROR_CAMCORDER_LOW_MEMORY;
254 if (format == EXIF_FORMAT_ASCII) {
255 memset(e->data, '\0', exif_format_get_size(format) * e->components);
259 e->size = exif_format_get_size(format) * e->components;
260 memcpy(e->data,data,e->size);
261 exif_content_add_entry(ed->ifd[ifd], e);
264 return MM_ERROR_NONE;
276 mm_exif_create_exif_info (mm_exif_info_t **info)
278 mm_exif_info_t *x = NULL;
279 #if (MM_EXIFINFO_USE_BINARY_EXIFDATA == 0)
281 unsigned char *eb = NULL;
284 mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
287 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s] NULL pointer\n", __LINE__, __func__);
288 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
291 x = malloc(sizeof(mm_exif_info_t));
293 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s]malloc error\n", __LINE__, __func__);
294 return MM_ERROR_CAMCORDER_LOW_MEMORY;
296 #if MM_EXIFINFO_USE_BINARY_EXIFDATA
298 x->data = malloc(_EXIF_BIN_SIZE_);
300 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s]malloc error\n", __LINE__, __func__);
302 return MM_ERROR_CAMCORDER_LOW_MEMORY;
304 memcpy(x->data, g_exif_bin, _EXIF_BIN_SIZE_);
305 x->size = _EXIF_BIN_SIZE_;
307 ed = exif_data_new();
309 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s]exif data new error\n", __LINE__, __func__);
310 return MM_ERROR_CAMCORDER_LOW_MEMORY;
313 exif_data_set_byte_order(ed, EXIF_BYTE_ORDER_INTEL);
314 exif_data_set_data_type(ed, EXIF_DATA_TYPE_COMPRESSED);
315 exif_data_set_option(ed, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
319 exif_data_save_data(ed, &eb, &ebs);
321 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s]exif_data_save_data error\n", __LINE__, __func__);
325 return MM_ERROR_CAMCORDER_INTERNAL;
334 mmf_debug(MMF_DEBUG_LOG, "%s() Data:%p Size:%d\n", __func__, x->data, x->size);
336 return MM_ERROR_NONE;
340 mm_exif_destory_exif_info (mm_exif_info_t *info)
342 //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
344 #if MM_EXIFINFO_USE_BINARY_EXIFDATA
353 exif_mem_free (info->data);
361 mm_exif_add_thumbnail_info (mm_exif_info_t *info, void *thumbnail, int width, int height, int len)
364 static ExifLong elong[10];
366 unsigned char *p_compressed = NULL;
367 int ret = MM_ERROR_NONE;
370 mmf_debug (MMF_DEBUG_LOG,"[%05d][%s] Thumbnail size:%d, width:%d, height:%d\n", __LINE__, __func__, len, width, height);
372 if( len > JPEG_THUMBNAIL_MAX_SIZE )
374 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] Thumbnail size[%d] over!!! Skip inserting thumbnail...\n", __LINE__, __func__, len);
375 return MM_ERROR_NONE;
378 /* get ExifData from info*/
379 ed = mm_exif_get_exif_from_info(info);
380 ed->data = thumbnail;
383 /* set thumbnail data */
384 p_compressed = malloc(sizeof(ExifShort));
385 if (p_compressed != NULL) {
386 exif_set_short(p_compressed, exif_data_get_byte_order(ed), 6);
387 ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_COMPRESSION, EXIF_FORMAT_SHORT, 1, p_compressed);
388 if (ret != MM_ERROR_NONE) {
392 ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
396 /* set thumbnail size */
397 exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), width);
398 ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_IMAGE_WIDTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++]);
399 if (ret != MM_ERROR_NONE) {
402 exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), height);
403 ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_IMAGE_LENGTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++]);
404 if (ret != MM_ERROR_NONE) {
408 ret = mm_exif_set_exif_to_info (info, ed);
409 if (ret != MM_ERROR_NONE) {
415 exif_data_unref (ed);
418 if(p_compressed != NULL)
424 int mm_exif_mnote_create (ExifData *exif)
427 ExifDataOption o = 0;
429 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p \n", __LINE__, __func__,ed);
430 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
433 if(!exif_data_mnote_data_new(ed, MAKER_SAMSUNG, o )){
434 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_mnote_data_samsung_new() failed. \n", __LINE__, __func__);
435 return MM_ERROR_CAMCORDER_MNOTE_CREATION;
438 return MM_ERROR_NONE;
442 int mm_exif_mnote_set_add_entry (ExifData *exif, MnoteSamsungTag tag, int index, int subindex1, int subindex2)
447 ExifShort product_id = 32768; //should be modified
448 char serialNum[] = "SerialNum123"; //should be modified
451 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p \n", __LINE__, __func__,ed);
452 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
455 md = exif_data_get_mnote_data (ed);
457 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_get_mnote_data() failed. \n", __LINE__, __func__);
458 return MM_ERROR_CAMCORDER_MNOTE_CREATION;
461 if(!exif_data_mnote_set_mem_for_adding_entry(md, MAKER_SAMSUNG)){
462 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_mem_for_adding_entry() failed. \n", __LINE__, __func__);
463 return MM_ERROR_CAMCORDER_MNOTE_MALLOC;
466 exif_mnote_data_set_byte_order(md, (ExifByteOrder) exif_data_get_data_order(ed));
469 case MNOTE_SAMSUNG_TAG_MNOTE_VERSION:
470 if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_UNDEFINED, 4, index)){
471 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
472 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
475 case MNOTE_SAMSUNG_TAG_DEVICE_ID:
476 if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
477 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
478 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
481 case MNOTE_SAMSUNG_TAG_MODEL_ID:
482 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 )){
483 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry_subtag() failed. \n", __LINE__, __func__);
484 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
487 case MNOTE_SAMSUNG_TAG_COLOR_INFO:
488 case MNOTE_SAMSUNG_TAG_SERIAL_NUM:
489 if(!exif_data_mnote_set_add_entry_string(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_ASCII, strlen(serialNum), serialNum)){
490 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry_string() failed. \n", __LINE__, __func__);
491 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
494 case MNOTE_SAMSUNG_TAG_IMAGE_COUNT:
495 case MNOTE_SAMSUNG_TAG_GPS_INFO01:
496 case MNOTE_SAMSUNG_TAG_GPS_INFO02:
497 case MNOTE_SAMSUNG_TAG_PREVIEW_IMAGE:
498 case MNOTE_SAMSUNG_TAG_FAVOR_TAGGING:
499 case MNOTE_SAMSUNG_TAG_SRW_COMPRESS:
500 case MNOTE_SAMSUNG_TAG_COLOR_SPACE:
501 if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
502 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
503 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
506 case MNOTE_SAMSUNG_TAG_AE:
507 case MNOTE_SAMSUNG_TAG_AF:
508 case MNOTE_SAMSUNG_TAG_AWB01:
509 case MNOTE_SAMSUNG_TAG_AWB02:
510 case MNOTE_SAMSUNG_TAG_IPC:
511 case MNOTE_SAMSUNG_TAG_SCENE_RESULT:
512 case MNOTE_SAMSUNG_TAG_SADEBUG_INFO01:
513 case MNOTE_SAMSUNG_TAG_SADEBUG_INFO02:
514 case MNOTE_SAMSUNG_TAG_FACE_DETECTION:
515 if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
516 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
517 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
520 case MNOTE_SAMSUNG_TAG_FACE_FEAT01:
521 case MNOTE_SAMSUNG_TAG_FACE_FEAT02:
522 case MNOTE_SAMSUNG_TAG_FACE_RECOG:
523 case MNOTE_SAMSUNG_TAG_LENS_INFO:
524 case MNOTE_SAMSUNG_TAG_THIRDPARTY:
529 return MM_ERROR_NONE;
534 mm_exif_write_exif_jpeg_to_file (char *filename, mm_exif_info_t *info, void *jpeg, int jpeg_len)
537 unsigned short head[2] = {0,};
538 unsigned short head_len = 0;
539 unsigned char *eb = NULL;
542 mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
548 fp = fopen (filename, "wb");
550 mmf_debug (MMF_DEBUG_ERROR, "%s(), fopen() failed [%s].\n", __func__, filename);
551 return MM_ERROR_IMAGE_FILEOPEN;
555 _exif_set_uint16 (0, &head[0], 0xffd8);
556 _exif_set_uint16 (0, &head[1], 0xffe1);
557 /*set header length*/
558 _exif_set_uint16 (0, &head_len, (unsigned short)(ebs + 2));
560 if(head[0]==0 || head[1]==0 || head_len==0)
562 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]setting error\n", __LINE__, __func__);
567 fwrite (&head[0], 1, EXIF_MARKER_SOI_LENGTH, fp); /*SOI marker*/
568 fwrite (&head[1], 1, EXIF_MARKER_APP1_LENGTH, fp); /*APP1 marker*/
569 fwrite (&head_len, 1, EXIF_APP1_LENGTH, fp); /*length of APP1*/
570 fwrite (eb, 1, ebs, fp); /*EXIF*/
571 fwrite (jpeg + JPEG_DATA_OFFSET, 1, jpeg_len - JPEG_DATA_OFFSET, fp); /*IMAGE*/
575 return MM_ERROR_NONE;
579 mm_exif_write_exif_jpeg_to_memory (void **mem, unsigned int *length, mm_exif_info_t *info, void *jpeg, unsigned int jpeg_len)
581 unsigned short head[2] = {0,};
582 unsigned short head_len = 0;
583 unsigned char *eb = NULL;
587 unsigned char *m = NULL;
590 mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
592 if(info==NULL || jpeg==NULL)
594 mmf_debug (MMF_DEBUG_ERROR, "%s(), MM_ERROR_CAMCORDER_INVALID_ARGUMENT info=%p, jpeg=%p\n", __func__,info,jpeg);
595 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
598 if(jpeg_len>JPEG_MAX_SIZE)
600 mmf_debug (MMF_DEBUG_ERROR, "%s(),jpeg_len is worng jpeg_len=%d\n", __func__,jpeg_len);
601 return MM_ERROR_CAMCORDER_DEVICE_WRONG_JPEG;
607 /*length of output image*/
608 /*SOI + APP1 + length of APP1 + length of EXIF + IMAGE*/
609 m_len = EXIF_MARKER_SOI_LENGTH + EXIF_MARKER_APP1_LENGTH + EXIF_APP1_LENGTH + ebs + (jpeg_len - JPEG_DATA_OFFSET);
610 /*alloc output image*/
613 mmf_debug (MMF_DEBUG_ERROR, "%s(), malloc() failed.\n", __func__);
614 return MM_ERROR_CAMCORDER_LOW_MEMORY;
618 _exif_set_uint16 (0, &head[0], 0xffd8);
619 _exif_set_uint16 (0, &head[1], 0xffe1);
620 /*set header length*/
621 _exif_set_uint16 (0, &head_len, (unsigned short)(ebs + 2));
622 if (head[0] == 0 || head[1] == 0 || head_len == 0) {
623 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]setting error\n", __LINE__, __func__);
625 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
628 /* Complete JPEG+EXIF */
630 memcpy(m, &head[0], EXIF_MARKER_SOI_LENGTH);
632 memcpy(m + EXIF_MARKER_SOI_LENGTH,
633 &head[1], EXIF_MARKER_APP1_LENGTH);
635 memcpy(m + EXIF_MARKER_SOI_LENGTH + EXIF_MARKER_APP1_LENGTH,
636 &head_len, EXIF_APP1_LENGTH);
638 memcpy(m + EXIF_MARKER_SOI_LENGTH + EXIF_MARKER_APP1_LENGTH + EXIF_APP1_LENGTH,
641 memcpy(m + EXIF_MARKER_SOI_LENGTH + EXIF_MARKER_APP1_LENGTH + EXIF_APP1_LENGTH + ebs,
642 jpeg + JPEG_DATA_OFFSET, jpeg_len - JPEG_DATA_OFFSET);
644 mmf_debug(MMF_DEBUG_LOG,"[%05d][%s] JPEG+EXIF Copy DONE(original:%d, copied:%d)\n",
645 __LINE__, __func__, jpeg_len, jpeg_len - JPEG_DATA_OFFSET);
651 return MM_ERROR_NONE;