- added experimental EXIF decoding when reading JPEG files.
[imager.git] / imexif.c
CommitLineData
f7450478
TC
1#include "imexif.h"
2#include <stdlib.h>
3#include <float.h>
4
5/*
6=head1 NAME
7
8imexif.c - EXIF support for Imager
9
10=head1 SYNOPSIS
11
12 if (i_int_decode_exif(im, app1data, app1datasize)) {
13 // exif block seen
14 }
15
16=head1 DESCRIPTION
17
18This code provides a basic EXIF data decoder. It is intended to be
19called from the JPEG reader code when an APP1 data block is found, and
20will set tags in the supplied image.
21
22=cut
23*/
24
25typedef enum tiff_type_tag {
26 tt_intel = 'I',
27 tt_motorola = 'M'
28} tiff_type;
29
30typedef enum {
31 ift_byte = 1,
32 ift_ascii = 2,
33 ift_short = 3,
34 ift_long = 4,
35 ift_rational = 5,
36 ift_sbyte = 6,
37 ift_undefined = 7,
38 ift_sshort = 8,
39 ift_slong = 9,
40 ift_srational = 10,
41 ift_float = 11,
42 ift_double = 12,
43 ift_last = 12 /* keep the same as the highest type code */
44} ifd_entry_type;
45
46static int type_sizes[] =
47 {
48 0, /* not used */
49 1, /* byte */
50 1, /* ascii */
51 2, /* short */
52 4, /* long */
53 8, /* rational */
54 1, /* sbyte */
55 1, /* undefined */
56 2, /* sshort */
57 4, /* slong */
58 8, /* srational */
59 4, /* float */
60 8, /* double */
61 };
62
63typedef struct {
64 int tag;
65 int type;
66 int count;
67 int size;
68 int offset;
69} ifd_entry;
70
71typedef struct {
72 int tag;
73 char const *name;
74} tag_map;
75
76typedef struct {
77 int tag;
78 char const *name;
79 tag_map const *map;
80 int map_count;
81} tag_value_map;
82
83#define PASTE(left, right) PASTE_(left, right)
84#define PASTE_(left, right) left##right
85#define QUOTE(value) #value
86
87#define VALUE_MAP_ENTRY(name) \
88 { \
89 PASTE(tag_, name), \
90 "exif_" QUOTE(name) "_name", \
91 PASTE(name, _values), \
92 ARRAY_COUNT(PASTE(name, _values)) \
93 }
94
95/* we don't process every tag */
96#define tag_make 271
97#define tag_model 272
98#define tag_orientation 274
99#define tag_x_resolution 282
100#define tag_y_resolution 283
101#define tag_resolution_unit 296
102#define tag_copyright 33432
103#define tag_software 305
104#define tag_artist 315
105#define tag_date_time 306
106#define tag_image_description 270
107
108#define tag_exif_ifd 34665
109#define tag_gps_ifd 34853
110
111#define resunit_none 1
112#define resunit_inch 2
113#define resunit_centimeter 3
114
115/* tags from the EXIF ifd */
116#define tag_exif_version 0x9000
117#define tag_flashpix_version 0xA000
118#define tag_color_space 0xA001
119#define tag_component_configuration 0x9101
120#define tag_component_bits_per_pixel 0x9102
121#define tag_pixel_x_dimension 0xA002
122#define tag_pixel_y_dimension 0xA003
123#define tag_maker_note 0x927C
124#define tag_user_comment 0x9286
125#define tag_related_sound_file 0xA004
126#define tag_date_time_original 0x9003
127#define tag_date_time_digitized 0x9004
128#define tag_sub_sec_time 0x9290
129#define tag_sub_sec_time_original 0x9291
130#define tag_sub_sec_time_digitized 0x9292
131#define tag_image_unique_id 0xA420
132#define tag_exposure_time 0x829a
133#define tag_f_number 0x829D
134#define tag_exposure_program 0x8822
135#define tag_spectral_sensitivity 0x8824
136#define tag_iso_speed_rating 0x8827
137#define tag_oecf 0x8828
138#define tag_shutter_speed 0x9201
139#define tag_aperture 0x9202
140#define tag_brightness 0x9203
141#define tag_exposure_bias 0x9204
142#define tag_max_aperture 0x9205
143#define tag_subject_distance 0x9206
144#define tag_metering_mode 0x9207
145#define tag_light_source 0x9208
146#define tag_flash 0x9209
147#define tag_focal_length 0x920a
148#define tag_subject_area 0x9214
149#define tag_flash_energy 0xA20B
150#define tag_spatial_frequency_response 0xA20C
151#define tag_focal_plane_x_resolution 0xA20e
152#define tag_focal_plane_y_resolution 0xA20F
153#define tag_focal_plane_resolution_unit 0xA210
154#define tag_subject_location 0xA214
155#define tag_exposure_index 0xA215
156#define tag_sensing_method 0xA217
157#define tag_file_source 0xA300
158#define tag_scene_type 0xA301
159#define tag_cfa_pattern 0xA302
160#define tag_custom_rendered 0xA401
161#define tag_exposure_mode 0xA402
162#define tag_white_balance 0xA403
163#define tag_digital_zoom_ratio 0xA404
164#define tag_focal_length_in_35mm_film 0xA405
165#define tag_scene_capture_type 0xA406
166#define tag_gain_control 0xA407
167#define tag_contrast 0xA408
168#define tag_saturation 0xA409
169#define tag_sharpness 0xA40A
170#define tag_device_setting_description 0xA40B
171#define tag_subject_distance_range 0xA40C
172
173/* don't use this on pointers */
174#define ARRAY_COUNT(array) (sizeof(array)/sizeof(*array))
175
176/* in memory tiff structure */
177typedef struct {
178 /* the data we use as a tiff */
179 unsigned char *base;
180 size_t size;
181
182 /* intel or motorola byte order */
183 tiff_type type;
184
185 /* initial ifd offset */
186 unsigned long first_ifd_offset;
187
188 /* size (in entries) and data */
189 int ifd_size;
190 ifd_entry *ifd;
191 unsigned long next_ifd;
192} imtiff;
193
194static int tiff_init(imtiff *tiff, unsigned char *base, size_t length);
195static int tiff_load_ifd(imtiff *tiff, unsigned long offset);
196static void tiff_final(imtiff *tiff);
197static void tiff_clear_ifd(imtiff *tiff);
198static int tiff_get_bytes(imtiff *tiff, unsigned char *to, size_t offset,
199 size_t count);
200static int tiff_get_tag_double(imtiff *, int index, double *result);
201static int tiff_get_tag_int(imtiff *, int index, int *result);
202static unsigned tiff_get16(imtiff *, unsigned long offset);
203static unsigned tiff_get32(imtiff *, unsigned long offset);
204static int tiff_get16s(imtiff *, unsigned long offset);
205static int tiff_get32s(imtiff *, unsigned long offset);
206static double tiff_get_rat(imtiff *, unsigned long offset);
207static double tiff_get_rats(imtiff *, unsigned long offset);
208static void save_ifd0_tags(i_img *im, imtiff *tiff, unsigned long *exif_ifd_offset);
209static void save_exif_ifd_tags(i_img *im, imtiff *tiff);
210static void
211copy_string_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
212static void
213copy_int_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
214static void
215copy_rat_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
216static void
217copy_name_tags(i_img *im, imtiff *tiff, tag_value_map *map, int map_count);
218static void process_maker_note(i_img *im, imtiff *tiff, unsigned long offset, size_t size);
219
220/*
221=head1 PUBLIC FUNCTIONS
222
223These functions are available to other parts of Imager. They aren't
224intended to be called from outside of Imager.
225
226=over
227
228=item i_int_decode_exit
229
230i_int_decode_exif(im, data_base, data_size);
231
232The data from data_base for data_size bytes will be scanned for EXIF
233data.
234
235Any data found will be used to set tags in the supplied image.
236
237The intent is that invalid EXIF data will simply fail to set tags, and
238write to the log. In no case should this code exit when supplied
239invalid data.
240
241Returns true if an Exif header was seen.
242
243*/
244
245int
246i_int_decode_exif(i_img *im, unsigned char *data, size_t length) {
247 imtiff tiff;
248 unsigned long exif_ifd_offset = 0;
249 unsigned long ifd1_offset;
250 /* basic checks - must start with "Exif\0\0" */
251
252 if (length < 6 || memcmp(data, "Exif\0\0", 6) != 0) {
253 return 0;
254 }
255
256 data += 6;
257 length -= 6;
258
259 if (!tiff_init(&tiff, data, length)) {
260 mm_log((2, "Exif header found, but no valid TIFF header\n"));
261 return 1;
262 }
263 if (!tiff_load_ifd(&tiff, tiff.first_ifd_offset)) {
264 mm_log((2, "Exif header found, but could not load IFD 0\n"));
265 tiff_final(&tiff);
266 return 1;
267 }
268
269 save_ifd0_tags(im, &tiff, &exif_ifd_offset);
270
271 if (exif_ifd_offset) {
272 if (tiff_load_ifd(&tiff, exif_ifd_offset)) {
273 save_exif_ifd_tags(im, &tiff);
274 }
275 else {
276 mm_log((2, "Could not load Exif IFD\n"));
277 }
278 }
279
280 tiff_final(&tiff);
281
282 return 1;
283}
284
285/*
286
287=back
288
289=head1 INTERNAL FUNCTIONS
290
291=head2 EXIF Processing
292
293=over
294
295=item save_ifd0_tags
296
297save_ifd0_tags(im, tiff, &exif_ifd_offset)
298
299Scans the currently loaded IFD for tags expected in IFD0 and sets them
300in the image.
301
302Sets *exif_ifd_offset to the offset of the EXIF IFD if found.
303
304=cut
305
306*/
307
308static tag_map ifd0_string_tags[] =
309 {
310 tag_make, "exif_make",
311 tag_model, "exif_model",
312 tag_copyright, "exif_copyright",
313 tag_software, "exif_software",
314 tag_artist, "exif_artist",
315 tag_date_time, "exif_date_time",
316 tag_image_description, "exif_image_description",
317 };
318
319static const int ifd0_string_tag_count = ARRAY_COUNT(ifd0_string_tags);
320
321static tag_map ifd0_int_tags[] =
322 {
323 { tag_orientation, "exif_orientation", },
324 { tag_resolution_unit, "exif_resolution_unit" },
325 };
326
327static const int ifd0_int_tag_count = ARRAY_COUNT(ifd0_int_tags);
328
329static tag_map ifd0_rat_tags[] =
330 {
331 { tag_x_resolution, "exif_x_resolution" },
332 { tag_y_resolution, "exif_y_resolution" },
333 };
334
335static tag_map resolution_unit_values[] =
336 {
337 { 1, "none" },
338 { 2, "inches" },
339 { 3, "centimeters" },
340 };
341
342static tag_value_map ifd0_values[] =
343 {
344 VALUE_MAP_ENTRY(resolution_unit),
345 };
346
347static void
348save_ifd0_tags(i_img *im, imtiff *tiff, unsigned long *exif_ifd_offset) {
349 int i, tag_index;
350 int work;
351 ifd_entry *entry;
352
353 for (tag_index = 0, entry = tiff->ifd;
354 tag_index < tiff->ifd_size; ++tag_index, ++entry) {
355 switch (entry->tag) {
356 case tag_exif_ifd:
357 if (tiff_get_tag_int(tiff, tag_index, &work))
358 *exif_ifd_offset = work;
359 break;
360 }
361 }
362
363 copy_string_tags(im, tiff, ifd0_string_tags, ifd0_string_tag_count);
364 copy_int_tags(im, tiff, ifd0_int_tags, ifd0_int_tag_count);
365 copy_rat_tags(im, tiff, ifd0_rat_tags, ARRAY_COUNT(ifd0_rat_tags));
366 copy_name_tags(im, tiff, ifd0_values, ARRAY_COUNT(ifd0_values));
367}
368
369/*
370=item save_exif_ifd_tags
371
372save_exif_ifd_tags(im, tiff)
373
374Scans the currently loaded IFD for the tags expected in the EXIF IFD
375and sets them as tags in the image.
376
377=cut
378
379*/
380
381static tag_map exif_ifd_string_tags[] =
382 {
383 { tag_exif_version, "exif_version", },
384 { tag_flashpix_version, "exif_flashpix_version", },
385 { tag_related_sound_file, "exif_related_sound_file", },
386 { tag_date_time_original, "exif_date_time_original", },
387 { tag_date_time_digitized, "exif_date_time_digitized", },
388 { tag_sub_sec_time, "exif_sub_sec_time" },
389 { tag_sub_sec_time_original, "exif_sub_sec_time_original" },
390 { tag_sub_sec_time_digitized, "exif_sub_sec_time_digitized" },
391 { tag_image_unique_id, "exif_image_unique_id" },
392 { tag_spectral_sensitivity, "exif_spectral_sensitivity" },
393 };
394
395static const int exif_ifd_string_tag_count = ARRAY_COUNT(exif_ifd_string_tags);
396
397static tag_map exif_ifd_int_tags[] =
398 {
399 { tag_color_space, "exif_color_space" },
400 { tag_exposure_program, "exif_exposure_program" },
401 { tag_iso_speed_rating, "exif_iso_speed_rating" },
402 { tag_metering_mode, "exif_metering_mode" },
403 { tag_light_source, "exif_light_source" },
404 { tag_flash, "exif_flash" },
405 { tag_focal_plane_resolution_unit, "exif_focal_plane_resolution_unit" },
406 { tag_subject_location, "exif_subject_location" },
407 { tag_sensing_method, "exif_sensing_method" },
408 { tag_custom_rendered, "exif_custom_rendered" },
409 { tag_exposure_mode, "exif_exposure_mode" },
410 { tag_white_balance, "exif_white_balance" },
411 { tag_focal_length_in_35mm_film, "exif_focal_length_in_35mm_film" },
412 { tag_scene_capture_type, "exif_scene_capture_type" },
413 { tag_contrast, "exif_contrast" },
414 { tag_saturation, "exif_saturation" },
415 { tag_sharpness, "exif_sharpness" },
416 { tag_subject_distance_range, "exif_subject_distance_range" },
417 };
418
419
420static const int exif_ifd_int_tag_count = ARRAY_COUNT(exif_ifd_int_tags);
421
422static tag_map exif_ifd_rat_tags[] =
423 {
424 { tag_exposure_time, "exif_exposure_time" },
425 { tag_f_number, "exif_f_number" },
426 { tag_shutter_speed, "exif_shutter_speed" },
427 { tag_aperture, "exif_aperture" },
428 { tag_brightness, "exif_brightness" },
429 { tag_exposure_bias, "exif_exposure_bias" },
430 { tag_max_aperture, "exif_max_aperture" },
431 { tag_subject_distance, "exif_subject_distance" },
432 { tag_focal_length, "exif_focal_length" },
433 { tag_flash_energy, "exif_flash_energy" },
434 { tag_focal_plane_x_resolution, "exif_focal_plane_x_resolution" },
435 { tag_focal_plane_y_resolution, "exif_focal_plane_y_resolution" },
436 { tag_exposure_index, "exif_exposure_index" },
437 { tag_digital_zoom_ratio, "exif_digital_zoom_ratio" },
438 { tag_gain_control, "exif_gain_control" },
439 };
440
441static const int exif_ifd_rat_tag_count = ARRAY_COUNT(exif_ifd_rat_tags);
442
443static tag_map exposure_mode_values[] =
444 {
445 { 0, "Auto exposure" },
446 { 1, "Manual exposure" },
447 { 2, "Auto bracket" },
448 };
449static tag_map color_space_values[] =
450 {
451 { 1, "sRGB" },
452 { 0xFFFF, "Uncalibrated" },
453 };
454
455static tag_map exposure_program_values[] =
456 {
457 { 0, "Not defined" },
458 { 1, "Manual" },
459 { 2, "Normal program" },
460 { 3, "Aperture priority" },
461 { 4, "Shutter priority" },
462 { 5, "Creative program" },
463 { 6, "Action program" },
464 { 7, "Portrait mode" },
465 { 8, "Landscape mode" },
466 };
467
468static tag_map metering_mode_values[] =
469 {
470 { 0, "unknown" },
471 { 1, "Average" },
472 { 2, "CenterWeightedAverage" },
473 { 3, "Spot" },
474 { 4, "MultiSpot" },
475 { 5, "Pattern" },
476 { 6, "Partial" },
477 { 255, "other" },
478 };
479
480static tag_map light_source_values[] =
481 {
482 { 0, "unknown" },
483 { 1, "Daylight" },
484 { 2, "Fluorescent" },
485 { 3, "Tungsten (incandescent light)" },
486 { 4, "Flash" },
487 { 9, "Fine weather" },
488 { 10, "Cloudy weather" },
489 { 11, "Shade" },
490