+#include "imager.h"
#include "imexif.h"
#include <stdlib.h>
#include <float.h>
+#include <string.h>
+#include <stdio.h>
/*
=head1 NAME
=head1 SYNOPSIS
- if (i_int_decode_exif(im, app1data, app1datasize)) {
+ if (im_decode_exif(im, app1data, app1datasize)) {
// exif block seen
}
int tag;
int type;
int count;
+ int item_size;
int size;
int offset;
} ifd_entry;
#define tag_f_number 0x829D
#define tag_exposure_program 0x8822
#define tag_spectral_sensitivity 0x8824
-#define tag_iso_speed_rating 0x8827
+#define tag_iso_speed_ratings 0x8827
#define tag_oecf 0x8828
#define tag_shutter_speed 0x9201
#define tag_aperture 0x9202
#define tag_device_setting_description 0xA40B
#define tag_subject_distance_range 0xA40C
+/* GPS tags */
+#define tag_gps_version_id 0
+#define tag_gps_latitude_ref 1
+#define tag_gps_latitude 2
+#define tag_gps_longitude_ref 3
+#define tag_gps_longitude 4
+#define tag_gps_altitude_ref 5
+#define tag_gps_altitude 6
+#define tag_gps_time_stamp 7
+#define tag_gps_satellites 8
+#define tag_gps_status 9
+#define tag_gps_measure_mode 10
+#define tag_gps_dop 11
+#define tag_gps_speed_ref 12
+#define tag_gps_speed 13
+#define tag_gps_track_ref 14
+#define tag_gps_track 15
+#define tag_gps_img_direction_ref 16
+#define tag_gps_img_direction 17
+#define tag_gps_map_datum 18
+#define tag_gps_dest_latitude_ref 19
+#define tag_gps_dest_latitude 20
+#define tag_gps_dest_longitude_ref 21
+#define tag_gps_dest_longitude 22
+#define tag_gps_dest_bearing_ref 23
+#define tag_gps_dest_bearing 24
+#define tag_gps_dest_distance_ref 25
+#define tag_gps_dest_distance 26
+#define tag_gps_processing_method 27
+#define tag_gps_area_information 28
+#define tag_gps_date_stamp 29
+#define tag_gps_differential 30
+
/* don't use this on pointers */
#define ARRAY_COUNT(array) (sizeof(array)/sizeof(*array))
static int tiff_load_ifd(imtiff *tiff, unsigned long offset);
static void tiff_final(imtiff *tiff);
static void tiff_clear_ifd(imtiff *tiff);
+#if 0 /* currently unused, but that may change */
static int tiff_get_bytes(imtiff *tiff, unsigned char *to, size_t offset,
size_t count);
+#endif
static int tiff_get_tag_double(imtiff *, int index, double *result);
static int tiff_get_tag_int(imtiff *, int index, int *result);
static unsigned tiff_get16(imtiff *, unsigned long offset);
static int tiff_get32s(imtiff *, unsigned long offset);
static double tiff_get_rat(imtiff *, unsigned long offset);
static double tiff_get_rats(imtiff *, unsigned long offset);
-static void save_ifd0_tags(i_img *im, imtiff *tiff, unsigned long *exif_ifd_offset);
+static void save_ifd0_tags(i_img *im, imtiff *tiff, unsigned long *exif_ifd_offset, unsigned long *gps_ifd_offset);
static void save_exif_ifd_tags(i_img *im, imtiff *tiff);
+static void save_gps_ifd_tags(i_img *im, imtiff *tiff);
static void
copy_string_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
static void
static void
copy_rat_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
static void
+copy_num_array_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count);
+static void
copy_name_tags(i_img *im, imtiff *tiff, tag_value_map *map, int map_count);
static void process_maker_note(i_img *im, imtiff *tiff, unsigned long offset, size_t size);
=over
-=item i_int_decode_exit
+=item im_decode_exif
-i_int_decode_exif(im, data_base, data_size);
+im_decode_exif(im, data_base, data_size);
-The data from data_base for data_size bytes will be scanned for EXIF
-data.
+The data from C<data_base> for C<data_size> bytes will be scanned for
+EXIF data.
Any data found will be used to set tags in the supplied image.
write to the log. In no case should this code exit when supplied
invalid data.
-Returns true if an Exif header was seen.
+Returns true if an EXIF header was seen.
+=cut
*/
int
-i_int_decode_exif(i_img *im, unsigned char *data, size_t length) {
+im_decode_exif(i_img *im, unsigned char *data, size_t length) {
imtiff tiff;
unsigned long exif_ifd_offset = 0;
- unsigned long ifd1_offset;
- /* basic checks - must start with "Exif\0\0" */
-
- if (length < 6 || memcmp(data, "Exif\0\0", 6) != 0) {
- return 0;
- }
-
- data += 6;
- length -= 6;
+ unsigned long gps_ifd_offset = 0;
if (!tiff_init(&tiff, data, length)) {
mm_log((2, "Exif header found, but no valid TIFF header\n"));
return 1;
}
- save_ifd0_tags(im, &tiff, &exif_ifd_offset);
+ save_ifd0_tags(im, &tiff, &exif_ifd_offset, &gps_ifd_offset);
if (exif_ifd_offset) {
if (tiff_load_ifd(&tiff, exif_ifd_offset)) {
}
}
+ if (gps_ifd_offset) {
+ if (tiff_load_ifd(&tiff, gps_ifd_offset)) {
+ save_gps_ifd_tags(im, &tiff);
+ }
+ else {
+ mm_log((2, "Could not load GPS IFD\n"));
+ }
+ }
+
tiff_final(&tiff);
return 1;
=item save_ifd0_tags
-save_ifd0_tags(im, tiff, &exif_ifd_offset)
+save_ifd0_tags(im, tiff, &exif_ifd_offset, &gps_ifd_offset)
Scans the currently loaded IFD for tags expected in IFD0 and sets them
in the image.
static tag_map ifd0_string_tags[] =
{
- tag_make, "exif_make",
- tag_model, "exif_model",
- tag_copyright, "exif_copyright",
- tag_software, "exif_software",
- tag_artist, "exif_artist",
- tag_date_time, "exif_date_time",
- tag_image_description, "exif_image_description",
+ { tag_make, "exif_make" },
+ { tag_model, "exif_model" },
+ { tag_copyright, "exif_copyright" },
+ { tag_software, "exif_software" },
+ { tag_artist, "exif_artist" },
+ { tag_date_time, "exif_date_time" },
+ { tag_image_description, "exif_image_description" },
};
static const int ifd0_string_tag_count = ARRAY_COUNT(ifd0_string_tags);
};
static void
-save_ifd0_tags(i_img *im, imtiff *tiff, unsigned long *exif_ifd_offset) {
- int i, tag_index;
+save_ifd0_tags(i_img *im, imtiff *tiff, unsigned long *exif_ifd_offset,
+ unsigned long *gps_ifd_offset) {
+ int tag_index;
int work;
ifd_entry *entry;
if (tiff_get_tag_int(tiff, tag_index, &work))
*exif_ifd_offset = work;
break;
+
+ case tag_gps_ifd:
+ if (tiff_get_tag_int(tiff, tag_index, &work))
+ *gps_ifd_offset = work;
+ break;
}
}
copy_int_tags(im, tiff, ifd0_int_tags, ifd0_int_tag_count);
copy_rat_tags(im, tiff, ifd0_rat_tags, ARRAY_COUNT(ifd0_rat_tags));
copy_name_tags(im, tiff, ifd0_values, ARRAY_COUNT(ifd0_values));
+ /* copy_num_array_tags(im, tiff, ifd0_num_arrays, ARRAY_COUNT(ifd0_num_arrays)); */
}
/*
{
{ tag_color_space, "exif_color_space" },
{ tag_exposure_program, "exif_exposure_program" },
- { tag_iso_speed_rating, "exif_iso_speed_rating" },
{ tag_metering_mode, "exif_metering_mode" },
{ tag_light_source, "exif_light_source" },
{ tag_flash, "exif_flash" },
VALUE_MAP_ENTRY(focal_plane_resolution_unit),
};
+static tag_map exif_num_arrays[] =
+ {
+ { tag_iso_speed_ratings, "exif_iso_speed_ratings" },
+ { tag_subject_area, "exif_subject_area" },
+ { tag_subject_location, "exif_subject_location" },
+ };
+
static void
save_exif_ifd_tags(i_img *im, imtiff *tiff) {
int i, tag_index;
- int work;
ifd_entry *entry;
char *user_comment;
unsigned long maker_note_offset = 0;
memcpy(user_comment, tiff->base + entry->offset, entry->size);
/* the first 8 bytes indicate the encoding, make them into spaces
for better presentation */
- for (i = 0; i < 8; ++i) {
+ for (i = 0; i < entry->size && i < 8; ++i) {
if (user_comment[i] == '\0')
user_comment[i] = ' ';
}
/* find the actual end of the string */
while (i < entry->size && user_comment[i])
++i;
- i_tags_add(&im->tags, "exif_user_comment", 0, user_comment, i, 0);
+ i_tags_set(&im->tags, "exif_user_comment", user_comment, i);
myfree(user_comment);
break;
copy_int_tags(im, tiff, exif_ifd_int_tags, exif_ifd_int_tag_count);
copy_rat_tags(im, tiff, exif_ifd_rat_tags, exif_ifd_rat_tag_count);
copy_name_tags(im, tiff, exif_ifd_values, ARRAY_COUNT(exif_ifd_values));
+ copy_num_array_tags(im, tiff, exif_num_arrays, ARRAY_COUNT(exif_num_arrays));
/* This trashes the IFD - make sure it's done last */
if (maker_note_offset) {
}
}
+static tag_map gps_ifd_string_tags[] =
+ {
+ { tag_gps_version_id, "exif_gps_version_id" },
+ { tag_gps_latitude_ref, "exif_gps_latitude_ref" },
+ { tag_gps_longitude_ref, "exif_gps_longitude_ref" },
+ { tag_gps_altitude_ref, "exif_gps_altitude_ref" },
+ { tag_gps_satellites, "exif_gps_satellites" },
+ { tag_gps_status, "exif_gps_status" },
+ { tag_gps_measure_mode, "exif_gps_measure_mode" },
+ { tag_gps_speed_ref, "exif_gps_speed_ref" },
+ { tag_gps_track_ref, "exif_gps_track_ref" },
+ };
+
+static tag_map gps_ifd_int_tags[] =
+ {
+ { tag_gps_differential, "exif_gps_differential" },
+ };
+
+static tag_map gps_ifd_rat_tags[] =
+ {
+ { tag_gps_altitude, "exif_gps_altitude" },
+ { tag_gps_time_stamp, "exif_gps_time_stamp" },
+ { tag_gps_dop, "exif_gps_dop" },
+ { tag_gps_speed, "exif_gps_speed" },
+ { tag_gps_track, "exif_track" }
+ };
+
+static tag_map gps_differential_values [] =
+ {
+ { 0, "without differential correction" },
+ { 1, "Differential correction applied" },
+ };
+
+static tag_value_map gps_ifd_values[] =
+ {
+ VALUE_MAP_ENTRY(gps_differential),
+ };
+
+static tag_map gps_num_arrays[] =
+ {
+ { tag_gps_latitude, "exif_gps_latitude" },
+ { tag_gps_longitude, "exif_gps_longitude" },
+ };
+
+static void
+save_gps_ifd_tags(i_img *im, imtiff *tiff) {
+ /* int i, tag_index;
+ int work;
+ ifd_entry *entry; */
+
+ /* for (tag_index = 0, entry = tiff->ifd;
+ tag_index < tiff->ifd_size; ++tag_index, ++entry) {
+ switch (entry->tag) {
+ break;
+ }
+ }*/
+
+ copy_string_tags(im, tiff, gps_ifd_string_tags,
+ ARRAY_COUNT(gps_ifd_string_tags));
+ copy_int_tags(im, tiff, gps_ifd_int_tags, ARRAY_COUNT(gps_ifd_int_tags));
+ copy_rat_tags(im, tiff, gps_ifd_rat_tags, ARRAY_COUNT(gps_ifd_rat_tags));
+ copy_name_tags(im, tiff, gps_ifd_values, ARRAY_COUNT(gps_ifd_values));
+ copy_num_array_tags(im, tiff, gps_num_arrays, ARRAY_COUNT(gps_num_arrays));
+}
+
/*
=item process_maker_note
/* rough check count + 1 entry + next offset */
if (offset + (2+12+4) > tiff->size) {
- mm_log((2, "offset %uld beyond end off Exif block"));
+ mm_log((2, "offset %lu beyond end off Exif block", offset));
return 0;
}
/* check we can fit the whole thing */
ifd_size = 2 + count * 12 + 4; /* count + count entries + next offset */
if (offset + ifd_size > tiff->size) {
- mm_log((2, "offset %uld beyond end off Exif block"));
+ mm_log((2, "offset %lu beyond end off Exif block", offset));
return 0;
}
entry->tag = tiff_get16(tiff, base);
entry->type = tiff_get16(tiff, base+2);
entry->count = tiff_get32(tiff, base+4);
- if (entry->type >= 1 || entry->type <= ift_last) {
- int data_size = type_sizes[entry->type] * entry->count;
- entry->size = data_size;
- if (data_size <= 4) {
+ if (entry->type >= 1 && entry->type <= ift_last) {
+ entry->item_size = type_sizes[entry->type];
+ entry->size = entry->item_size * entry->count;
+ if (entry->size / entry->item_size != entry->count) {
+ myfree(entries);
+ mm_log((1, "Integer overflow calculating tag data size processing EXIF block\n"));
+ return 0;
+ }
+ else if (entry->size <= 4) {
entry->offset = base + 8;
}
else {
entry->offset = tiff_get32(tiff, base+8);
- if (entry->offset + data_size > tiff->size) {
- mm_log((2, "Invalid data offset processing IFD"));
+ if (entry->offset + entry->size > tiff->size) {
+ mm_log((2, "Invalid data offset processing IFD\n"));
myfree(entries);
return 0;
}
static void
tiff_clear_ifd(imtiff *tiff) {
- int i;
-
if (tiff->ifd_size && tiff->ifd) {
myfree(tiff->ifd);
tiff->ifd_size = 0;
*/
static int
-tiff_get_tag_double(imtiff *tiff, int index, double *result) {
+tiff_get_tag_double_array(imtiff *tiff, int index, double *result,
+ int array_index) {
ifd_entry *entry;
+ unsigned long offset;
if (index < 0 || index >= tiff->ifd_size) {
- m_fatal(3, "tiff_get_tag_double() index out of range");
+ mm_log((3, "tiff_get_tag_double_array() tag index out of range"));
+ return 0;
}
entry = tiff->ifd + index;
- if (entry->count != 1) {
- mm_log((3, "tiff_get_tag_double() called on tag with multiple values"));
+ if (array_index < 0 || array_index >= entry->count) {
+ mm_log((3, "tiff_get_tag_double_array() array index out of range"));
return 0;
}
+ offset = entry->offset + array_index * entry->item_size;
+
switch (entry->type) {
case ift_short:
- *result = tiff_get16(tiff, entry->offset);
+ *result = tiff_get16(tiff, offset);
return 1;
case ift_long:
- *result = tiff_get32(tiff, entry->offset);
+ *result = tiff_get32(tiff, offset);
return 1;
case ift_rational:
- *result = tiff_get_rat(tiff, entry->offset);
+ *result = tiff_get_rat(tiff, offset);
return 1;
case ift_sshort:
- *result = tiff_get16s(tiff, entry->offset);
+ *result = tiff_get16s(tiff, offset);
return 1;
case ift_slong:
- *result = tiff_get32s(tiff, entry->offset);
+ *result = tiff_get32s(tiff, offset);
return 1;
case ift_srational:
- *result = tiff_get_rats(tiff, entry->offset);
+ *result = tiff_get_rats(tiff, offset);
+ return 1;
+
+ case ift_byte:
+ *result = *(tiff->base + offset);
return 1;
}
}
/*
-=item tiff_get_tag_int
+=item tiff_get_tag_double
- int value;
- if (tiff_get_tag_int(tiff, index, &value)) {
+ double value;
+ if (tiff_get_tag(tiff, index, &value)) {
// process value
}
-Attempts to retrieve an integer value from the given index in the
+Attempts to retrieve a double value from the given index in the
current IFD.
The value must have a count of 1.
*/
static int
-tiff_get_tag_int(imtiff *tiff, int index, int *result) {
+tiff_get_tag_double(imtiff *tiff, int index, double *result) {
ifd_entry *entry;
if (index < 0 || index >= tiff->ifd_size) {
- m_fatal(3, "tiff_get_tag_int() index out of range");
+ mm_log((3, "tiff_get_tag_double() index out of range"));
+ return 0;
}
entry = tiff->ifd + index;
if (entry->count != 1) {
- mm_log((3, "tiff_get_tag_int() called on tag with multiple values"));
+ mm_log((3, "tiff_get_tag_double() called on tag with multiple values"));
+ return 0;
+ }
+
+ return tiff_get_tag_double_array(tiff, index, result, 0);
+}
+
+/*
+=item tiff_get_tag_int_array
+
+ int value;
+ if (tiff_get_tag_int_array(tiff, index, &value, array_index)) {
+ // process value
+ }
+
+Attempts to retrieve an integer value from the given index in the
+current IFD.
+
+=cut
+*/
+
+static int
+tiff_get_tag_int_array(imtiff *tiff, int index, int *result, int array_index) {
+ ifd_entry *entry;
+ unsigned long offset;
+ if (index < 0 || index >= tiff->ifd_size) {
+ mm_log((3, "tiff_get_tag_int_array() tag index out of range"));
+ return 0;
+ }
+
+ entry = tiff->ifd + index;
+ if (array_index < 0 || array_index >= entry->count) {
+ mm_log((3, "tiff_get_tag_int_array() array index out of range"));
return 0;
}
+ offset = entry->offset + array_index * entry->item_size;
+
switch (entry->type) {
case ift_short:
- *result = tiff_get16(tiff, entry->offset);
+ *result = tiff_get16(tiff, offset);
return 1;
case ift_long:
- *result = tiff_get32(tiff, entry->offset);
+ *result = tiff_get32(tiff, offset);
return 1;
case ift_sshort:
- *result = tiff_get16s(tiff, entry->offset);
+ *result = tiff_get16s(tiff, offset);
return 1;
case ift_slong:
- *result = tiff_get32s(tiff, entry->offset);
+ *result = tiff_get32s(tiff, offset);
+ return 1;
+
+ case ift_byte:
+ *result = *(tiff->base + offset);
return 1;
}
return 0;
}
+/*
+=item tiff_get_tag_int
+
+ int value;
+ if (tiff_get_tag_int(tiff, index, &value)) {
+ // process value
+ }
+
+Attempts to retrieve an integer value from the given index in the
+current IFD.
+
+The value must have a count of 1.
+
+=cut
+*/
+
+static int
+tiff_get_tag_int(imtiff *tiff, int index, int *result) {
+ ifd_entry *entry;
+ if (index < 0 || index >= tiff->ifd_size) {
+ mm_log((3, "tiff_get_tag_int() index out of range"));
+ return 0;
+ }
+
+ entry = tiff->ifd + index;
+ if (entry->count != 1) {
+ mm_log((3, "tiff_get_tag_int() called on tag with multiple values"));
+ return 0;
+ }
+
+ return tiff_get_tag_int_array(tiff, index, result, 0);
+}
+
/*
=back
int value;
if (map[i].tag == entry->tag
&& tiff_get_tag_int(tiff, tag_index, &value)) {
- i_tags_addn(&im->tags, map[i].name, 0, value);
+ i_tags_setn(&im->tags, map[i].name, value);
break;
}
}
for (i = 0; i < map_count; ++i) {
if (map[i].tag == entry->tag) {
int len = entry->type == ift_ascii ? entry->size - 1 : entry->size;
- i_tags_add(&im->tags, map[i].name, 0,
- (char const *)(tiff->base + entry->offset), len, 0);
+ i_tags_set(&im->tags, map[i].name,
+ (char const *)(tiff->base + entry->offset), len);
+ break;
+ }
+ }
+ }
+}
+
+/*
+=item copy_num_array_tags
+
+Scans the IFD for arrays of numbers and sets them in the image.
+
+=cut
+*/
+
+/* a more general solution would be better in some ways, but we don't need it */
+#define MAX_ARRAY_VALUES 10
+#define MAX_ARRAY_STRING (MAX_ARRAY_VALUES * 20)
+
+static void
+copy_num_array_tags(i_img *im, imtiff *tiff, tag_map *map, int map_count) {
+ int i, j, tag_index;
+ ifd_entry *entry;
+
+ for (tag_index = 0, entry = tiff->ifd;
+ tag_index < tiff->ifd_size; ++tag_index, ++entry) {
+ for (i = 0; i < map_count; ++i) {
+ if (map[i].tag == entry->tag && entry->count <= MAX_ARRAY_VALUES) {
+ if (entry->type == ift_rational || entry->type == ift_srational) {
+ double value;
+ char workstr[MAX_ARRAY_STRING];
+ size_t len = 0, item_len;
+ *workstr = '\0';
+ for (j = 0; j < entry->count; ++j) {
+ if (!tiff_get_tag_double_array(tiff, tag_index, &value, j)) {
+ mm_log((3, "unexpected failure from tiff_get_tag_double_array(..., %d, ..., %d)\n", tag_index, j));
+ return;
+ }
+ if (len >= sizeof(workstr) - 1) {
+ mm_log((3, "Buffer would overflow reading tag %#x\n", entry->tag));
+ return;
+ }
+ if (j) {
+ strcat(workstr, " ");
+ ++len;
+ }
+#ifdef IMAGER_SNPRINTF
+ item_len = snprintf(workstr + len, sizeof(workstr)-len, "%.6g", value);
+#else
+ item_len = sprintf(workstr + len, "%.6g", value);
+#endif
+ len += item_len;
+ }
+ i_tags_set(&im->tags, map[i].name, workstr, -1);
+ }
+ else if (entry->type == ift_short || entry->type == ift_long
+ || entry->type == ift_sshort || entry->type == ift_slong
+ || entry->type == ift_byte) {
+ int value;
+ char workstr[MAX_ARRAY_STRING];
+ size_t len = 0, item_len;
+ *workstr = '\0';
+ for (j = 0; j < entry->count; ++j) {
+ if (!tiff_get_tag_int_array(tiff, tag_index, &value, j)) {
+ mm_log((3, "unexpected failure from tiff_get_tag_int_array(..., %d, ..., %d)\n", tag_index, j));
+ return;
+ }
+ if (len >= sizeof(workstr) - 1) {
+ mm_log((3, "Buffer would overflow reading tag %#x\n", entry->tag));
+ return;
+ }
+ if (j) {
+ strcat(workstr, " ");
+ ++len;
+ }
+#ifdef IMAGER_SNPRINTF
+ item_len = snprintf(workstr + len, sizeof(workstr) - len, "%d", value);
+#else
+ item_len = sprintf(workstr + len, "%d", value);
+#endif
+ len += item_len;
+ }
+ i_tags_set(&im->tags, map[i].name, workstr, -1);
+ }
break;
}
}
}
}
if (found) {
- i_tags_add(&im->tags, map[i].name, 0, found->name, -1, 0);
+ i_tags_set(&im->tags, map[i].name, found->name, -1);
}
break;
}
static unsigned
tiff_get16(imtiff *tiff, unsigned long offset) {
- if (offset + 2 > tiff->size)
- m_fatal(3, "attempt to get16 at %uld in %uld image", offset, tiff->size);
+ if (offset + 2 > tiff->size) {
+ mm_log((3, "attempt to get16 at %lu in %lu image", offset,
+ (unsigned long)tiff->size));
+ return 0;
+ }
if (tiff->type == tt_intel)
return tiff->base[offset] + 0x100 * tiff->base[offset+1];
static unsigned
tiff_get32(imtiff *tiff, unsigned long offset) {
- if (offset + 4 > tiff->size)
- m_fatal(3, "attempt to get16 at %uld in %uld image", offset, tiff->size);
+ if (offset + 4 > tiff->size) {
+ mm_log((3, "attempt to get16 at %lu in %lu image", offset,
+ (unsigned long)tiff->size));
+ return 0;
+ }
if (tiff->type == tt_intel)
return tiff->base[offset] + 0x100 * tiff->base[offset+1]
+ 0x10000 * tiff->base[offset+1] + 0x1000000 * tiff->base[offset];
}
+#if 0 /* currently unused, but that may change */
+
/*
=item tiff_get_bytes
return 1;
}
+#endif
+
/*
=item tiff_get16s
tiff_get16s(imtiff *tiff, unsigned long offset) {
int result;
- if (offset + 2 > tiff->size)
- m_fatal(3, "attempt to get16 at %uld in %uld image", offset, tiff->size);
+ if (offset + 2 > tiff->size) {
+ mm_log((3, "attempt to get16 at %lu in %lu image", offset,
+ (unsigned long)tiff->size));
+ return 0;
+ }
if (tiff->type == tt_intel)
result = tiff->base[offset] + 0x100 * tiff->base[offset+1];
tiff_get32s(imtiff *tiff, unsigned long offset) {
unsigned work;
- if (offset + 4 > tiff->size)
- m_fatal(3, "attempt to get16 at %uld in %uld image", offset, tiff->size);
+ if (offset + 4 > tiff->size) {
+ mm_log((3, "attempt to get16 at %lu in %lu image", offset,
+ (unsigned long)tiff->size));
+ return 0;
+ }
if (tiff->type == tt_intel)
work = tiff->base[offset] + 0x100 * tiff->base[offset+1]
static double
tiff_get_rat(imtiff *tiff, unsigned long offset) {
unsigned long numer, denom;
- if (offset + 8 > tiff->size)
- m_fatal(3, "attempt to get_rat at %lu in %lu image", offset, tiff->size);
+ if (offset + 8 > tiff->size) {
+ mm_log((3, "attempt to get_rat at %lu in %lu image", offset,
+ (unsigned long)tiff->size));
+ return 0;
+ }
numer = tiff_get32(tiff, offset);
denom = tiff_get32(tiff, offset+4);
static double
tiff_get_rats(imtiff *tiff, unsigned long offset) {
long numer, denom;
- if (offset + 8 > tiff->size)
- m_fatal(3, "attempt to get_rat at %lu in %lu image", offset, tiff->size);
+ if (offset + 8 > tiff->size) {
+ mm_log((3, "attempt to get_rat at %lu in %lu image", offset,
+ (unsigned long)tiff->size));
+ return 0;
+ }
numer = tiff_get32s(tiff, offset);
denom = tiff_get32s(tiff, offset+4);
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION