提交 16821b87 编写于 作者: C Coralie RACHEX 提交者: 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.
上级 45c5f0a5
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册