Fix reading of 16-bit TIFF images on big endian host.
Use correct integer types for arguments to TIFFGetField to avoid corruption of values and failed loads of TIFF file when using cv::imread(). Added test where both big and little endian TIFF files are read using imread(). Fixed build of 3rdparty libtiff on big endian hosts. Reduced memory required during decode_tile16384x16384 test by not converting large grayscale test image to color image during read.
This commit is contained in:
@@ -408,8 +408,8 @@ TEST(Highgui_Tiff, decode_tile16384x16384)
|
||||
|
||||
try
|
||||
{
|
||||
cv::imread(file3);
|
||||
EXPECT_NO_THROW(cv::imread(file4));
|
||||
cv::imread(file3, CV_LOAD_IMAGE_UNCHANGED);
|
||||
EXPECT_NO_THROW(cv::imread(file4, CV_LOAD_IMAGE_UNCHANGED));
|
||||
}
|
||||
catch(const std::bad_alloc&)
|
||||
{
|
||||
@@ -419,4 +419,52 @@ TEST(Highgui_Tiff, decode_tile16384x16384)
|
||||
remove(file3.c_str());
|
||||
remove(file4.c_str());
|
||||
}
|
||||
|
||||
TEST(Highgui_Tiff, write_read_16bit_big_little_endian)
|
||||
{
|
||||
// see issue #2601 "16-bit Grayscale TIFF Load Failures Due to Buffer Underflow and Endianness"
|
||||
|
||||
// Setup data for two minimal 16-bit grayscale TIFF files in both endian formats
|
||||
uchar tiff_sample_data[2][86] = { {
|
||||
// Little endian
|
||||
0x49, 0x49, 0x2a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xad, 0xde, 0xef, 0xbe, 0x06, 0x00, 0x00, 0x01,
|
||||
0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
|
||||
0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01,
|
||||
0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x01, 0x04, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }, {
|
||||
// Big endian
|
||||
0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x0c, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x06, 0x01, 0x00,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10,
|
||||
0x00, 0x00, 0x01, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x11,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x01, 0x17, 0x00, 0x04, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x04 }
|
||||
};
|
||||
|
||||
// Test imread() for both a little endian TIFF and big endian TIFF
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
string filename = cv::tempfile(".tiff");
|
||||
|
||||
// Write sample TIFF file
|
||||
FILE* fp = fopen(filename.c_str(), "wb");
|
||||
ASSERT_TRUE(fp != NULL);
|
||||
ASSERT_EQ((size_t)1, fwrite(tiff_sample_data, 86, 1, fp));
|
||||
fclose(fp);
|
||||
|
||||
Mat img = imread(filename, CV_LOAD_IMAGE_UNCHANGED);
|
||||
|
||||
EXPECT_EQ(1, img.rows);
|
||||
EXPECT_EQ(2, img.cols);
|
||||
EXPECT_EQ(CV_16U, img.type());
|
||||
EXPECT_EQ(sizeof(ushort), img.elemSize());
|
||||
EXPECT_EQ(1, img.channels());
|
||||
EXPECT_EQ(0xDEAD, img.at<ushort>(0,0));
|
||||
EXPECT_EQ(0xBEEF, img.at<ushort>(0,1));
|
||||
|
||||
remove(filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user