8 imexif.c - EXIF support for Imager
12 if (i_int_decode_exif(im, app1data, app1datasize)) {
18 This code provides a basic EXIF data decoder. It is intended to be
19 called from the JPEG reader code when an APP1 data block is found, and
20 will set tags in the supplied image.
25 typedef enum tiff_type_tag {
43 ift_last = 12 /* keep the same as the highest type code */
46 static int type_sizes[] =
84 #define PASTE(left, right) PASTE_(left, right)
85 #define PASTE_(left, right) left##right
86 #define QUOTE(value) #value
88 #define VALUE_MAP_ENTRY(name) \
91 "exif_" QUOTE(name) "_name", \
92 PASTE(name, _values), \
93 ARRAY_COUNT(PASTE(name, _values)) \
96 /* we don't process every tag */
99 #define tag_orientation 274
100 #define tag_x_resolution 282
101 #define tag_y_resolution 283
102 #define tag_resolution_unit 296
103 #define tag_copyright 33432
104 #define tag_software 305
105 #define tag_artist 315
106 #define tag_date_time 306
107 #define tag_image_description 270
109 #define tag_exif_ifd 34665
110 #define tag_gps_ifd 34853
112 #define resunit_none 1
113 #define resunit_inch 2
114 #define resunit_centimeter 3
116 /* tags from the EXIF ifd */
117 #define tag_exif_version 0x9000
118 #define tag_flashpix_version 0xA000
119 #define tag_color_space 0xA001
120 #define tag_component_configuration 0x9101
121 #define tag_component_bits_per_pixel 0x9102
122 #define tag_pixel_x_dimension 0xA002
123 #define tag_pixel_y_dimension 0xA003
124 #define tag_maker_note 0x927C
125 #define tag_user_comment 0x9286
126 #define tag_related_sound_file 0xA004
127 #define tag_date_time_original 0x9003
128 #define tag_date_time_digitized 0x9004
129 #define tag_sub_sec_time 0x9290
130 #define tag_sub_sec_time_original 0x9291
131 #define tag_sub_sec_time_digitized 0x9292
132 #define tag_image_unique_id 0xA420
133 #define tag_exposure_time 0x829a
134 #define tag_f_number 0x829D
135 #define tag_exposure_program 0x8822
136 #define tag_spectral_sensitivity 0x8824
137 #define tag_iso_speed_ratings 0x8827
138 #define tag_oecf 0x8828
139 #define tag_shutter_speed 0x9201
140 #define tag_aperture 0x9202
141 #define tag_brightness 0x9203
142 #define tag_exposure_bias 0x9204
143 #define tag_max_aperture 0x9205
144 #define tag_subject_distance 0x9206
145 #define tag_metering_mode 0x9207
146 #define tag_light_source 0x9208
147 #define tag_flash 0x9209
148 #define tag_focal_length 0x920a
149 #define tag_subject_area 0x9214
150 #define tag_flash_energy 0xA20B
151 #define tag_spatial_frequency_response 0xA20C
152 #define tag_focal_plane_x_resolution 0xA20e
153 #define tag_focal_plane_y_resolution 0xA20F
154 #define tag_focal_plane_resolution_unit 0xA210
155 #define tag_subject_location 0xA214
156 #define tag_exposure_index 0xA215
157 #define tag_sensing_method 0xA217
158 #define tag_file_source 0xA300
159 #define tag_scene_type 0xA301
160 #define tag_cfa_pattern 0xA302
161 #define tag_custom_rendered 0xA401
162 #define tag_exposure_mode 0xA402
163 #define tag_white_balance 0xA403
164 #define tag_digital_zoom_ratio 0xA404
165 #define tag_focal_length_in_35mm_film 0xA405
166 #define tag_scene_capture_type 0xA406
167 #define tag_gain_control 0xA407
168 #define tag_contrast 0xA408
169 #define tag_saturation 0xA409
170 #define tag_sharpness 0xA40A
171 #define tag_device_setting_description 0xA40B
172 #define tag_subject_distance_range 0xA40C
175 #define tag_gps_version_id 0
176 #define tag_gps_latitude_ref 1
177 #define tag_gps_latitude 2
178 #define tag_gps_longitude_ref 3
179 #define tag_gps_longitude 4
180 #define tag_gps_altitude_ref 5
181 #define tag_gps_altitude 6
182 #define tag_gps_time_stamp 7
183 #define tag_gps_satellites 8
184 #define tag_gps_status 9
185 #define tag_gps_measure_mode 10
186 #define tag_gps_dop 11
187 #define tag_gps_speed_ref 12
188 #define tag_gps_speed 13
189 #define tag_gps_track_ref 14
190 #define tag_gps_track 15
191 #define tag_gps_img_direction_ref 16
192 #define tag_gps_img_direction 17
193 #define tag_gps_map_datum 18
194 #define tag_gps_dest_latitude_ref 19
195 #define tag_gps_dest_latitude 20
196 #define tag_gps_dest_longitude_ref 21
197 #define tag_gps_dest_longitude 22
198 #define tag_gps_dest_bearing_ref 23
199 #define tag_gps_dest_bearing 24
200 #define tag_gps_dest_distance_ref 25
201 #define tag_gps_dest_distance 26
202 #define tag_gps_processing_method 27
203 #define tag_gps_area_information 28
204 #define tag_gps_date_stamp 29
205 #define tag_gps_differential 30
207 /* don't use this on pointers */
208 #define ARRAY_COUNT(array) (sizeof(array)/sizeof(*array))
210 /* in memory tiff structure */
212 /* the data we use as a tiff */
216 /* intel or motorola byte order */
219 /* initial ifd offset */
220 unsigned long first_ifd_offset;
222 /* size (in entries) and data */
225 unsigned long next_ifd;
228 static int tiff_init(imtiff *tiff, unsigned char *base, size_t length);
229 static int tiff_load_ifd(imtiff *tiff, unsigned long offset);
230 static void tiff_final(imtiff *tiff);
231 static void tiff_clear_ifd(imtiff *tiff);
232 static int tiff_get_bytes(imtiff *tiff, unsigned char *to, size_t offset,
234 static int tiff_get_tag_double(imtiff *, int index, double *result);
235 static int tiff_get_tag_int(imtiff *, int index, int *result);
236 static unsigned tiff_get16(imtiff *, unsigned long offset);
237 static unsigned tiff_get32(imtiff *, unsigned long offset);
238 static int tiff_get16s(imtiff *, unsigned long offset);
239 static int tiff_get32s(imtiff *, unsigned long offset);
240 static double tiff_get_rat(imtiff *, unsigned long offset);
241 static double tiff_get_rats(imtiff *, unsigned long offset);
242 static void save_ifd0_tags(i_img *im, imtiff *tiff, unsigned long *exif_ifd_offset, unsigned long *gps_ifd_offset);
243 static void save_exif_ifd_tags(i_img *im, imtiff *tiff);
244 static void save_gps_ifd_tags(i_img *im, imtiff *tiff);
246 copy_string_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
248 copy_int_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
250 copy_rat_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
252 copy_num_array_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
254 copy_name_tags(i_img *im, imtiff *tiff, tag_value_map *map, int map_count);
255 static void process_maker_note(i_img *im, imtiff *tiff, unsigned long offset, size_t size);
258 =head1 PUBLIC FUNCTIONS
260 These functions are available to other parts of Imager. They aren't
261 intended to be called from outside of Imager.
265 =item i_int_decode_exit
267 i_int_decode_exif(im, data_base, data_size);
269 The data from data_base for data_size bytes will be scanned for EXIF
272 Any data found will be used to set tags in the supplied image.
274 The intent is that invalid EXIF data will simply fail to set tags, and
275 write to the log. In no case should this code exit when supplied
278 Returns true if an Exif header was seen.
283 i_int_decode_exif(i_img *im, unsigned char *data, size_t length) {
285 unsigned long exif_ifd_offset = 0;
286 unsigned long gps_ifd_offset = 0;
287 /* basic checks - must start with "Exif\0\0" */
289 if (length < 6 || memcmp(data, "Exif\0\0", 6) != 0) {
296 if (!tiff_init(&tiff, data, length)) {
297 mm_log((2, "Exif header found, but no valid TIFF header\n"));
300 if (!tiff_load_ifd(&tiff, tiff.first_ifd_offset)) {
301 mm_log((2, "Exif header found, but could not load IFD 0\n"));
306 save_ifd0_tags(im, &tiff, &exif_ifd_offset, &gps_ifd_offset);
308 if (exif_ifd_offset) {
309 if (tiff_load_ifd(&tiff, exif_ifd_offset)) {
310 save_exif_ifd_tags(im, &tiff);
313 mm_log((2, "Could not load Exif IFD\n"));
317 if (gps_ifd_offset) {
318 if (tiff_load_ifd(&tiff, gps_ifd_offset)) {
319 save_gps_ifd_tags(im, &tiff);
322 mm_log((2, "Could not load GPS IFD\n"));
335 =head1 INTERNAL FUNCTIONS
337 =head2 EXIF Processing
343 save_ifd0_tags(im, tiff, &exif_ifd_offset, &gps_ifd_offset)
345 Scans the currently loaded IFD for tags expected in IFD0 and sets them
348 Sets *exif_ifd_offset to the offset of the EXIF IFD if found.
354 static tag_map ifd0_string_tags[] =
356 { tag_make, "exif_make" },
357 { tag_model, "exif_model" },
358 { tag_copyright, "exif_copyright" },
359 { tag_software, "exif_software" },
360 { tag_artist, "exif_artist" },
361 { tag_date_time, "exif_date_time" },
362 { tag_image_description, "exif_image_description" },
365 static const int ifd0_string_tag_count = ARRAY_COUNT(ifd0_string_tags);
367 static tag_map ifd0_int_tags[] =
369 { tag_orientation, "exif_orientation", },
370 { tag_resolution_unit, "exif_resolution_unit" },
373 static const int ifd0_int_tag_count = ARRAY_COUNT(ifd0_int_tags);
375 static tag_map ifd0_rat_tags[] =
377 { tag_x_resolution, "exif_x_resolution" },
378 { tag_y_resolution, "exif_y_resolution" },
381 static tag_map resolution_unit_values[] =
385 { 3, "centimeters" },
388 static tag_value_map ifd0_values[] =
390 VALUE_MAP_ENTRY(resolution_unit),
394 save_ifd0_tags(i_img *im, imtiff *tiff, unsigned long *exif_ifd_offset,
395 unsigned long *gps_ifd_offset) {
400 for (tag_index = 0, entry = tiff->ifd;
401 tag_index < tiff->ifd_size; ++tag_index, ++entry) {
402 switch (entry->tag) {
404 if (tiff_get_tag_int(tiff, tag_index, &work))
405 *exif_ifd_offset = work;
409 if (tiff_get_tag_int(tiff, tag_index, &work))
410 *gps_ifd_offset = work;
415 copy_string_tags(im, tiff, ifd0_string_tags, ifd0_string_tag_count);
416 copy_int_tags(im, tiff, ifd0_int_tags, ifd0_int_tag_count);
417 copy_rat_tags(im, tiff, ifd0_rat_tags, ARRAY_COUNT(ifd0_rat_tags));
418 copy_name_tags(im, tiff, ifd0_values, ARRAY_COUNT(ifd0_values));
419 /* copy_num_array_tags(im, tiff, ifd0_num_arrays, ARRAY_COUNT(ifd0_num_arrays)); */
423 =item save_exif_ifd_tags
425 save_exif_ifd_tags(im, tiff)
427 Scans the currently loaded IFD for the tags expected in the EXIF IFD
428 and sets them as tags in the image.
434 static tag_map exif_ifd_string_tags[] =
436 { tag_exif_version, "exif_version", },
437 { tag_flashpix_version, "exif_flashpix_version", },
438 { tag_related_sound_file, "exif_related_sound_file", },
439 { tag_date_time_original, "exif_date_time_original", },
440 { tag_date_time_digitized, "exif_date_time_digitized", },
441 { tag_sub_sec_time, "exif_sub_sec_time" },
442 { tag_sub_sec_time_original, "exif_sub_sec_time_original" },
443 { tag_sub_sec_time_digitized, "exif_sub_sec_time_digitized" },
444 { tag_image_unique_id, "exif_image_unique_id" },
445 { tag_spectral_sensitivity, "exif_spectral_sensitivity" },
448 static const int exif_ifd_string_tag_count = ARRAY_COUNT(exif_ifd_string_tags);
450 static tag_map exif_ifd_int_tags[] =
452 { tag_color_space, "exif_color_space" },
453 { tag_exposure_program, "exif_exposure_program" },
454 { tag_metering_mode, "exif_metering_mode" },
455 { tag_light_source, "exif_light_source" },
456 { tag_flash, "exif_flash" },
457 { tag_focal_plane_resolution_unit, "exif_focal_plane_resolution_unit" },
458 { tag_subject_location, "exif_subject_location" },
459 { tag_sensing_method, "exif_sensing_method" },
460 { tag_custom_rendered, "exif_custom_rendered" },
461 { tag_exposure_mode, "exif_exposure_mode" },
462 { tag_white_balance, "exif_white_balance" },
463 { tag_focal_length_in_35mm_film, "exif_focal_length_in_35mm_film" },
464 { tag_scene_capture_type, "exif_scene_capture_type" },
465 { tag_contrast, "exif_contrast" },
466 { tag_saturation, "exif_saturation" },
467 { tag_sharpness, "exif_sharpness" },
468 { tag_subject_distance_range, "exif_subject_distance_range" },
472 static const int exif_ifd_int_tag_count = ARRAY_COUNT(exif_ifd_int_tags);
474 static tag_map exif_ifd_rat_tags[] =
476 { tag_exposure_time, "exif_exposure_time" },
477 { tag_f_number, "exif_f_number" },
478 { tag_shutter_speed, "exif_shutter_speed" },
479 { tag_aperture, "exif_aperture" },
480 { tag_brightness, "exif_brightness" },
481 { tag_exposure_bias, "exif_exposure_bias" },
482 { tag_max_aperture, "exif_max_aperture" },
483 { tag_subject_distance, "exif_subject_distance" },
484 { tag_focal_length, "exif_focal_length" },
485 { tag_flash_energy, "exif_flash_energy" },
486 { tag_focal_plane_x_resolution, "exif_focal_plane_x_resolution" },
487 { tag_focal_plane_y_resolution, "exif_focal_plane_y_resolution" },
488 { tag_exposure_index, "exif_exposure_index" },
489 { tag_digital_zoom_ratio, "exif_digital_zoom_ratio" },
490 { tag_gain_control, "exif_gain_control" },
493 static const int exif_ifd_rat_tag_count = ARRAY_COUNT(exif_ifd_rat_tags);
495 static tag_map exposure_mode_values[] =
497 { 0, "Auto exposure" },
498 { 1, "Manual exposure" },
499 { 2, "Auto bracket" },
501 static tag_map color_space_values[] =
504 { 0xFFFF, "Uncalibrated" },
507 static tag_map exposure_program_values[] =
509 { 0, "Not defined" },
511 { 2, "Normal program" },
512 { 3, "Aperture priority" },
513 { 4, "Shutter priority" },
514 { 5, "Creative program" },
515 { 6, "Action program" },
516 { 7, "Portrait mode" },
517 { 8, "Landscape mode" },
520 static tag_map metering_mode_values[] =
524 { 2, "CenterWeightedAverage" },
532 static tag_map light_source_values[] =
536 { 2, "Fluorescent" },
537 { 3, "Tungsten (incandescent light)" },
539 { 9, "Fine weather" },
540 { 10, "Cloudy weather" },
542 { 12, "Daylight fluorescent (D 5700 Ã 7100K)" },
543 { 13, "Day white fluorescent (N 4600 Ã 5400K)" },
544 { 14, "Cool white fluorescent (W 3900 Ã 4500K)" },
545 { 15, "White fluorescent (WW 3200 Ã 3700K)" },
546 { 17, "Standard light A" },
547 { 18, "Standard light B" },
548 { 19, "Standard light C" },
553 { 24, "ISO studio tungsten" },
554 { 255, "other light source" },
557 static tag_map flash_values[] =
559 { 0x0000, "Flash did not fire." },
560 { 0x0001, "Flash fired." },
561 { 0x0005, "Strobe return light not detected." },
562 { 0x0007, "Strobe return light detected." },
563 { 0x0009, "Flash fired, compulsory flash mode" },
564 { 0x000D, "Flash fired, compulsory flash mode, return light not detected" },
565 { 0x000F, "Flash fired, compulsory flash mode, return light detected" },
566 { 0x0010, "Flash did not fire, compulsory flash mode" },
567 { 0x0018, "Flash did not fire, auto mode" },
568 { 0x0019, "Flash fired, auto mode" },
569 { 0x001D, "Flash fired, auto mode, return light not detected" },
570 { 0x001F, "Flash fired, auto mode, return light detected" },
571 { 0x0020, "No flash function" },
572 { 0x0041, "Flash fired, red-eye reduction mode" },
573 { 0x0045, "Flash fired, red-eye reduction mode, return light not detected" },
574 { 0x0047, "Flash fired, red-eye reduction mode, return light detected" },
575 { 0x0049, "Flash fired, compulsory flash mode, red-eye reduction mode" },
576 { 0x004D, "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected" },
577 { 0x004F, "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected" },
578 { 0x0059, "Flash fired, auto mode, red-eye reduction mode" },
579 { 0x005D, "Flash fired, auto mode, return light not detected, red-eye reduction mode" },
580 { 0x005F, "Flash fired, auto mode, return light detected, red-eye reduction mode" },
583 static tag_map sensing_method_values[] =
585 { 1, "Not defined" },
586 { 2, "One-chip color area sensor" },
587 { 3, "Two-chip color area sensor" },
588 { 4, "Three-chip color area sensor" },
589 { 5, "Color sequential area sensor" },
590 { 7, "Trilinear sensor" },
591 { 8, "Color sequential linear sensor" },
594 static tag_map custom_rendered_values[] =
596 { 0, "Normal process" },
597 { 1, "Custom process" },
600 static tag_map white_balance_values[] =
602 { 0, "Auto white balance" },
603 { 1, "Manual white balance" },
606 static tag_map scene_capture_type_values[] =
611 { 3, "Night scene" },
614 static tag_map gain_control_values[] =
617 { 1, "Low gain up" },
618 { 2, "High gain up" },
619 { 3, "Low gain down" },
620 { 4, "High gain down" },
623 static tag_map contrast_values[] =
630 static tag_map saturation_values[] =
633 { 1, "Low saturation" },
634 { 2, "High saturation" },
637 static tag_map sharpness_values[] =
644 static tag_map subject_distance_range_values[] =
649 { 3, "Distant view" },
652 #define focal_plane_resolution_unit_values resolution_unit_values
654 static tag_value_map exif_ifd_values[] =
656 VALUE_MAP_ENTRY(exposure_mode),
657 VALUE_MAP_ENTRY(color_space),
658 VALUE_MAP_ENTRY(exposure_program),
659 VALUE_MAP_ENTRY(metering_mode),
660 VALUE_MAP_ENTRY(light_source),
661 VALUE_MAP_ENTRY(flash),
662 VALUE_MAP_ENTRY(sensing_method),
663 VALUE_MAP_ENTRY(custom_rendered),
664 VALUE_MAP_ENTRY(white_balance),
665 VALUE_MAP_ENTRY(scene_capture_type),
666 VALUE_MAP_ENTRY(gain_control),
667 VALUE_MAP_ENTRY(contrast),
668 VALUE_MAP_ENTRY(saturation),
669 VALUE_MAP_ENTRY(sharpness),
670 VALUE_MAP_ENTRY(subject_distance_range),
671 VALUE_MAP_ENTRY(focal_plane_resolution_unit),
674 static tag_map exif_num_arrays[] =
676 { tag_iso_speed_ratings, "exif_iso_speed_ratings" },
677 { tag_subject_area, "exif_subject_area" },
678 { tag_subject_location, "exif_subject_location" },
682 save_exif_ifd_tags(i_img *im, imtiff *tiff) {
686 unsigned long maker_note_offset = 0;
687 size_t maker_note_size = 0;
689 for (tag_index = 0, entry = tiff->ifd;
690 tag_index < tiff->ifd_size; ++tag_index, ++entry) {
691 switch (entry->tag) {
692 case tag_user_comment:
693 /* I don't want to trash the source, so work on a copy */
694 user_comment = mymalloc(entry->size);
695 memcpy(user_comment, tiff->base + entry->offset, entry->size);
696 /* the first 8 bytes indicate the encoding, make them into spaces
697 for better presentation */
698 for (i = 0; i < entry->size && i < 8; ++i) {
699 if (user_comment[i] == '\0')
700 user_comment[i] = ' ';
702 /* find the actual end of the string */
703 while (i < entry->size && user_comment[i])
705 i_tags_add(&im->tags, "exif_user_comment", 0, user_comment, i, 0);
706 myfree(user_comment);
710 maker_note_offset = entry->offset;
711 maker_note_size = entry->size;
714 /* the following aren't processed yet */
716 case tag_spatial_frequency_response:
717 case tag_file_source:
719 case tag_cfa_pattern:
720 case tag_device_setting_description:
721 case tag_subject_area:
726 copy_string_tags(im, tiff, exif_ifd_string_tags, exif_ifd_string_tag_count);
727 copy_int_tags(im, tiff, exif_ifd_int_tags, exif_ifd_int_tag_count);
728 copy_rat_tags(im, tiff, exif_ifd_rat_tags, exif_ifd_rat_tag_count);
729 copy_name_tags(im, tiff, exif_ifd_values, ARRAY_COUNT(exif_ifd_values));
730 copy_num_array_tags(im, tiff, exif_num_arrays, ARRAY_COUNT(exif_num_arrays));
732 /* This trashes the IFD - make sure it's done last */
733 if (maker_note_offset) {
734 process_maker_note(im, tiff, maker_note_offset, maker_note_size);
738 static tag_map gps_ifd_string_tags[] =
740 { tag_gps_version_id, "exif_gps_version_id" },
741 { tag_gps_latitude_ref, "exif_gps_latitude_ref" },
742 { tag_gps_longitude_ref, "exif_gps_longitude_ref" },
743 { tag_gps_altitude_ref, "exif_gps_altitude_ref" },
744 { tag_gps_satellites, "exif_gps_satellites" },
745 { tag_gps_status, "exif_gps_status" },
746 { tag_gps_measure_mode, "exif_gps_measure_mode" },
747 { tag_gps_speed_ref, "exif_gps_speed_ref" },
748 { tag_gps_track_ref, "exif_gps_track_ref" },
751 static tag_map gps_ifd_int_tags[] =
753 { tag_gps_differential, "exif_gps_differential" },
756 static tag_map gps_ifd_rat_tags[] =
758 { tag_gps_altitude, "exif_gps_altitude" },
759 { tag_gps_time_stamp, "exif_gps_time_stamp" },
760 { tag_gps_dop, "exif_gps_dop" },
761 { tag_gps_speed, "exif_gps_speed" },
762 { tag_gps_track, "exif_track" }
765 static tag_map gps_differential_values [] =
767 { 0, "without differential correction" },
768 { 1, "Differential correction applied" },
771 static tag_value_map gps_ifd_values[] =
773 VALUE_MAP_ENTRY(gps_differential),
776 static tag_map gps_num_arrays[] =
778 { tag_gps_latitude, "exif_gps_latitude" },
779 { tag_gps_longitude, "exif_gps_longitude" },
783 save_gps_ifd_tags(i_img *im, imtiff *tiff) {
788 /* for (tag_index = 0, entry = tiff->ifd;
789 tag_index < tiff->ifd_size; ++tag_index, ++entry) {
790 switch (entry->tag) {
795 copy_string_tags(im, tiff, gps_ifd_string_tags,
796 ARRAY_COUNT(gps_ifd_string_tags));
797 copy_int_tags(im, tiff, gps_ifd_int_tags, ARRAY_COUNT(gps_ifd_int_tags));
798 copy_rat_tags(im, tiff, gps_ifd_rat_tags, ARRAY_COUNT(gps_ifd_rat_tags));
799 copy_name_tags(im, tiff, gps_ifd_values, ARRAY_COUNT(gps_ifd_values));
800 copy_num_array_tags(im, tiff, gps_num_arrays, ARRAY_COUNT(gps_num_arrays));
804 =item process_maker_note
806 This is a stub for processing the maker note tag.
808 Maker notes aren't covered by EXIF itself and in general aren't
809 documented by the manufacturers.
815 process_maker_note(i_img *im, imtiff *tiff, unsigned long offset, size_t size) {
816 /* this will be added in a future release */
822 =head2 High level TIFF functions
824 To avoid relying upon tifflib when we're not processing an image we
825 have some simple in-memory TIFF file management.
832 if (tiff_init(tiff, data_base, data_size)) {
836 Initialize the tiff data structure.
838 Scans for the byte order and version markers, and stores the offset to
839 the first IFD (IFD0 in EXIF) in first_ifd_offset.
845 tiff_init(imtiff *tiff, unsigned char *data, size_t length) {
850 if (length < 8) /* well... would have to be much bigger to be useful */
852 if (data[0] == 'M' && data[1] == 'M')
853 tiff->type = tt_motorola;
854 else if (data[0] == 'I' && data[1] == 'I')
855 tiff->type = tt_intel;
857 return 0; /* invalid header */
859 version = tiff_get16(tiff, 2);
863 tiff->first_ifd_offset = tiff_get32(tiff, 4);
864 if (tiff->first_ifd_offset > length || tiff->first_ifd_offset < 8)
879 Clean up the tiff structure initialized by tiff_init()
885 tiff_final(imtiff *tiff) {
886 tiff_clear_ifd(tiff);
892 if (tiff_load_ifd(tiff, offset)) {
896 Loads the IFD from the given offset into the tiff objects ifd.
898 This can fail if the IFD extends beyond end of file, or if any data
899 offsets combined with their sizes, extends beyond end of file.
901 Returns true on success.
907 tiff_load_ifd(imtiff *tiff, unsigned long offset) {
910 ifd_entry *entries = NULL;
914 tiff_clear_ifd(tiff);
916 /* rough check count + 1 entry + next offset */
917 if (offset + (2+12+4) > tiff->size) {
918 mm_log((2, "offset %uld beyond end off Exif block"));
922 count = tiff_get16(tiff, offset);
924 /* check we can fit the whole thing */
925 ifd_size = 2 + count * 12 + 4; /* count + count entries + next offset */
926 if (offset + ifd_size > tiff->size) {
927 mm_log((2, "offset %uld beyond end off Exif block"));
931 entries = mymalloc(count * sizeof(ifd_entry));
932 memset(entries, 0, count * sizeof(ifd_entry));
934 for (i = 0; i < count; ++i) {
935 ifd_entry *entry = entries + i;
936 entry->tag = tiff_get16(tiff, base);
937 entry->type = tiff_get16(tiff, base+2);
938 entry->count = tiff_get32(tiff, base+4);
939 if (entry->type >= 1 && entry->type <= ift_last) {
940 entry->item_size = type_sizes[entry->type];
941 entry->size = entry->item_size * entry->count;
942 if (entry->size / entry->item_size != entry->count) {
943 mm_log((1, "Integer overflow calculating tag data size processing EXIF block\n"));
946 else if (entry->size <= 4) {
947 entry->offset = base + 8;
950 entry->offset = tiff_get32(tiff, base+8);
951 if (entry->offset + entry->size > tiff->size) {
952 mm_log((2, "Invalid data offset processing IFD\n"));
965 tiff->ifd_size = count;
967 tiff->next_ifd = tiff_get32(tiff, base);
977 Releases any memory associated with the stored IFD and resets the IFD
980 This is called by tiff_load_ifd() and tiff_final().
986 tiff_clear_ifd(imtiff *tiff) {
987 if (tiff->ifd_size && tiff->ifd) {
995 =item tiff_get_tag_double
998 if (tiff_get_tag(tiff, index, &value)) {
1002 Attempts to retrieve a double value from the given index in the
1005 The value must have a count of 1.
1011 tiff_get_tag_double_array(imtiff *tiff, int index, double *result,
1014 unsigned long offset;
1015 if (index < 0 || index >= tiff->ifd_size) {
1016 m_fatal(3, "tiff_get_tag_double_array() tag index out of range");
1019 entry = tiff->ifd + index;
1020 if (array_index < 0 || array_index >= entry->count) {
1021 mm_log((3, "tiff_get_tag_double_array() array index out of range"));
1025 offset = entry->offset + array_index * entry->item_size;
1027 switch (entry->type) {
1029 *result = tiff_get16(tiff, offset);
1033 *result = tiff_get32(tiff, offset);
1037 *result = tiff_get_rat(tiff, offset);
1041 *result = tiff_get16s(tiff, offset);
1045 *result = tiff_get32s(tiff, offset);
1049 *result = tiff_get_rats(tiff, offset);
1053 *result = *(tiff->base + offset);
1061 =item tiff_get_tag_double
1064 if (tiff_get_tag(tiff, index, &value)) {
1068 Attempts to retrieve a double value from the given index in the
1071 The value must have a count of 1.
1077 tiff_get_tag_double(imtiff *tiff, int index, double *result) {
1079 if (index < 0 || index >= tiff->ifd_size) {
1080 m_fatal(3, "tiff_get_tag_double() index out of range");
1083 entry = tiff->ifd + index;
1084 if (entry->count != 1) {
1085 mm_log((3, "tiff_get_tag_double() called on tag with multiple values"));
1089 return tiff_get_tag_double_array(tiff, index, result, 0);
1093 =item tiff_get_tag_int_array
1096 if (tiff_get_tag_int_array(tiff, index, &value, array_index)) {
1100 Attempts to retrieve an integer value from the given index in the
1107 tiff_get_tag_int_array(imtiff *tiff, int index, int *result, int array_index) {
1109 unsigned long offset;
1110 if (index < 0 || index >= tiff->ifd_size) {
1111 m_fatal(3, "tiff_get_tag_int_array() tag index out of range");
1114 entry = tiff->ifd + index;
1115 if (array_index < 0 || array_index >= entry->count) {
1116 m_fatal(3, "tiff_get_tag_int_array() array index out of range");
1119 offset = entry->offset + array_index * entry->item_size;
1121 switch (entry->type) {
1123 *result = tiff_get16(tiff, offset);
1127 *result = tiff_get32(tiff, offset);
1131 *result = tiff_get16s(tiff, offset);
1135 *result = tiff_get32s(tiff, offset);
1139 *result = *(tiff->base + offset);
1147 =item tiff_get_tag_int
1150 if (tiff_get_tag_int(tiff, index, &value)) {
1154 Attempts to retrieve an integer value from the given index in the
1157 The value must have a count of 1.
1163 tiff_get_tag_int(imtiff *tiff, int index, int *result) {
1165 if (index < 0 || index >= tiff->ifd_size) {
1166 m_fatal(3, "tiff_get_tag_int() index out of range");
1169 entry = tiff->ifd + index;
1170 if (entry->count != 1) {
1171 mm_log((3, "tiff_get_tag_int() called on tag with multiple values"));
1175 return tiff_get_tag_int_array(tiff, index, result, 0);
1181 =head2 Table-based tag setters
1183 This set of functions checks for matches between the current IFD and
1184 tags supplied in an array, when there's a match it sets the
1185 appropriate tag in the image.
1191 Scans the IFD for integer tags and sets them in the image,
1197 copy_int_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count) {
1201 for (tag_index = 0, entry = tiff->ifd;
1202 tag_index < tiff->ifd_size; ++tag_index, ++entry) {
1203 for (i = 0; i < map_count; ++i) {
1205 if (map[i].tag == entry->tag
1206 && tiff_get_tag_int(tiff, tag_index, &value)) {
1207 i_tags_addn(&im->tags, map[i].name, 0, value);
1217 Scans the IFD for rational tags and sets them in the image.
1223 copy_rat_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count) {
1227 for (tag_index = 0, entry = tiff->ifd;
1228 tag_index < tiff->ifd_size; ++tag_index, ++entry) {
1229 for (i = 0; i < map_count; ++i) {
1231 if (map[i].tag == entry->tag
1232 && tiff_get_tag_double(tiff, tag_index, &value)) {
1233 i_tags_set_float2(&im->tags, map[i].name, 0, value, 6);
1241 =item copy_string_tags
1243 Scans the IFD for string tags and sets them in the image.
1249 copy_string_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count) {
1253 for (tag_index = 0, entry = tiff->ifd;
1254 tag_index < tiff->ifd_size; ++tag_index, ++entry) {
1255 for (i = 0; i < map_count; ++i) {
1256 if (map[i].tag == entry->tag) {
1257 int len = entry->type == ift_ascii ? entry->size - 1 : entry->size;
1258 i_tags_add(&im->tags, map[i].name, 0,
1259 (char const *)(tiff->base + entry->offset), len, 0);
1267 =item copy_num_array_tags
1269 Scans the IFD for arrays of numbers and sets them in the image.
1274 /* a more general solution would be better in some ways, but we don't need it */
1275 #define MAX_ARRAY_VALUES 10
1276 #define MAX_ARRAY_STRING (MAX_ARRAY_VALUES * 20)
1279 copy_num_array_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count) {
1280 int i, j, tag_index;
1283 for (tag_index = 0, entry = tiff->ifd;
1284 tag_index < tiff->ifd_size; ++tag_index, ++entry) {
1285 for (i = 0; i < map_count; ++i) {
1286 if (map[i].tag == entry->tag && entry->count <= MAX_ARRAY_VALUES) {
1287 if (entry->type == ift_rational || entry->type == ift_srational) {
1289 char workstr[MAX_ARRAY_STRING];
1291 for (j = 0; j < entry->count; ++j) {
1292 if (!tiff_get_tag_double_array(tiff, tag_index, &value, j)) {
1293 m_fatal(3, "unexpected failure from tiff_get_tag_double_array(..., %d, ..., %d)\n", tag_index, j);
1296 strcat(workstr, " ");
1297 sprintf(workstr + strlen(workstr), "%.6g", value);
1299 i_tags_add(&im->tags, map[i].name, 0, workstr, -1, 0);
1301 else if (entry->type == ift_short || entry->type == ift_long
1302 || entry->type == ift_sshort || entry->type == ift_slong
1303 || entry->type == ift_byte) {
1305 char workstr[MAX_ARRAY_STRING];
1307 for (j = 0; j < entry->count; ++j) {
1308 if (!tiff_get_tag_int_array(tiff, tag_index, &value, j)) {
1309 m_fatal(3, "unexpected failure from tiff_get_tag_int_array(..., %d, ..., %d)\n", tag_index, j);
1312 strcat(workstr, " ");
1313 sprintf(workstr + strlen(workstr), "%d", value);
1315 i_tags_add(&im->tags, map[i].name, 0, workstr, -1, 0);
1324 =item copy_name_tags
1326 This function maps integer values to descriptions for those values.
1328 In general we handle the integer value through copy_int_tags() and
1329 then the same tage with a "_name" suffix here.
1335 copy_name_tags(i_img *im, imtiff *tiff, tag_value_map *map, int map_count) {
1336 int i, j, tag_index;
1339 for (tag_index = 0, entry = tiff->ifd;
1340 tag_index < tiff->ifd_size; ++tag_index, ++entry) {
1341 for (i = 0; i < map_count; ++i) {
1343 if (map[i].tag == entry->tag
1344 && tiff_get_tag_int(tiff, tag_index, &value)) {
1345 tag_map const *found = NULL;
1346 for (j = 0; j < map[i].map_count; ++j) {
1347 if (value == map[i].map[j].tag) {
1348 found = map[i].map + j;
1353 i_tags_add(&im->tags, map[i].name, 0, found->name, -1, 0);
1365 =head2 Low level data access functions
1367 These functions use the byte order in the tiff object to extract
1368 various types of data from the tiff data.
1370 These functions will abort if called with an out of range offset.
1372 The intent is that any offset checks should have been done by the caller.
1378 Retrieve a 16 bit unsigned integer from offset.
1384 tiff_get16(imtiff *tiff, unsigned long offset) {
1385 if (offset + 2 > tiff->size)
1386 m_fatal(3, "attempt to get16 at %uld in %uld image", offset, tiff->size);
1388 if (tiff->type == tt_intel)
1389 return tiff->base[offset] + 0x100 * tiff->base[offset+1];
1391 return tiff->base[offset+1] + 0x100 * tiff->base[offset];
1397 Retrieve a 32-bit unsigned integer from offset.
1403 tiff_get32(imtiff *tiff, unsigned long offset) {
1404 if (offset + 4 > tiff->size)
1405 m_fatal(3, "attempt to get16 at %uld in %uld image", offset, tiff->size);
1407 if (tiff->type == tt_intel)
1408 return tiff->base[offset] + 0x100 * tiff->base[offset+1]
1409 + 0x10000 * tiff->base[offset+2] + 0x1000000 * tiff->base[offset+3];
1411 return tiff->base[offset+3] + 0x100 * tiff->base[offset+2]
1412 + 0x10000 * tiff->base[offset+1] + 0x1000000 * tiff->base[offset];
1416 =item tiff_get_bytes
1418 Retrieve a byte string from offset.
1420 This isn't used much, you can usually deal with the data in-situ.
1421 This is intended for use when you need to modify the data in some way.
1427 tiff_get_bytes(imtiff *tiff, unsigned char *data, size_t offset,
1429 if (offset + size > tiff->size)
1432 memcpy(data, tiff->base+offset, size);
1440 Retrieve a 16-bit signed integer from offset.
1446 tiff_get16s(imtiff *tiff, unsigned long offset) {
1449 if (offset + 2 > tiff->size)
1450 m_fatal(3, "attempt to get16 at %uld in %uld image", offset, tiff->size);
1452 if (tiff->type == tt_intel)
1453 result = tiff->base[offset] + 0x100 * tiff->base[offset+1];
1455 result = tiff->base[offset+1] + 0x100 * tiff->base[offset];
1457 if (result > 0x7FFF)
1466 Retrieve a 32-bit signed integer from offset.
1472 tiff_get32s(imtiff *tiff, unsigned long offset) {
1475 if (offset + 4 > tiff->size)
1476 m_fatal(3, "attempt to get16 at %uld in %uld image", offset, tiff->size);
1478 if (tiff->type == tt_intel)
1479 work = tiff->base[offset] + 0x100 * tiff->base[offset+1]
1480 + 0x10000 * tiff->base[offset+2] + 0x1000000 * tiff->base[offset+3];
1482 work = tiff->base[offset+3] + 0x100 * tiff->base[offset+2]
1483 + 0x10000 * tiff->base[offset+1] + 0x1000000 * tiff->base[offset];
1485 /* not really needed on 32-bit int machines */
1486 if (work > 0x7FFFFFFFUL)
1487 return work - 0x80000000UL;
1495 Retrieve an unsigned rational from offset.
1501 tiff_get_rat(imtiff *tiff, unsigned long offset) {
1502 unsigned long numer, denom;
1503 if (offset + 8 > tiff->size)
1504 m_fatal(3, "attempt to get_rat at %lu in %lu image", offset, tiff->size);
1506 numer = tiff_get32(tiff, offset);
1507 denom = tiff_get32(tiff, offset+4);
1513 return (double)numer / denom;
1519 Retrieve an signed rational from offset.
1525 tiff_get_rats(imtiff *tiff, unsigned long offset) {
1527 if (offset + 8 > tiff->size)
1528 m_fatal(3, "attempt to get_rat at %lu in %lu image", offset, tiff->size);
1530 numer = tiff_get32s(tiff, offset);
1531 denom = tiff_get32s(tiff, offset+4);
1537 return (double)numer / denom;
1547 http://www.exif.org/
1551 Tony Cook <tony@imager.perl.org>