mirror of
https://github.com/opencv/opencv.git
synced 2025-01-18 22:44:02 +08:00
Merge pull request #10493 from RachexCoralie:tiff32FC1Codec
* Load and save tiff images in CV_32FC1 format (1 channel of floats). * Add test * Fix error handling and resources leak. Improve test.
This commit is contained in:
parent
45c5f0a549
commit
16821b877c
@ -292,7 +292,11 @@ bool TiffDecoder::readData( Mat& img )
|
||||
{
|
||||
if(m_hdr && img.type() == CV_32FC3)
|
||||
{
|
||||
return readHdrData(img);
|
||||
return readData_32FC3(img);
|
||||
}
|
||||
if(img.type() == CV_32FC1)
|
||||
{
|
||||
return readData_32FC1(img);
|
||||
}
|
||||
bool result = false;
|
||||
bool color = img.channels() > 1;
|
||||
@ -528,8 +532,9 @@ bool TiffDecoder::readData( Mat& img )
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TiffDecoder::readHdrData(Mat& img)
|
||||
bool TiffDecoder::readData_32FC3(Mat& img)
|
||||
{
|
||||
|
||||
int rows_per_strip = 0, photometric = 0;
|
||||
if(!m_tif)
|
||||
{
|
||||
@ -559,6 +564,44 @@ bool TiffDecoder::readHdrData(Mat& img)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TiffDecoder::readData_32FC1(Mat& img)
|
||||
{
|
||||
if(!m_tif)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
TIFF *tif = static_cast<TIFF*>(m_tif);
|
||||
|
||||
uint32 img_width, img_height;
|
||||
TIFFGetField(tif,TIFFTAG_IMAGEWIDTH, &img_width);
|
||||
TIFFGetField(tif,TIFFTAG_IMAGELENGTH, &img_height);
|
||||
if(img.size() != Size(img_width,img_height))
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
tsize_t scanlength = TIFFScanlineSize(tif);
|
||||
tdata_t buf = _TIFFmalloc(scanlength);
|
||||
float* data;
|
||||
for (uint32 row = 0; row < img_height; row++)
|
||||
{
|
||||
if (TIFFReadScanline(tif, buf, row) != 1)
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
data=(float*)buf;
|
||||
for (uint32 i=0; i<img_width; i++)
|
||||
{
|
||||
img.at<float>(row,i) = data[i];
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TiffEncoder::TiffEncoder()
|
||||
@ -818,7 +861,7 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const std::vector<int>& params)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TiffEncoder::writeHdr(const Mat& _img)
|
||||
bool TiffEncoder::write_32FC3(const Mat& _img)
|
||||
{
|
||||
Mat img;
|
||||
cvtColor(_img, img, COLOR_BGR2XYZ);
|
||||
@ -857,13 +900,58 @@ bool TiffEncoder::writeHdr(const Mat& _img)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TiffEncoder::write_32FC1(const Mat& _img)
|
||||
{
|
||||
|
||||
TIFF* tif;
|
||||
|
||||
TiffEncoderBufHelper buf_helper(m_buf);
|
||||
if ( m_buf )
|
||||
{
|
||||
tif = buf_helper.open();
|
||||
}
|
||||
else
|
||||
{
|
||||
tif = TIFFOpen(m_filename.c_str(), "w");
|
||||
}
|
||||
|
||||
if (!tif)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, _img.cols);
|
||||
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, _img.rows);
|
||||
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
|
||||
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
|
||||
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
|
||||
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
|
||||
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
|
||||
for (uint32 row = 0; row < (uint32)_img.rows; row++)
|
||||
{
|
||||
if (TIFFWriteScanline(tif, (tdata_t)_img.ptr<float>(row), row, 1) != 1)
|
||||
{
|
||||
TIFFClose(tif);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
TIFFWriteDirectory(tif);
|
||||
TIFFClose(tif);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TiffEncoder::write( const Mat& img, const std::vector<int>& params)
|
||||
{
|
||||
int depth = img.depth();
|
||||
|
||||
if(img.type() == CV_32FC3)
|
||||
{
|
||||
return writeHdr(img); // TODO Rename
|
||||
return write_32FC3(img);
|
||||
}
|
||||
if(img.type() == CV_32FC1)
|
||||
{
|
||||
return write_32FC1(img);
|
||||
}
|
||||
|
||||
CV_Assert(depth == CV_8U || depth == CV_16U);
|
||||
|
@ -108,7 +108,8 @@ public:
|
||||
protected:
|
||||
void* m_tif;
|
||||
int normalizeChannelsNumber(int channels) const;
|
||||
bool readHdrData(Mat& img);
|
||||
bool readData_32FC3(Mat& img);
|
||||
bool readData_32FC1(Mat& img);
|
||||
bool m_hdr;
|
||||
size_t m_buf_pos;
|
||||
|
||||
@ -135,7 +136,8 @@ protected:
|
||||
int count, int value );
|
||||
|
||||
bool writeLibTiff( const Mat& img, const std::vector<int>& params );
|
||||
bool writeHdr( const Mat& img );
|
||||
bool write_32FC3( const Mat& img );
|
||||
bool write_32FC1( const Mat& img );
|
||||
|
||||
private:
|
||||
TiffEncoder(const TiffEncoder &); // copy disabled
|
||||
|
@ -146,6 +146,23 @@ TEST(Imgcodecs_Tiff, decode_infinite_rowsperstrip)
|
||||
EXPECT_EQ(0, remove(filename.c_str()));
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_Tiff, readWrite_32FC1)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test32FC1.tiff";
|
||||
const string filenameOutput = cv::tempfile(".tiff");
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_32FC1,img.type());
|
||||
|
||||
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
|
||||
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
|
||||
ASSERT_EQ(img2.type(),img.type());
|
||||
ASSERT_EQ(img2.size(),img.size());
|
||||
EXPECT_GE(1e-3, cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE));
|
||||
EXPECT_EQ(0, remove(filenameOutput.c_str()));
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
typedef testing::TestWithParam<int> Imgcodecs_Tiff_Modes;
|
||||
|
Loading…
Reference in New Issue
Block a user