Commit 16821b87 authored by Coralie RACHEX's avatar Coralie RACHEX Committed by Alexander Alekhin

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.
parent 45c5f0a5
...@@ -292,7 +292,11 @@ bool TiffDecoder::readData( Mat& img ) ...@@ -292,7 +292,11 @@ bool TiffDecoder::readData( Mat& img )
{ {
if(m_hdr && img.type() == CV_32FC3) 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 result = false;
bool color = img.channels() > 1; bool color = img.channels() > 1;
...@@ -528,8 +532,9 @@ bool TiffDecoder::readData( Mat& img ) ...@@ -528,8 +532,9 @@ bool TiffDecoder::readData( Mat& img )
return result; return result;
} }
bool TiffDecoder::readHdrData(Mat& img) bool TiffDecoder::readData_32FC3(Mat& img)
{ {
int rows_per_strip = 0, photometric = 0; int rows_per_strip = 0, photometric = 0;
if(!m_tif) if(!m_tif)
{ {
...@@ -559,6 +564,44 @@ bool TiffDecoder::readHdrData(Mat& img) ...@@ -559,6 +564,44 @@ bool TiffDecoder::readHdrData(Mat& img)
return true; 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() TiffEncoder::TiffEncoder()
...@@ -818,7 +861,7 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const std::vector<int>& params) ...@@ -818,7 +861,7 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const std::vector<int>& params)
return true; return true;
} }
bool TiffEncoder::writeHdr(const Mat& _img) bool TiffEncoder::write_32FC3(const Mat& _img)
{ {
Mat img; Mat img;
cvtColor(_img, img, COLOR_BGR2XYZ); cvtColor(_img, img, COLOR_BGR2XYZ);
...@@ -857,13 +900,58 @@ bool TiffEncoder::writeHdr(const Mat& _img) ...@@ -857,13 +900,58 @@ bool TiffEncoder::writeHdr(const Mat& _img)
return true; 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) bool TiffEncoder::write( const Mat& img, const std::vector<int>& params)
{ {
int depth = img.depth(); int depth = img.depth();
if(img.type() == CV_32FC3) 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); CV_Assert(depth == CV_8U || depth == CV_16U);
......
...@@ -108,7 +108,8 @@ public: ...@@ -108,7 +108,8 @@ public:
protected: protected:
void* m_tif; void* m_tif;
int normalizeChannelsNumber(int channels) const; int normalizeChannelsNumber(int channels) const;
bool readHdrData(Mat& img); bool readData_32FC3(Mat& img);
bool readData_32FC1(Mat& img);
bool m_hdr; bool m_hdr;
size_t m_buf_pos; size_t m_buf_pos;
...@@ -135,7 +136,8 @@ protected: ...@@ -135,7 +136,8 @@ protected:
int count, int value ); int count, int value );
bool writeLibTiff( const Mat& img, const std::vector<int>& params ); 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: private:
TiffEncoder(const TiffEncoder &); // copy disabled TiffEncoder(const TiffEncoder &); // copy disabled
......
...@@ -146,6 +146,23 @@ TEST(Imgcodecs_Tiff, decode_infinite_rowsperstrip) ...@@ -146,6 +146,23 @@ TEST(Imgcodecs_Tiff, decode_infinite_rowsperstrip)
EXPECT_EQ(0, remove(filename.c_str())); 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; typedef testing::TestWithParam<int> Imgcodecs_Tiff_Modes;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment