Fix corrupt 32-bit compressed TIFF

Match endianness of pixel data with endianness of Exif metadata when
saving compressed 32-bit float TIFF.
Fixes #4377
This commit is contained in:
Morgan Hardwood 2018-02-07 17:10:57 +01:00
parent 4579d4be14
commit 09c4572402

View File

@ -1438,14 +1438,14 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed)
} }
} }
if (iptcdata) {
rtexif::Tag iptcTag(nullptr, rtexif::lookupAttrib (rtexif::ifdAttribs, "IPTCData"));
iptcTag.initLongArray((char*)iptcdata, iptclen);
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::MOTOROLA; bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::MOTOROLA;
#else #else
bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::INTEL; bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::INTEL;
#endif #endif
if (iptcdata) {
rtexif::Tag iptcTag(nullptr, rtexif::lookupAttrib (rtexif::ifdAttribs, "IPTCData"));
iptcTag.initLongArray((char*)iptcdata, iptclen);
if (needsReverse) { if (needsReverse) {
unsigned char *ptr = iptcTag.getValue(); unsigned char *ptr = iptcTag.getValue();
for (int a = 0; a < iptcTag.getCount(); ++a) { for (int a = 0; a < iptcTag.getCount(); ++a) {
@ -1471,15 +1471,13 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed)
TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, height); TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, height);
TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, bps); TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, bps);
TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
TIFFSetField (out, TIFFTAG_COMPRESSION, uncompressed ? COMPRESSION_NONE : COMPRESSION_DEFLATE); TIFFSetField (out, TIFFTAG_COMPRESSION, uncompressed ? COMPRESSION_NONE : COMPRESSION_ADOBE_DEFLATE);
TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, bps == 32 ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT); TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, bps == 32 ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT);
if (!uncompressed) { if (!uncompressed) {
TIFFSetField (out, TIFFTAG_PREDICTOR, bps == 32 ? PREDICTOR_FLOATINGPOINT : PREDICTOR_HORIZONTAL); TIFFSetField (out, TIFFTAG_PREDICTOR, bps == 32 ? PREDICTOR_FLOATINGPOINT : PREDICTOR_HORIZONTAL);
} }
if (profileData) { if (profileData) {
TIFFSetField (out, TIFFTAG_ICCPROFILE, profileLength, profileData); TIFFSetField (out, TIFFTAG_ICCPROFILE, profileLength, profileData);
} }
@ -1487,6 +1485,17 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed)
for (int row = 0; row < height; row++) { for (int row = 0; row < height; row++) {
getScanline (row, linebuffer, bps); getScanline (row, linebuffer, bps);
if(needsReverse && !uncompressed && bps == 32) {
for(int i = 0; i < lineWidth; i += 4) {
char temp = linebuffer[i];
linebuffer[i] = linebuffer[i + 3];
linebuffer[i + 3] = temp;
temp = linebuffer[i + 1];
linebuffer[i + 1] = linebuffer[i + 2];
linebuffer[i + 2] = temp;
}
}
if (TIFFWriteScanline (out, linebuffer, row, 0) < 0) { if (TIFFWriteScanline (out, linebuffer, row, 0) < 0) {
TIFFClose (out); TIFFClose (out);
delete [] linebuffer; delete [] linebuffer;