mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge pull request #22404 from Kumataro:3.4-fix22388_2
* imgcodecs: tiff: Reduce memory usage to read 16bit image. * imgcodecs: tiff: Reduce memory usage to read 8bit images * imgcodecs: tiff: split basic test and full test. * imgcodecs: tiff: fix to warning C4244 * imgcodecs: tiff: fix to warning C4244
This commit is contained in:
parent
572d4f4491
commit
2f79b1b087
@ -234,7 +234,6 @@ public:
|
|||||||
bool TiffDecoder::readHeader()
|
bool TiffDecoder::readHeader()
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
TIFF* tif = static_cast<TIFF*>(m_tif.get());
|
TIFF* tif = static_cast<TIFF*>(m_tif.get());
|
||||||
if (!tif)
|
if (!tif)
|
||||||
{
|
{
|
||||||
@ -390,18 +389,15 @@ static void fixOrientationFull(Mat &img, int orientation)
|
|||||||
* For 8 bit some corrections are done by TIFFReadRGBAStrip/Tile already.
|
* For 8 bit some corrections are done by TIFFReadRGBAStrip/Tile already.
|
||||||
* Not so for 16/32/64 bit.
|
* Not so for 16/32/64 bit.
|
||||||
*/
|
*/
|
||||||
static void fixOrientation(Mat &img, uint16 orientation, int dst_bpp)
|
static void fixOrientation(Mat &img, uint16 orientation, bool isOrientationFull)
|
||||||
{
|
{
|
||||||
switch(dst_bpp) {
|
if( isOrientationFull )
|
||||||
case 8:
|
{
|
||||||
fixOrientationPartial(img, orientation);
|
fixOrientationFull(img, orientation);
|
||||||
break;
|
}
|
||||||
|
else
|
||||||
case 16:
|
{
|
||||||
case 32:
|
fixOrientationPartial(img, orientation);
|
||||||
case 64:
|
|
||||||
fixOrientationFull(img, orientation);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,17 +436,7 @@ bool TiffDecoder::readData( Mat& img )
|
|||||||
(img_orientation == ORIENTATION_BOTRIGHT || img_orientation == ORIENTATION_RIGHTBOT ||
|
(img_orientation == ORIENTATION_BOTRIGHT || img_orientation == ORIENTATION_RIGHTBOT ||
|
||||||
img_orientation == ORIENTATION_BOTLEFT || img_orientation == ORIENTATION_LEFTBOT);
|
img_orientation == ORIENTATION_BOTLEFT || img_orientation == ORIENTATION_LEFTBOT);
|
||||||
int wanted_channels = normalizeChannelsNumber(img.channels());
|
int wanted_channels = normalizeChannelsNumber(img.channels());
|
||||||
|
bool doReadScanline = false;
|
||||||
if (dst_bpp == 8)
|
|
||||||
{
|
|
||||||
char errmsg[1024];
|
|
||||||
if (!TIFFRGBAImageOK(tif, errmsg))
|
|
||||||
{
|
|
||||||
CV_LOG_WARNING(NULL, "OpenCV TIFF: TIFFRGBAImageOK: " << errmsg);
|
|
||||||
close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 tile_width0 = m_width, tile_height0 = 0;
|
uint32 tile_width0 = m_width, tile_height0 = 0;
|
||||||
|
|
||||||
@ -480,25 +466,139 @@ bool TiffDecoder::readData( Mat& img )
|
|||||||
const uint64_t MAX_TILE_SIZE = (CV_BIG_UINT(1) << 30);
|
const uint64_t MAX_TILE_SIZE = (CV_BIG_UINT(1) << 30);
|
||||||
CV_CheckLE((int)ncn, 4, "");
|
CV_CheckLE((int)ncn, 4, "");
|
||||||
CV_CheckLE((int)bpp, 64, "");
|
CV_CheckLE((int)bpp, 64, "");
|
||||||
CV_Assert(((uint64_t)tile_width0 * tile_height0 * ncn * std::max(1, (int)(bpp / bitsPerByte)) < MAX_TILE_SIZE) && "TIFF tile size is too large: >= 1Gb");
|
|
||||||
|
|
||||||
if (dst_bpp == 8)
|
if (dst_bpp == 8)
|
||||||
{
|
{
|
||||||
// we will use TIFFReadRGBA* functions, so allocate temporary buffer for 32bit RGBA
|
const int _ncn = 4; // Read RGBA
|
||||||
bpp = 8;
|
const int _bpp = 8; // Read 8bit
|
||||||
ncn = 4;
|
|
||||||
|
// if buffer_size(as 32bit RGBA) >= MAX_TILE_SIZE*95%,
|
||||||
|
// we will use TIFFReadScanline function.
|
||||||
|
|
||||||
|
if (
|
||||||
|
(uint64_t)tile_width0 * tile_height0 * _ncn * std::max(1, (int)(_bpp / bitsPerByte))
|
||||||
|
>=
|
||||||
|
( (uint64_t) MAX_TILE_SIZE * 95 / 100)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint16_t planerConfig = (uint16)-1;
|
||||||
|
CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planerConfig));
|
||||||
|
|
||||||
|
doReadScanline = (!is_tiled) // no tile
|
||||||
|
&&
|
||||||
|
( ( ncn == 1 ) || ( ncn == 3 ) || ( ncn == 4 ) )
|
||||||
|
&&
|
||||||
|
( ( bpp == 8 ) || ( bpp == 16 ) )
|
||||||
|
&&
|
||||||
|
(tile_height0 == (uint32_t) m_height) // single strip
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
(photometric == PHOTOMETRIC_MINISWHITE)
|
||||||
|
||
|
||||||
|
(photometric == PHOTOMETRIC_MINISBLACK)
|
||||||
|
||
|
||||||
|
(photometric == PHOTOMETRIC_RGB)
|
||||||
|
)
|
||||||
|
&&
|
||||||
|
(planerConfig != PLANARCONFIG_SEPARATE);
|
||||||
|
|
||||||
|
// Currently only EXTRASAMPLE_ASSOCALPHA is supported.
|
||||||
|
if ( doReadScanline && ( ncn == 4 ) )
|
||||||
|
{
|
||||||
|
uint16_t extra_samples_num;
|
||||||
|
uint16_t *extra_samples = NULL;
|
||||||
|
CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &extra_samples_num, &extra_samples ));
|
||||||
|
doReadScanline = ( extra_samples_num == 1 ) && ( extra_samples[0] == EXTRASAMPLE_ASSOCALPHA );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !doReadScanline )
|
||||||
|
{
|
||||||
|
// we will use TIFFReadRGBA* functions, so allocate temporary buffer for 32bit RGBA
|
||||||
|
bpp = 8;
|
||||||
|
ncn = 4;
|
||||||
|
|
||||||
|
char errmsg[1024];
|
||||||
|
if (!TIFFRGBAImageOK(tif, errmsg))
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "OpenCV TIFF: TIFFRGBAImageOK: " << errmsg);
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dst_bpp == 16)
|
||||||
|
{
|
||||||
|
// if buffer_size >= MAX_TILE_SIZE*95%,
|
||||||
|
// we will use TIFFReadScanline function.
|
||||||
|
if (
|
||||||
|
(uint64_t)tile_width0 * tile_height0 * ncn * std::max(1, (int)(bpp / bitsPerByte))
|
||||||
|
>=
|
||||||
|
MAX_TILE_SIZE * 95 / 100
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint16_t planerConfig = (uint16)-1;
|
||||||
|
CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planerConfig));
|
||||||
|
|
||||||
|
doReadScanline = (!is_tiled) // no tile
|
||||||
|
&&
|
||||||
|
( ( ncn == 1 ) || ( ncn == 3 ) || ( ncn == 4 ) )
|
||||||
|
&&
|
||||||
|
( ( bpp == 8 ) || ( bpp == 16 ) )
|
||||||
|
&&
|
||||||
|
(tile_height0 == (uint32_t) m_height) // single strip
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
(photometric == PHOTOMETRIC_MINISWHITE)
|
||||||
|
||
|
||||||
|
(photometric == PHOTOMETRIC_MINISBLACK)
|
||||||
|
||
|
||||||
|
(photometric == PHOTOMETRIC_RGB)
|
||||||
|
)
|
||||||
|
&&
|
||||||
|
(planerConfig != PLANARCONFIG_SEPARATE);
|
||||||
|
|
||||||
|
// Currently only EXTRASAMPLE_ASSOCALPHA is supported.
|
||||||
|
if ( doReadScanline && ( ncn == 4 ) )
|
||||||
|
{
|
||||||
|
uint16_t extra_samples_num;
|
||||||
|
uint16_t *extra_samples = NULL;
|
||||||
|
CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &extra_samples_num, &extra_samples ));
|
||||||
|
doReadScanline = ( extra_samples_num == 1 ) && ( extra_samples[0] == EXTRASAMPLE_ASSOCALPHA );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (dst_bpp == 32 || dst_bpp == 64)
|
else if (dst_bpp == 32 || dst_bpp == 64)
|
||||||
{
|
{
|
||||||
CV_Assert(ncn == img.channels());
|
CV_Assert(ncn == img.channels());
|
||||||
CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP));
|
CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( doReadScanline )
|
||||||
|
{
|
||||||
|
// Read each scanlines.
|
||||||
|
tile_height0 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
const size_t buffer_size = (bpp / bitsPerByte) * ncn * tile_height0 * tile_width0;
|
const size_t buffer_size = (bpp / bitsPerByte) * ncn * tile_height0 * tile_width0;
|
||||||
|
CV_CheckLT( buffer_size, MAX_TILE_SIZE, "buffer_size is too large: >= 1Gb");
|
||||||
|
|
||||||
|
if ( doReadScanline )
|
||||||
|
{
|
||||||
|
CV_CheckGE( static_cast<int>(buffer_size),
|
||||||
|
static_cast<int>(TIFFScanlineSize(tif)),
|
||||||
|
"buffer_size is smaller than TIFFScanlineSize(). ");
|
||||||
|
}
|
||||||
|
|
||||||
AutoBuffer<uchar> _buffer(buffer_size);
|
AutoBuffer<uchar> _buffer(buffer_size);
|
||||||
uchar* buffer = _buffer.data();
|
uchar* buffer = _buffer.data();
|
||||||
ushort* buffer16 = (ushort*)buffer;
|
ushort* buffer16 = (ushort*)buffer;
|
||||||
int tileidx = 0;
|
int tileidx = 0;
|
||||||
|
|
||||||
|
#define MAKE_FLAG(a,b) ( (a << 8) | b )
|
||||||
|
const int convert_flag = MAKE_FLAG( ncn, wanted_channels );
|
||||||
|
const bool isNeedConvert16to8 = ( doReadScanline ) && ( bpp == 16 ) && ( dst_bpp == 8);
|
||||||
|
|
||||||
for (int y = 0; y < m_height; y += (int)tile_height0)
|
for (int y = 0; y < m_height; y += (int)tile_height0)
|
||||||
{
|
{
|
||||||
int tile_height = std::min((int)tile_height0, m_height - y);
|
int tile_height = std::min((int)tile_height0, m_height - y);
|
||||||
@ -514,7 +614,29 @@ bool TiffDecoder::readData( Mat& img )
|
|||||||
case 8:
|
case 8:
|
||||||
{
|
{
|
||||||
uchar* bstart = buffer;
|
uchar* bstart = buffer;
|
||||||
if (!is_tiled)
|
if (doReadScanline)
|
||||||
|
{
|
||||||
|
CV_TIFF_CHECK_CALL((int)TIFFReadScanline(tif, (uint32*)buffer, y) >= 0);
|
||||||
|
|
||||||
|
if ( isNeedConvert16to8 )
|
||||||
|
{
|
||||||
|
// Convert buffer image from 16bit to 8bit.
|
||||||
|
int ix;
|
||||||
|
for ( ix = 0 ; ix < tile_width * ncn - 4; ix += 4 )
|
||||||
|
{
|
||||||
|
buffer[ ix ] = buffer[ ix * 2 + 1 ];
|
||||||
|
buffer[ ix + 1 ] = buffer[ ix * 2 + 3 ];
|
||||||
|
buffer[ ix + 2 ] = buffer[ ix * 2 + 5 ];
|
||||||
|
buffer[ ix + 3 ] = buffer[ ix * 2 + 7 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; ix < tile_width * ncn ; ix ++ )
|
||||||
|
{
|
||||||
|
buffer[ ix ] = buffer[ ix * 2 + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!is_tiled)
|
||||||
{
|
{
|
||||||
CV_TIFF_CHECK_CALL(TIFFReadRGBAStrip(tif, y, (uint32*)buffer));
|
CV_TIFF_CHECK_CALL(TIFFReadRGBAStrip(tif, y, (uint32*)buffer));
|
||||||
}
|
}
|
||||||
@ -525,9 +647,65 @@ bool TiffDecoder::readData( Mat& img )
|
|||||||
bstart += (tile_height0 - tile_height) * tile_width0 * 4;
|
bstart += (tile_height0 - tile_height) * tile_width0 * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uchar* img_line_buffer = (uchar*) img.ptr(y, 0);
|
||||||
|
|
||||||
for (int i = 0; i < tile_height; i++)
|
for (int i = 0; i < tile_height; i++)
|
||||||
{
|
{
|
||||||
if (color)
|
if (doReadScanline)
|
||||||
|
{
|
||||||
|
switch ( convert_flag )
|
||||||
|
{
|
||||||
|
case MAKE_FLAG( 1, 1 ): // GRAY to GRAY
|
||||||
|
memcpy( (void*) img_line_buffer,
|
||||||
|
(void*) bstart,
|
||||||
|
tile_width * sizeof(uchar) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAKE_FLAG( 1, 3 ): // GRAY to BGR
|
||||||
|
icvCvt_Gray2BGR_8u_C1C3R( bstart, 0,
|
||||||
|
img_line_buffer, 0,
|
||||||
|
Size(tile_width, 1) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAKE_FLAG( 3, 1): // RGB to GRAY
|
||||||
|
icvCvt_BGR2Gray_8u_C3C1R( bstart, 0,
|
||||||
|
img_line_buffer, 0,
|
||||||
|
Size(tile_width, 1) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAKE_FLAG( 3, 3 ): // RGB to BGR
|
||||||
|
icvCvt_BGR2RGB_8u_C3R( bstart, 0,
|
||||||
|
img_line_buffer, 0,
|
||||||
|
Size(tile_width, 1) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAKE_FLAG( 4, 1 ): // RGBA to GRAY
|
||||||
|
icvCvt_BGRA2Gray_8u_C4C1R( bstart, 0,
|
||||||
|
img_line_buffer, 0,
|
||||||
|
Size(tile_width, 1) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAKE_FLAG( 4, 3 ): // RGBA to BGR
|
||||||
|
icvCvt_BGRA2BGR_8u_C4C3R( bstart, 0,
|
||||||
|
img_line_buffer, 0,
|
||||||
|
Size(tile_width, 1), 2 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAKE_FLAG( 4, 4 ): // RGBA to BGRA
|
||||||
|
icvCvt_BGRA2RGBA_8u_C4R(bstart, 0,
|
||||||
|
img_line_buffer, 0,
|
||||||
|
Size(tile_width, 1) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
CV_LOG_ONCE_ERROR(NULL, "OpenCV TIFF(line " << __LINE__ << "): Unsupported convertion :"
|
||||||
|
<< " bpp = " << bpp << " ncn = " << (int)ncn
|
||||||
|
<< " wanted_channels =" << wanted_channels );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#undef MAKE_FLAG
|
||||||
|
}
|
||||||
|
else if (color)
|
||||||
{
|
{
|
||||||
if (wanted_channels == 4)
|
if (wanted_channels == 4)
|
||||||
{
|
{
|
||||||
@ -556,7 +734,11 @@ bool TiffDecoder::readData( Mat& img )
|
|||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
{
|
{
|
||||||
if (!is_tiled)
|
if (doReadScanline)
|
||||||
|
{
|
||||||
|
CV_TIFF_CHECK_CALL((int)TIFFReadScanline(tif, (uint32*)buffer, y) >= 0);
|
||||||
|
}
|
||||||
|
else if (!is_tiled)
|
||||||
{
|
{
|
||||||
CV_TIFF_CHECK_CALL((int)TIFFReadEncodedStrip(tif, tileidx, (uint32*)buffer, buffer_size) >= 0);
|
CV_TIFF_CHECK_CALL((int)TIFFReadEncodedStrip(tif, tileidx, (uint32*)buffer, buffer_size) >= 0);
|
||||||
}
|
}
|
||||||
@ -655,7 +837,11 @@ bool TiffDecoder::readData( Mat& img )
|
|||||||
} // for x
|
} // for x
|
||||||
} // for y
|
} // for y
|
||||||
}
|
}
|
||||||
fixOrientation(img, img_orientation, dst_bpp);
|
|
||||||
|
// If TIFFReadRGBA* function is used -> fixOrientationPartial().
|
||||||
|
// Otherwise -> fixOrientationFull().
|
||||||
|
fixOrientation(img, img_orientation,
|
||||||
|
( ( dst_bpp != 8 ) && ( !doReadScanline ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_hdr && depth >= CV_32F)
|
if (m_hdr && depth >= CV_32F)
|
||||||
@ -680,6 +866,7 @@ TiffEncoder::~TiffEncoder()
|
|||||||
|
|
||||||
ImageEncoder TiffEncoder::newEncoder() const
|
ImageEncoder TiffEncoder::newEncoder() const
|
||||||
{
|
{
|
||||||
|
cv_tiffSetErrorHandler();
|
||||||
return makePtr<TiffEncoder>();
|
return makePtr<TiffEncoder>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||||
// of this distribution and at http://opencv.org/license.html
|
// of this distribution and at http://opencv.org/license.html
|
||||||
#include "test_precomp.hpp"
|
#include "test_precomp.hpp"
|
||||||
|
#include "opencv2/core/utils/logger.hpp"
|
||||||
|
#include "opencv2/core/utils/configuration.private.hpp"
|
||||||
|
|
||||||
namespace opencv_test { namespace {
|
namespace opencv_test { namespace {
|
||||||
|
|
||||||
@ -46,6 +48,432 @@ TEST(Imgcodecs_Tiff, decode_tile16384x16384)
|
|||||||
EXPECT_EQ(0, remove(file4.c_str()));
|
EXPECT_EQ(0, remove(file4.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
// See https://github.com/opencv/opencv/issues/22388
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy enum to show combination of IMREAD_*.
|
||||||
|
*/
|
||||||
|
enum ImreadMixModes
|
||||||
|
{
|
||||||
|
IMREAD_MIX_UNCHANGED = IMREAD_UNCHANGED ,
|
||||||
|
IMREAD_MIX_GRAYSCALE = IMREAD_GRAYSCALE ,
|
||||||
|
IMREAD_MIX_COLOR = IMREAD_COLOR ,
|
||||||
|
IMREAD_MIX_GRAYSCALE_ANYDEPTH = IMREAD_GRAYSCALE | IMREAD_ANYDEPTH ,
|
||||||
|
IMREAD_MIX_GRAYSCALE_ANYCOLOR = IMREAD_GRAYSCALE | IMREAD_ANYCOLOR,
|
||||||
|
IMREAD_MIX_GRAYSCALE_ANYDEPTH_ANYCOLOR = IMREAD_GRAYSCALE | IMREAD_ANYDEPTH | IMREAD_ANYCOLOR,
|
||||||
|
IMREAD_MIX_COLOR_ANYDEPTH = IMREAD_COLOR | IMREAD_ANYDEPTH ,
|
||||||
|
IMREAD_MIX_COLOR_ANYCOLOR = IMREAD_COLOR | IMREAD_ANYCOLOR,
|
||||||
|
IMREAD_MIX_COLOR_ANYDEPTH_ANYCOLOR = IMREAD_COLOR | IMREAD_ANYDEPTH | IMREAD_ANYCOLOR
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef tuple< uint64_t, tuple<string, int>, ImreadMixModes > Bufsize_and_Type;
|
||||||
|
typedef testing::TestWithParam<Bufsize_and_Type> Imgcodecs_Tiff_decode_Huge;
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void PrintTo(const ImreadMixModes& val, std::ostream* os)
|
||||||
|
{
|
||||||
|
PrintTo( static_cast<ImreadModes>(val), os );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(Imgcodecs_Tiff_decode_Huge, regression)
|
||||||
|
{
|
||||||
|
// Get test parameters
|
||||||
|
const uint64_t buffer_size = get<0>(GetParam());
|
||||||
|
const string mat_type_string = get<0>(get<1>(GetParam()));
|
||||||
|
const int mat_type = get<1>(get<1>(GetParam()));
|
||||||
|
const int imread_mode = get<2>(GetParam());
|
||||||
|
|
||||||
|
// Detect data file
|
||||||
|
const string req_filename = cv::format("readwrite/huge-tiff/%s_%llu.tif", mat_type_string.c_str(), buffer_size);
|
||||||
|
const string filename = findDataFile( req_filename );
|
||||||
|
|
||||||
|
// Preparation process for test
|
||||||
|
{
|
||||||
|
// Convert from mat_type and buffer_size to tiff file information.
|
||||||
|
const uint64_t width = 32768;
|
||||||
|
int ncn = CV_MAT_CN(mat_type);
|
||||||
|
int depth = ( CV_MAT_DEPTH(mat_type) == CV_16U) ? 2 : 1; // 16bit or 8 bit
|
||||||
|
const uint64_t height = (uint64_t) buffer_size / width / ncn / depth;
|
||||||
|
const uint64_t base_scanline_size = (uint64_t) width * ncn * depth;
|
||||||
|
const uint64_t base_strip_size = (uint64_t) base_scanline_size * height;
|
||||||
|
|
||||||
|
// To avoid exception about pixel size, check it.
|
||||||
|
static const size_t CV_IO_MAX_IMAGE_PIXELS = utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_PIXELS", 1 << 30);
|
||||||
|
uint64_t pixels = (uint64_t) width * height;
|
||||||
|
if ( pixels > CV_IO_MAX_IMAGE_PIXELS )
|
||||||
|
{
|
||||||
|
throw SkipTestException( cv::format("Test is skipped( pixels(%lu) > CV_IO_MAX_IMAGE_PIXELS(%lu) )",
|
||||||
|
pixels, CV_IO_MAX_IMAGE_PIXELS ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If buffer_size >= 1GB * 95%, TIFFReadScanline() is used.
|
||||||
|
const uint64_t BUFFER_SIZE_LIMIT_FOR_READS_CANLINE = (uint64_t) 1024*1024*1024*95/100;
|
||||||
|
const bool doReadScanline = ( base_strip_size >= BUFFER_SIZE_LIMIT_FOR_READS_CANLINE );
|
||||||
|
|
||||||
|
// Update ncn and depth for destination Mat.
|
||||||
|
switch ( imread_mode )
|
||||||
|
{
|
||||||
|
case IMREAD_UNCHANGED:
|
||||||
|
break;
|
||||||
|
case IMREAD_GRAYSCALE:
|
||||||
|
ncn = 1;
|
||||||
|
depth = 1;
|
||||||
|
break;
|
||||||
|
case IMREAD_GRAYSCALE | IMREAD_ANYDEPTH:
|
||||||
|
ncn = 1;
|
||||||
|
break;
|
||||||
|
case IMREAD_GRAYSCALE | IMREAD_ANYCOLOR:
|
||||||
|
ncn = (ncn == 1)?1:3;
|
||||||
|
depth = 1;
|
||||||
|
break;
|
||||||
|
case IMREAD_GRAYSCALE | IMREAD_ANYCOLOR | IMREAD_ANYDEPTH:
|
||||||
|
ncn = (ncn == 1)?1:3;
|
||||||
|
break;
|
||||||
|
case IMREAD_COLOR:
|
||||||
|
ncn = 3;
|
||||||
|
depth = 1;
|
||||||
|
break;
|
||||||
|
case IMREAD_COLOR | IMREAD_ANYDEPTH:
|
||||||
|
ncn = 3;
|
||||||
|
break;
|
||||||
|
case IMREAD_COLOR | IMREAD_ANYCOLOR:
|
||||||
|
ncn = 3;
|
||||||
|
depth = 1;
|
||||||
|
break;
|
||||||
|
case IMREAD_COLOR | IMREAD_ANYDEPTH | IMREAD_ANYCOLOR:
|
||||||
|
ncn = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory usage for Destination Mat
|
||||||
|
const uint64_t memory_usage_cvmat = (uint64_t) width * ncn * depth * height;
|
||||||
|
|
||||||
|
// Memory usage for Work memory in libtiff.
|
||||||
|
uint64_t memory_usage_tiff = 0;
|
||||||
|
if ( ( depth == 1 ) && ( !doReadScanline ) )
|
||||||
|
{
|
||||||
|
// TIFFReadRGBA*() request to allocate RGBA(32bit) buffer.
|
||||||
|
memory_usage_tiff = (uint64_t)
|
||||||
|
width *
|
||||||
|
4 * // ncn = RGBA
|
||||||
|
1 * // dst_bpp = 8 bpp
|
||||||
|
height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TIFFReadEncodedStrip() or TIFFReadScanline() request to allocate strip memory.
|
||||||
|
memory_usage_tiff = base_strip_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory usage for Work memory in imgcodec/grfmt_tiff.cpp
|
||||||
|
const uint64_t memory_usage_work =
|
||||||
|
( doReadScanline ) ? base_scanline_size // for TIFFReadScanline()
|
||||||
|
: base_strip_size; // for TIFFReadRGBA*() or TIFFReadEncodedStrip()
|
||||||
|
|
||||||
|
// Total memory usage.
|
||||||
|
const uint64_t memory_usage_total =
|
||||||
|
memory_usage_cvmat + // Destination Mat
|
||||||
|
memory_usage_tiff + // Work memory in libtiff
|
||||||
|
memory_usage_work; // Work memory in imgcodecs
|
||||||
|
|
||||||
|
// Output memory usage log.
|
||||||
|
CV_LOG_DEBUG(NULL, cv::format("OpenCV TIFF-test(line %d):memory usage info : mat(%llu), libtiff(%llu), work(%llu) -> total(%llu)",
|
||||||
|
__LINE__, memory_usage_cvmat, memory_usage_tiff, memory_usage_work, memory_usage_total) );
|
||||||
|
|
||||||
|
// Add test tags.
|
||||||
|
if ( memory_usage_total >= (uint64_t) 6144 * 1024 * 1024 )
|
||||||
|
{
|
||||||
|
applyTestTag( CV_TEST_TAG_MEMORY_14GB, CV_TEST_TAG_VERYLONG );
|
||||||
|
}
|
||||||
|
else if ( memory_usage_total >= (uint64_t) 2048 * 1024 * 1024 )
|
||||||
|
{
|
||||||
|
applyTestTag( CV_TEST_TAG_MEMORY_6GB, CV_TEST_TAG_VERYLONG );
|
||||||
|
}
|
||||||
|
else if ( memory_usage_total >= (uint64_t) 1024 * 1024 * 1024 )
|
||||||
|
{
|
||||||
|
applyTestTag( CV_TEST_TAG_MEMORY_2GB, CV_TEST_TAG_LONG );
|
||||||
|
}
|
||||||
|
else if ( memory_usage_total >= (uint64_t) 512 * 1024 * 1024 )
|
||||||
|
{
|
||||||
|
applyTestTag( CV_TEST_TAG_MEMORY_1GB );
|
||||||
|
}
|
||||||
|
else if ( memory_usage_total >= (uint64_t) 200 * 1024 * 1024 )
|
||||||
|
{
|
||||||
|
applyTestTag( CV_TEST_TAG_MEMORY_512MB );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEST Main
|
||||||
|
|
||||||
|
cv::Mat img;
|
||||||
|
ASSERT_NO_THROW( img = cv::imread(filename, imread_mode) );
|
||||||
|
ASSERT_FALSE(img.empty());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test marker pixels at each corners.
|
||||||
|
*
|
||||||
|
* 0xAn,0x00 ... 0x00, 0xBn
|
||||||
|
* 0x00,0x00 ... 0x00, 0x00
|
||||||
|
* : : : :
|
||||||
|
* 0x00,0x00 ... 0x00, 0x00
|
||||||
|
* 0xCn,0x00 .., 0x00, 0xDn
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAKE_FLAG(from_type, to_type) (((uint64_t)from_type << 32 ) | to_type )
|
||||||
|
|
||||||
|
switch ( MAKE_FLAG(mat_type, img.type() ) )
|
||||||
|
{
|
||||||
|
// GRAY TO GRAY
|
||||||
|
case MAKE_FLAG(CV_8UC1, CV_8UC1):
|
||||||
|
case MAKE_FLAG(CV_16UC1, CV_8UC1):
|
||||||
|
EXPECT_EQ( 0xA0, img.at<uchar>(0, 0) );
|
||||||
|
EXPECT_EQ( 0xB0, img.at<uchar>(0, img.cols-1) );
|
||||||
|
EXPECT_EQ( 0xC0, img.at<uchar>(img.rows-1, 0) );
|
||||||
|
EXPECT_EQ( 0xD0, img.at<uchar>(img.rows-1, img.cols-1) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// RGB/RGBA TO BGR
|
||||||
|
case MAKE_FLAG(CV_8UC3, CV_8UC3):
|
||||||
|
case MAKE_FLAG(CV_8UC4, CV_8UC3):
|
||||||
|
case MAKE_FLAG(CV_16UC3, CV_8UC3):
|
||||||
|
case MAKE_FLAG(CV_16UC4, CV_8UC3):
|
||||||
|
EXPECT_EQ( 0xA2, img.at<Vec3b>(0, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xA1, img.at<Vec3b>(0, 0) [1] );
|
||||||
|
EXPECT_EQ( 0xA0, img.at<Vec3b>(0, 0) [2] );
|
||||||
|
EXPECT_EQ( 0xB2, img.at<Vec3b>(0, img.cols-1)[0] );
|
||||||
|
EXPECT_EQ( 0xB1, img.at<Vec3b>(0, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( 0xB0, img.at<Vec3b>(0, img.cols-1)[2] );
|
||||||
|
EXPECT_EQ( 0xC2, img.at<Vec3b>(img.rows-1, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xC1, img.at<Vec3b>(img.rows-1, 0) [1] );
|
||||||
|
EXPECT_EQ( 0xC0, img.at<Vec3b>(img.rows-1, 0) [2] );
|
||||||
|
EXPECT_EQ( 0xD2, img.at<Vec3b>(img.rows-1, img.cols-1)[0] );
|
||||||
|
EXPECT_EQ( 0xD1, img.at<Vec3b>(img.rows-1, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( 0xD0, img.at<Vec3b>(img.rows-1, img.cols-1)[2] );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// RGBA TO BGRA
|
||||||
|
case MAKE_FLAG(CV_8UC4, CV_8UC4):
|
||||||
|
case MAKE_FLAG(CV_16UC4, CV_8UC4):
|
||||||
|
EXPECT_EQ( 0xA2, img.at<Vec4b>(0, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xA1, img.at<Vec4b>(0, 0) [1] );
|
||||||
|
EXPECT_EQ( 0xA0, img.at<Vec4b>(0, 0) [2] );
|
||||||
|
EXPECT_EQ( 0xA3, img.at<Vec4b>(0, 0) [3] );
|
||||||
|
EXPECT_EQ( 0xB2, img.at<Vec4b>(0, img.cols-1)[0] );
|
||||||
|
EXPECT_EQ( 0xB1, img.at<Vec4b>(0, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( 0xB0, img.at<Vec4b>(0, img.cols-1)[2] );
|
||||||
|
EXPECT_EQ( 0xB3, img.at<Vec4b>(0, img.cols-1)[3] );
|
||||||
|
EXPECT_EQ( 0xC2, img.at<Vec4b>(img.rows-1, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xC1, img.at<Vec4b>(img.rows-1, 0) [1] );
|
||||||
|
EXPECT_EQ( 0xC0, img.at<Vec4b>(img.rows-1, 0) [2] );
|
||||||
|
EXPECT_EQ( 0xC3, img.at<Vec4b>(img.rows-1, 0) [3] );
|
||||||
|
EXPECT_EQ( 0xD2, img.at<Vec4b>(img.rows-1, img.cols-1)[0] );
|
||||||
|
EXPECT_EQ( 0xD1, img.at<Vec4b>(img.rows-1, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( 0xD0, img.at<Vec4b>(img.rows-1, img.cols-1)[2] );
|
||||||
|
EXPECT_EQ( 0xD3, img.at<Vec4b>(img.rows-1, img.cols-1)[3] );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// RGB/RGBA to GRAY
|
||||||
|
case MAKE_FLAG(CV_8UC3, CV_8UC1):
|
||||||
|
case MAKE_FLAG(CV_8UC4, CV_8UC1):
|
||||||
|
case MAKE_FLAG(CV_16UC3, CV_8UC1):
|
||||||
|
case MAKE_FLAG(CV_16UC4, CV_8UC1):
|
||||||
|
EXPECT_LE( 0xA0, img.at<uchar>(0, 0) );
|
||||||
|
EXPECT_GE( 0xA2, img.at<uchar>(0, 0) );
|
||||||
|
EXPECT_LE( 0xB0, img.at<uchar>(0, img.cols-1) );
|
||||||
|
EXPECT_GE( 0xB2, img.at<uchar>(0, img.cols-1) );
|
||||||
|
EXPECT_LE( 0xC0, img.at<uchar>(img.rows-1, 0) );
|
||||||
|
EXPECT_GE( 0xC2, img.at<uchar>(img.rows-1, 0) );
|
||||||
|
EXPECT_LE( 0xD0, img.at<uchar>(img.rows-1, img.cols-1) );
|
||||||
|
EXPECT_GE( 0xD2, img.at<uchar>(img.rows-1, img.cols-1) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// GRAY to BGR
|
||||||
|
case MAKE_FLAG(CV_8UC1, CV_8UC3):
|
||||||
|
case MAKE_FLAG(CV_16UC1, CV_8UC3):
|
||||||
|
EXPECT_EQ( 0xA0, img.at<Vec3b>(0, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xB0, img.at<Vec3b>(0, img.cols-1)[0] );
|
||||||
|
EXPECT_EQ( 0xC0, img.at<Vec3b>(img.rows-1, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xD0, img.at<Vec3b>(img.rows-1, img.cols-1)[0] );
|
||||||
|
// R==G==B
|
||||||
|
EXPECT_EQ( img.at<Vec3b>(0, 0) [0], img.at<Vec3b>(0, 0) [1] );
|
||||||
|
EXPECT_EQ( img.at<Vec3b>(0, 0) [0], img.at<Vec3b>(0, 0) [2] );
|
||||||
|
EXPECT_EQ( img.at<Vec3b>(0, img.cols-1) [0], img.at<Vec3b>(0, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( img.at<Vec3b>(0, img.cols-1) [0], img.at<Vec3b>(0, img.cols-1)[2] );
|
||||||
|
EXPECT_EQ( img.at<Vec3b>(img.rows-1, 0) [0], img.at<Vec3b>(img.rows-1, 0) [1] );
|
||||||
|
EXPECT_EQ( img.at<Vec3b>(img.rows-1, 0) [0], img.at<Vec3b>(img.rows-1, 0) [2] );
|
||||||
|
EXPECT_EQ( img.at<Vec3b>(img.rows-1, img.cols-1) [0], img.at<Vec3b>(img.rows-1, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( img.at<Vec3b>(img.rows-1, img.cols-1) [0], img.at<Vec3b>(img.rows-1, img.cols-1)[2] );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// GRAY TO GRAY
|
||||||
|
case MAKE_FLAG(CV_16UC1, CV_16UC1):
|
||||||
|
EXPECT_EQ( 0xA090, img.at<ushort>(0, 0) );
|
||||||
|
EXPECT_EQ( 0xB080, img.at<ushort>(0, img.cols-1) );
|
||||||
|
EXPECT_EQ( 0xC070, img.at<ushort>(img.rows-1, 0) );
|
||||||
|
EXPECT_EQ( 0xD060, img.at<ushort>(img.rows-1, img.cols-1) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// RGB/RGBA TO BGR
|
||||||
|
case MAKE_FLAG(CV_16UC3, CV_16UC3):
|
||||||
|
case MAKE_FLAG(CV_16UC4, CV_16UC3):
|
||||||
|
EXPECT_EQ( 0xA292, img.at<Vec3w>(0, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xA191, img.at<Vec3w>(0, 0) [1] );
|
||||||
|
EXPECT_EQ( 0xA090, img.at<Vec3w>(0, 0) [2] );
|
||||||
|
EXPECT_EQ( 0xB282, img.at<Vec3w>(0, img.cols-1)[0] );
|
||||||
|
EXPECT_EQ( 0xB181, img.at<Vec3w>(0, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( 0xB080, img.at<Vec3w>(0, img.cols-1)[2] );
|
||||||
|
EXPECT_EQ( 0xC272, img.at<Vec3w>(img.rows-1, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xC171, img.at<Vec3w>(img.rows-1, 0) [1] );
|
||||||
|
EXPECT_EQ( 0xC070, img.at<Vec3w>(img.rows-1, 0) [2] );
|
||||||
|
EXPECT_EQ( 0xD262, img.at<Vec3w>(img.rows-1, img.cols-1)[0] );
|
||||||
|
EXPECT_EQ( 0xD161, img.at<Vec3w>(img.rows-1, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( 0xD060, img.at<Vec3w>(img.rows-1, img.cols-1)[2] );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// RGBA TO RGBA
|
||||||
|
case MAKE_FLAG(CV_16UC4, CV_16UC4):
|
||||||
|
EXPECT_EQ( 0xA292, img.at<Vec4w>(0, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xA191, img.at<Vec4w>(0, 0) [1] );
|
||||||
|
EXPECT_EQ( 0xA090, img.at<Vec4w>(0, 0) [2] );
|
||||||
|
EXPECT_EQ( 0xA393, img.at<Vec4w>(0, 0) [3] );
|
||||||
|
EXPECT_EQ( 0xB282, img.at<Vec4w>(0, img.cols-1)[0] );
|
||||||
|
EXPECT_EQ( 0xB181, img.at<Vec4w>(0, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( 0xB080, img.at<Vec4w>(0, img.cols-1)[2] );
|
||||||
|
EXPECT_EQ( 0xB383, img.at<Vec4w>(0, img.cols-1)[3] );
|
||||||
|
EXPECT_EQ( 0xC272, img.at<Vec4w>(img.rows-1, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xC171, img.at<Vec4w>(img.rows-1, 0) [1] );
|
||||||
|
EXPECT_EQ( 0xC070, img.at<Vec4w>(img.rows-1, 0) [2] );
|
||||||
|
EXPECT_EQ( 0xC373, img.at<Vec4w>(img.rows-1, 0) [3] );
|
||||||
|
EXPECT_EQ( 0xD262, img.at<Vec4w>(img.rows-1,img.cols-1) [0] );
|
||||||
|
EXPECT_EQ( 0xD161, img.at<Vec4w>(img.rows-1,img.cols-1) [1] );
|
||||||
|
EXPECT_EQ( 0xD060, img.at<Vec4w>(img.rows-1,img.cols-1) [2] );
|
||||||
|
EXPECT_EQ( 0xD363, img.at<Vec4w>(img.rows-1,img.cols-1) [3] );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// RGB/RGBA to GRAY
|
||||||
|
case MAKE_FLAG(CV_16UC3, CV_16UC1):
|
||||||
|
case MAKE_FLAG(CV_16UC4, CV_16UC1):
|
||||||
|
EXPECT_LE( 0xA090, img.at<ushort>(0, 0) );
|
||||||
|
EXPECT_GE( 0xA292, img.at<ushort>(0, 0) );
|
||||||
|
EXPECT_LE( 0xB080, img.at<ushort>(0, img.cols-1) );
|
||||||
|
EXPECT_GE( 0xB282, img.at<ushort>(0, img.cols-1) );
|
||||||
|
EXPECT_LE( 0xC070, img.at<ushort>(img.rows-1, 0) );
|
||||||
|
EXPECT_GE( 0xC272, img.at<ushort>(img.rows-1, 0) );
|
||||||
|
EXPECT_LE( 0xD060, img.at<ushort>(img.rows-1, img.cols-1) );
|
||||||
|
EXPECT_GE( 0xD262, img.at<ushort>(img.rows-1, img.cols-1) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// GRAY to RGB
|
||||||
|
case MAKE_FLAG(CV_16UC1, CV_16UC3):
|
||||||
|
EXPECT_EQ( 0xA090, img.at<Vec3w>(0, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xB080, img.at<Vec3w>(0, img.cols-1)[0] );
|
||||||
|
EXPECT_EQ( 0xC070, img.at<Vec3w>(img.rows-1, 0) [0] );
|
||||||
|
EXPECT_EQ( 0xD060, img.at<Vec3w>(img.rows-1, img.cols-1)[0] );
|
||||||
|
// R==G==B
|
||||||
|
EXPECT_EQ( img.at<Vec3w>(0, 0) [0], img.at<Vec3w>(0, 0) [1] );
|
||||||
|
EXPECT_EQ( img.at<Vec3w>(0, 0) [0], img.at<Vec3w>(0, 0) [2] );
|
||||||
|
EXPECT_EQ( img.at<Vec3w>(0, img.cols-1) [0], img.at<Vec3w>(0, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( img.at<Vec3w>(0, img.cols-1) [0], img.at<Vec3w>(0, img.cols-1)[2] );
|
||||||
|
EXPECT_EQ( img.at<Vec3w>(img.rows-1, 0) [0], img.at<Vec3w>(img.rows-1, 0) [1] );
|
||||||
|
EXPECT_EQ( img.at<Vec3w>(img.rows-1, 0) [0], img.at<Vec3w>(img.rows-1, 0) [2] );
|
||||||
|
EXPECT_EQ( img.at<Vec3w>(img.rows-1, img.cols-1) [0], img.at<Vec3w>(img.rows-1, img.cols-1)[1] );
|
||||||
|
EXPECT_EQ( img.at<Vec3w>(img.rows-1, img.cols-1) [0], img.at<Vec3w>(img.rows-1, img.cols-1)[2] );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// No supported.
|
||||||
|
// (1) 8bit to 16bit
|
||||||
|
case MAKE_FLAG(CV_8UC1, CV_16UC1):
|
||||||
|
case MAKE_FLAG(CV_8UC1, CV_16UC3):
|
||||||
|
case MAKE_FLAG(CV_8UC1, CV_16UC4):
|
||||||
|
case MAKE_FLAG(CV_8UC3, CV_16UC1):
|
||||||
|
case MAKE_FLAG(CV_8UC3, CV_16UC3):
|
||||||
|
case MAKE_FLAG(CV_8UC3, CV_16UC4):
|
||||||
|
case MAKE_FLAG(CV_8UC4, CV_16UC1):
|
||||||
|
case MAKE_FLAG(CV_8UC4, CV_16UC3):
|
||||||
|
case MAKE_FLAG(CV_8UC4, CV_16UC4):
|
||||||
|
// (2) GRAY/RGB TO RGBA
|
||||||
|
case MAKE_FLAG(CV_8UC1, CV_8UC4):
|
||||||
|
case MAKE_FLAG(CV_8UC3, CV_8UC4):
|
||||||
|
case MAKE_FLAG(CV_16UC1, CV_8UC4):
|
||||||
|
case MAKE_FLAG(CV_16UC3, CV_8UC4):
|
||||||
|
case MAKE_FLAG(CV_16UC1, CV_16UC4):
|
||||||
|
case MAKE_FLAG(CV_16UC3, CV_16UC4):
|
||||||
|
default:
|
||||||
|
FAIL() << cv::format("Unknown test pattern: from = %d ( %d, %d) to = %d ( %d, %d )",
|
||||||
|
mat_type, (int)CV_MAT_CN(mat_type ), ( CV_MAT_DEPTH(mat_type )==CV_16U)?16:8,
|
||||||
|
img.type(), (int)CV_MAT_CN(img.type() ), ( CV_MAT_DEPTH(img.type() )==CV_16U)?16:8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MAKE_FLAG
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic Test
|
||||||
|
const Bufsize_and_Type Imgcodecs_Tiff_decode_Huge_list_basic[] =
|
||||||
|
{
|
||||||
|
make_tuple<uint64_t, tuple<string,int>,ImreadMixModes>( 1073479680ull, make_tuple<string,int>("CV_8UC1", CV_8UC1), IMREAD_MIX_COLOR ),
|
||||||
|
make_tuple<uint64_t, tuple<string,int>,ImreadMixModes>( 2147483648ull, make_tuple<string,int>("CV_16UC4", CV_16UC4), IMREAD_MIX_COLOR ),
|
||||||
|
};
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(Imgcodecs_Tiff, Imgcodecs_Tiff_decode_Huge,
|
||||||
|
testing::ValuesIn( Imgcodecs_Tiff_decode_Huge_list_basic )
|
||||||
|
);
|
||||||
|
|
||||||
|
// Full Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test lists for combination of IMREAD_*.
|
||||||
|
*/
|
||||||
|
const ImreadMixModes all_modes_Huge_Full[] =
|
||||||
|
{
|
||||||
|
IMREAD_MIX_UNCHANGED,
|
||||||
|
IMREAD_MIX_GRAYSCALE,
|
||||||
|
IMREAD_MIX_GRAYSCALE_ANYDEPTH,
|
||||||
|
IMREAD_MIX_GRAYSCALE_ANYCOLOR,
|
||||||
|
IMREAD_MIX_GRAYSCALE_ANYDEPTH_ANYCOLOR,
|
||||||
|
IMREAD_MIX_COLOR,
|
||||||
|
IMREAD_MIX_COLOR_ANYDEPTH,
|
||||||
|
IMREAD_MIX_COLOR_ANYCOLOR,
|
||||||
|
IMREAD_MIX_COLOR_ANYDEPTH_ANYCOLOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint64_t huge_buffer_sizes_decode_Full[] =
|
||||||
|
{
|
||||||
|
1048576ull, // 1 * 1024 * 1024
|
||||||
|
1073479680ull, // 1024 * 1024 * 1024 - 32768 * 4 * 2
|
||||||
|
1073741824ull, // 1024 * 1024 * 1024
|
||||||
|
2147483648ull, // 2048 * 1024 * 1024
|
||||||
|
};
|
||||||
|
|
||||||
|
const tuple<string, int> mat_types_Full[] =
|
||||||
|
{
|
||||||
|
make_tuple<string, int>("CV_8UC1", CV_8UC1), // 8bit GRAY
|
||||||
|
make_tuple<string, int>("CV_8UC3", CV_8UC3), // 24bit RGB
|
||||||
|
make_tuple<string, int>("CV_8UC4", CV_8UC4), // 32bit RGBA
|
||||||
|
make_tuple<string, int>("CV_16UC1", CV_16UC1), // 16bit GRAY
|
||||||
|
make_tuple<string, int>("CV_16UC3", CV_16UC3), // 48bit RGB
|
||||||
|
make_tuple<string, int>("CV_16UC4", CV_16UC4), // 64bit RGBA
|
||||||
|
};
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(DISABLED_Imgcodecs_Tiff_Full, Imgcodecs_Tiff_decode_Huge,
|
||||||
|
testing::Combine(
|
||||||
|
testing::ValuesIn(huge_buffer_sizes_decode_Full),
|
||||||
|
testing::ValuesIn(mat_types_Full),
|
||||||
|
testing::ValuesIn(all_modes_Huge_Full)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
|
||||||
TEST(Imgcodecs_Tiff, write_read_16bit_big_little_endian)
|
TEST(Imgcodecs_Tiff, write_read_16bit_big_little_endian)
|
||||||
{
|
{
|
||||||
// see issue #2601 "16-bit Grayscale TIFF Load Failures Due to Buffer Underflow and Endianness"
|
// see issue #2601 "16-bit Grayscale TIFF Load Failures Due to Buffer Underflow and Endianness"
|
||||||
|
Loading…
Reference in New Issue
Block a user