Merge pull request #2323 from stuart8c:issue2601_2.4_fix_16bit_tiff_reading_on_big_endian_host
This commit is contained in:
		
							
								
								
									
										12
									
								
								3rdparty/libtiff/tif_config.h.cmakein
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								3rdparty/libtiff/tif_config.h.cmakein
									
									
									
									
										vendored
									
									
								
							@@ -54,7 +54,7 @@
 | 
			
		||||
 | 
			
		||||
/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
 | 
			
		||||
   (Intel) */
 | 
			
		||||
#define HOST_BIGENDIAN 0
 | 
			
		||||
#define HOST_BIGENDIAN @WORDS_BIGENDIAN@
 | 
			
		||||
 | 
			
		||||
/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
 | 
			
		||||
#define HOST_FILLORDER FILLORDER_LSB2MSB
 | 
			
		||||
@@ -156,15 +156,7 @@
 | 
			
		||||
 | 
			
		||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
 | 
			
		||||
   significant byte first (like Motorola and SPARC, unlike Intel). */
 | 
			
		||||
#if defined AC_APPLE_UNIVERSAL_BUILD
 | 
			
		||||
# if defined __BIG_ENDIAN__
 | 
			
		||||
#  define WORDS_BIGENDIAN 1
 | 
			
		||||
# endif
 | 
			
		||||
#else
 | 
			
		||||
# ifndef WORDS_BIGENDIAN
 | 
			
		||||
/* #  undef WORDS_BIGENDIAN */
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
#cmakedefine WORDS_BIGENDIAN 1
 | 
			
		||||
 | 
			
		||||
/* Support Deflate compression */
 | 
			
		||||
#define ZIP_SUPPORT 1
 | 
			
		||||
 
 | 
			
		||||
@@ -444,6 +444,12 @@ endif()
 | 
			
		||||
include(cmake/OpenCVPCHSupport.cmake)
 | 
			
		||||
include(cmake/OpenCVModule.cmake)
 | 
			
		||||
 | 
			
		||||
# ----------------------------------------------------------------------------
 | 
			
		||||
#  Detect endianness of build platform
 | 
			
		||||
# ----------------------------------------------------------------------------
 | 
			
		||||
include(TestBigEndian)
 | 
			
		||||
test_big_endian(WORDS_BIGENDIAN)
 | 
			
		||||
 | 
			
		||||
# ----------------------------------------------------------------------------
 | 
			
		||||
#  Detect 3rd-party libraries
 | 
			
		||||
# ----------------------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -161,6 +161,6 @@
 | 
			
		||||
/* Xine video library */
 | 
			
		||||
#cmakedefine HAVE_XINE
 | 
			
		||||
 | 
			
		||||
/* Define to 1 if your processor stores words with the most significant byte
 | 
			
		||||
/* Define if your processor stores words with the most significant byte
 | 
			
		||||
   first (like Motorola and SPARC, unlike Intel and VAX). */
 | 
			
		||||
#cmakedefine WORDS_BIGENDIAN
 | 
			
		||||
 
 | 
			
		||||
@@ -111,18 +111,21 @@ bool TiffDecoder::readHeader()
 | 
			
		||||
    bool result = false;
 | 
			
		||||
 | 
			
		||||
    close();
 | 
			
		||||
    TIFF* tif = TIFFOpen( m_filename.c_str(), "rb" );
 | 
			
		||||
    // TIFFOpen() mode flags are different to fopen().  A 'b' in mode "rb" has no effect when reading.
 | 
			
		||||
    // http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
 | 
			
		||||
    TIFF* tif = TIFFOpen( m_filename.c_str(), "r" );
 | 
			
		||||
 | 
			
		||||
    if( tif )
 | 
			
		||||
    {
 | 
			
		||||
        int wdth = 0, hght = 0, photometric = 0;
 | 
			
		||||
        uint32 wdth = 0, hght = 0;
 | 
			
		||||
        uint16 photometric = 0;
 | 
			
		||||
        m_tif = tif;
 | 
			
		||||
 | 
			
		||||
        if( TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &wdth ) &&
 | 
			
		||||
            TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &hght ) &&
 | 
			
		||||
            TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric ))
 | 
			
		||||
        {
 | 
			
		||||
            int bpp=8, ncn = photometric > 1 ? 3 : 1;
 | 
			
		||||
            uint16 bpp=8, ncn = photometric > 1 ? 3 : 1;
 | 
			
		||||
            TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bpp );
 | 
			
		||||
            TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &ncn );
 | 
			
		||||
 | 
			
		||||
@@ -175,12 +178,12 @@ bool  TiffDecoder::readData( Mat& img )
 | 
			
		||||
    if( m_tif && m_width && m_height )
 | 
			
		||||
    {
 | 
			
		||||
        TIFF* tif = (TIFF*)m_tif;
 | 
			
		||||
        int tile_width0 = m_width, tile_height0 = 0;
 | 
			
		||||
        uint32 tile_width0 = m_width, tile_height0 = 0;
 | 
			
		||||
        int x, y, i;
 | 
			
		||||
        int is_tiled = TIFFIsTiled(tif);
 | 
			
		||||
        int photometric;
 | 
			
		||||
        uint16 photometric;
 | 
			
		||||
        TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric );
 | 
			
		||||
        int bpp = 8, ncn = photometric > 1 ? 3 : 1;
 | 
			
		||||
        uint16 bpp = 8, ncn = photometric > 1 ? 3 : 1;
 | 
			
		||||
        TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bpp );
 | 
			
		||||
        TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &ncn );
 | 
			
		||||
        const int bitsPerByte = 8;
 | 
			
		||||
 
 | 
			
		||||
@@ -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