2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <libexif/exif-loader.h>
22 #include <libexif/exif-utils.h>
23 #include <libexif/exif-data.h>
26 #define ASCII_COMMENT_HEADER "ASCII\0\0\0"
27 // #define CHECK_EXIF_BEFOR_CREATE
29 static int check_exif_from_data(const unsigned char *img, unsigned int size)
31 #ifdef CHECK_EXIF_BEFOR_CREATE
32 ExifLoader *loader = NULL;
33 unsigned char ret = 0;
34 const unsigned char *buf = NULL;
35 unsigned int b_size = 0;
38 retv_if(size == 0, -1);
40 loader = exif_loader_new();
43 ret = exif_loader_write(loader, img, size);
45 _E("failed to loader write");
46 exif_loader_unref(loader);
50 exif_loader_get_buf(loader, &buf, &b_size);
52 _E("image has already exif data [%u]", b_size);
53 exif_loader_unref(loader);
57 exif_loader_unref(loader);
58 #endif /* CHECK_EXIF_BEFOR_CREATE */
64 add_tag_by_init(ExifData *exif, ExifIfd ifd, ExifTag tag)
66 ExifEntry *entry = NULL;
70 entry = exif_content_get_entry(exif->ifd[ifd], tag);
72 entry = exif_entry_new();
73 retv_if(!entry, NULL);
75 exif_entry_initialize(entry, tag);
78 exif_content_add_entry(exif->ifd[ifd], entry);
80 exif_entry_unref(entry);
86 add_tag_by_malloc(ExifData *exif, ExifIfd ifd, ExifTag tag, unsigned int size)
88 ExifEntry *entry = NULL;
93 retv_if(size == 0, NULL);
95 mem = exif_mem_new_default();
98 entry = exif_entry_new_mem(mem);
100 _E("failed to exif_entry_new_mem()");
105 buffer = exif_mem_alloc(mem, size);
107 _E("failed to exif_mem_alloc()");
109 exif_entry_unref(entry);
113 entry->data = buffer;
116 entry->components = size;
117 entry->format = EXIF_FORMAT_UNDEFINED;
118 exif_content_add_entry (exif->ifd[ifd], entry);
121 exif_entry_unref(entry);
127 add_tag_user_comment(ExifData *exif, const char *comment, unsigned int length)
129 ExifEntry *entry = NULL;
130 size_t header_size = 0;
132 retv_if(!exif, NULL);
133 retv_if(!comment, NULL);
134 retv_if(length == 0, NULL);
136 header_size = sizeof(ASCII_COMMENT_HEADER) -1;
138 entry = add_tag_by_malloc(exif, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
139 header_size + length);
141 retv_if(!entry, NULL);
143 memcpy(entry->data, ASCII_COMMENT_HEADER, header_size);
144 memcpy(entry->data + header_size, comment, length);
150 create_exif_data(const unsigned char *jpg_data, unsigned int jpg_size,
151 unsigned int jpg_width, unsigned int jpg_height,
152 const char *user_comment, unsigned int comment_len,
153 unsigned char **exif_data, unsigned int *exif_size)
157 unsigned int data_len;
158 ExifEntry *ee = NULL;
159 ExifData *exif = NULL;
161 retv_if(!jpg_data, -1);
162 retv_if(!exif_data, -1);
163 retv_if(!exif_size, -1);
165 if (check_exif_from_data(jpg_data, jpg_size))
168 exif = exif_data_new();
171 exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
172 exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
173 exif_data_set_byte_order(exif, EXIF_BYTE_ORDER_INTEL);
177 ee = add_tag_by_init(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION);
178 exif_set_long(ee->data, EXIF_BYTE_ORDER_INTEL, jpg_width);
180 ee = add_tag_by_init(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION);
181 exif_set_long(ee->data, EXIF_BYTE_ORDER_INTEL, jpg_height);
183 ee = add_tag_user_comment(exif, user_comment, comment_len);
185 exif_data_save_data(exif, &data, &data_len);
187 _E("failed to get exif data");
188 exif_data_unref(exif);
191 exif_data_unref(exif);
194 *exif_size = data_len;
200 save_jpeg_file(const char *output_file,
201 const unsigned char *jpg_data, unsigned int jpg_size)
204 retv_if(!output_file, -1);
205 retv_if(!jpg_data, -1);
206 retv_if(jpg_size <= 2, -1);
208 fp = fopen(output_file, "wb");
211 if (1 != fwrite(jpg_data, jpg_size, 1, fp)) {
212 _E("failed to write jpg data");
220 _D("file saved [%s]", output_file);
226 save_jpeg_file_with_exif(const char *output_file,
227 const unsigned char *jpg_data, unsigned int jpg_size,
228 unsigned char *exif_data, unsigned int exif_size)
231 const unsigned char exif_header[] = { 0xff, 0xd8, 0xff, 0xe1 }; // FFD8 -SOI Maker, FFE1 - APP1 Maker
232 const unsigned short exif_header_length = 4;
233 const unsigned short jpg_offset = 2; // SOI maker offset
234 unsigned short exif_length = 0;
236 ((unsigned char *)&exif_length)[0] = (exif_size + 2) >> 8;
237 ((unsigned char *)&exif_length)[1] = (exif_size + 2) & 0x00ff;
239 retv_if(!output_file, -1);
240 retv_if(!jpg_data, -1);
241 retv_if(!exif_data, -1);
242 retv_if(jpg_size <= 2, -1);
243 retv_if(exif_size == 0, -1);
245 fp = fopen(output_file, "wb");
248 if (1 != fwrite(exif_header, exif_header_length, 1, fp)) {
249 _E("failed to write exif header");
253 if (1 != fwrite(&exif_length, sizeof(exif_length), 1, fp)) {
254 _E("failed to write exif legth");
258 if (1 != fwrite(exif_data, exif_size, 1, fp)) {
259 _E("failed to write exif");
263 if (1 != fwrite(jpg_data + jpg_offset, jpg_size - jpg_offset, 1, fp)) {
264 _E("failed to write jpg data");
275 _E(" failed to save file - [%s]", output_file);
279 int exif_write_jpg_file_with_comment(const char *output_file,
280 const unsigned char *jpg_data, unsigned int jpg_size,
281 unsigned int jpg_width, unsigned int jpg_height,
282 const char *comment, unsigned int comment_len)
285 unsigned char *exif_data = NULL;
286 unsigned int exif_size = 0;
288 if (!comment || (comment_len == 0)) {
289 _W("There is no comment");
290 return save_jpeg_file(output_file, jpg_data, jpg_size);
293 ret = create_exif_data(jpg_data, jpg_size, jpg_width, jpg_height,
294 comment, comment_len, &exif_data, &exif_size);
296 _E("failed to create_exif_data(), save jpg data only");
297 return save_jpeg_file(output_file, jpg_data, jpg_size);
300 ret = save_jpeg_file_with_exif(
301 output_file, jpg_data, jpg_size, exif_data, exif_size);