|
|
} | } |
| |
| |
|
/* Adjust Exif image parameters. |
|
* |
|
* We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. |
|
*/ |
|
|
|
LOCAL(void) |
|
adjust_exif_parameters (JOCTET FAR * data, unsigned int length, |
|
JDIMENSION new_width, JDIMENSION new_height) |
|
{ |
|
boolean is_motorola; /* Flag for byte order */ |
|
unsigned int number_of_tags, tagnum; |
|
unsigned int firstoffset, offset; |
|
JDIMENSION new_value; |
|
|
|
if (length < 12) return; /* Length of an IFD entry */ |
|
|
|
/* Discover byte order */ |
|
if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) |
|
is_motorola = FALSE; |
|
else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) |
|
is_motorola = TRUE; |
|
else |
|
return; |
|
|
|
/* Check Tag Mark */ |
|
if (is_motorola) { |
|
if (GETJOCTET(data[2]) != 0) return; |
|
if (GETJOCTET(data[3]) != 0x2A) return; |
|
} else { |
|
if (GETJOCTET(data[3]) != 0) return; |
|
if (GETJOCTET(data[2]) != 0x2A) return; |
|
} |
|
|
|
/* Get first IFD offset (offset to IFD0) */ |
|
if (is_motorola) { |
|
if (GETJOCTET(data[4]) != 0) return; |
|
if (GETJOCTET(data[5]) != 0) return; |
|
firstoffset = GETJOCTET(data[6]); |
|
firstoffset <<= 8; |
|
firstoffset += GETJOCTET(data[7]); |
|
} else { |
|
if (GETJOCTET(data[7]) != 0) return; |
|
if (GETJOCTET(data[6]) != 0) return; |
|
firstoffset = GETJOCTET(data[5]); |
|
firstoffset <<= 8; |
|
firstoffset += GETJOCTET(data[4]); |
|
} |
|
if (firstoffset > length - 2) return; /* check end of data segment */ |
|
|
|
/* Get the number of directory entries contained in this IFD */ |
|
if (is_motorola) { |
|
number_of_tags = GETJOCTET(data[firstoffset]); |
|
number_of_tags <<= 8; |
|
number_of_tags += GETJOCTET(data[firstoffset+1]); |
|
} else { |
|
number_of_tags = GETJOCTET(data[firstoffset+1]); |
|
number_of_tags <<= 8; |
|
number_of_tags += GETJOCTET(data[firstoffset]); |
|
} |
|
if (number_of_tags == 0) return; |
|
firstoffset += 2; |
|
|
|
/* Search for ExifSubIFD offset Tag in IFD0 */ |
|
for (;;) { |
|
if (firstoffset > length - 12) return; /* check end of data segment */ |
|
/* Get Tag number */ |
|
if (is_motorola) { |
|
tagnum = GETJOCTET(data[firstoffset]); |
|
tagnum <<= 8; |
|
tagnum += GETJOCTET(data[firstoffset+1]); |
|
} else { |
|
tagnum = GETJOCTET(data[firstoffset+1]); |
|
tagnum <<= 8; |
|
tagnum += GETJOCTET(data[firstoffset]); |
|
} |
|
if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ |
|
if (--number_of_tags == 0) return; |
|
firstoffset += 12; |
|
} |
|
|
|
/* Get the ExifSubIFD offset */ |
|
if (is_motorola) { |
|
if (GETJOCTET(data[firstoffset+8]) != 0) return; |
|
if (GETJOCTET(data[firstoffset+9]) != 0) return; |
|
offset = GETJOCTET(data[firstoffset+10]); |
|
offset <<= 8; |
|
offset += GETJOCTET(data[firstoffset+11]); |
|
} else { |
|
if (GETJOCTET(data[firstoffset+11]) != 0) return; |
|
if (GETJOCTET(data[firstoffset+10]) != 0) return; |
|
offset = GETJOCTET(data[firstoffset+9]); |
|
offset <<= 8; |
|
offset += GETJOCTET(data[firstoffset+8]); |
|
} |
|
if (offset > length - 2) return; /* check end of data segment */ |
|
|
|
/* Get the number of directory entries contained in this SubIFD */ |
|
if (is_motorola) { |
|
number_of_tags = GETJOCTET(data[offset]); |
|
number_of_tags <<= 8; |
|
number_of_tags += GETJOCTET(data[offset+1]); |
|
} else { |
|
number_of_tags = GETJOCTET(data[offset+1]); |
|
number_of_tags <<= 8; |
|
number_of_tags += GETJOCTET(data[offset]); |
|
} |
|
if (number_of_tags < 2) return; |
|
offset += 2; |
|
|
|
/* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ |
|
do { |
|
if (offset > length - 12) return; /* check end of data segment */ |
|
/* Get Tag number */ |
|
if (is_motorola) { |
|
tagnum = GETJOCTET(data[offset]); |
|
tagnum <<= 8; |
|
tagnum += GETJOCTET(data[offset+1]); |
|
} else { |
|
tagnum = GETJOCTET(data[offset+1]); |
|
tagnum <<= 8; |
|
tagnum += GETJOCTET(data[offset]); |
|
} |
|
if (tagnum == 0xA002 || tagnum == 0xA003) { |
|
if (tagnum == 0xA002) |
|
new_value = new_width; /* ExifImageWidth Tag */ |
|
else |
|
new_value = new_height; /* ExifImageHeight Tag */ |
|
if (is_motorola) { |
|
data[offset+2] = 0; /* Format = unsigned long (4 octets) */ |
|
data[offset+3] = 4; |
|
data[offset+4] = 0; /* Number Of Components = 1 */ |
|
data[offset+5] = 0; |
|
data[offset+6] = 0; |
|
data[offset+7] = 1; |
|
data[offset+8] = 0; |
|
data[offset+9] = 0; |
|
data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); |
|
data[offset+11] = (JOCTET)(new_value & 0xFF); |
|
} else { |
|
data[offset+2] = 4; /* Format = unsigned long (4 octets) */ |
|
data[offset+3] = 0; |
|
data[offset+4] = 1; /* Number Of Components = 1 */ |
|
data[offset+5] = 0; |
|
data[offset+6] = 0; |
|
data[offset+7] = 0; |
|
data[offset+8] = (JOCTET)(new_value & 0xFF); |
|
data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); |
|
data[offset+10] = 0; |
|
data[offset+11] = 0; |
|
} |
|
} |
|
offset += 12; |
|
} while (--number_of_tags); |
|
} |
|
|
|
|
/* Adjust output image parameters as needed. | /* Adjust output image parameters as needed. |
* | * |
* This must be called after jpeg_copy_critical_parameters() | * This must be called after jpeg_copy_critical_parameters() |
|
|
break; | break; |
} | } |
| |
|
/* Adjust Exif properties */ |
|
if (srcinfo->marker_list != NULL && |
|
srcinfo->marker_list->marker == JPEG_APP0+1 && |
|
srcinfo->marker_list->data_length >= 6 && |
|
GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && |
|
GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && |
|
GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && |
|
GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && |
|
GETJOCTET(srcinfo->marker_list->data[4]) == 0 && |
|
GETJOCTET(srcinfo->marker_list->data[5]) == 0) { |
|
/* Suppress output of JFIF marker */ |
|
dstinfo->write_JFIF_header = FALSE; |
|
/* Adjust Exif image parameters */ |
|
if (dstinfo->image_width != srcinfo->image_width || |
|
dstinfo->image_height != srcinfo->image_height) |
|
/* Align data segment to start of TIFF structure for parsing */ |
|
adjust_exif_parameters(srcinfo->marker_list->data + 6, |
|
srcinfo->marker_list->data_length - 6, |
|
dstinfo->image_width, dstinfo->image_height); |
|
} |
|
|
/* Return the appropriate output data set */ | /* Return the appropriate output data set */ |
if (info->workspace_coef_arrays != NULL) | if (info->workspace_coef_arrays != NULL) |
return info->workspace_coef_arrays; | return info->workspace_coef_arrays; |