Skip to content

Commit 16821b8

Browse files
RCoraliealalek
authored andcommitted
Merge pull request opencv#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.
1 parent 45c5f0a commit 16821b8

File tree

3 files changed

+113
-6
lines changed

3 files changed

+113
-6
lines changed

modules/imgcodecs/src/grfmt_tiff.cpp

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,11 @@ bool TiffDecoder::readData( Mat& img )
292292
{
293293
if(m_hdr && img.type() == CV_32FC3)
294294
{
295-
return readHdrData(img);
295+
return readData_32FC3(img);
296+
}
297+
if(img.type() == CV_32FC1)
298+
{
299+
return readData_32FC1(img);
296300
}
297301
bool result = false;
298302
bool color = img.channels() > 1;
@@ -528,8 +532,9 @@ bool TiffDecoder::readData( Mat& img )
528532
return result;
529533
}
530534

531-
bool TiffDecoder::readHdrData(Mat& img)
535+
bool TiffDecoder::readData_32FC3(Mat& img)
532536
{
537+
533538
int rows_per_strip = 0, photometric = 0;
534539
if(!m_tif)
535540
{
@@ -559,6 +564,44 @@ bool TiffDecoder::readHdrData(Mat& img)
559564
return true;
560565
}
561566

567+
bool TiffDecoder::readData_32FC1(Mat& img)
568+
{
569+
if(!m_tif)
570+
{
571+
return false;
572+
}
573+
TIFF *tif = static_cast<TIFF*>(m_tif);
574+
575+
uint32 img_width, img_height;
576+
TIFFGetField(tif,TIFFTAG_IMAGEWIDTH, &img_width);
577+
TIFFGetField(tif,TIFFTAG_IMAGELENGTH, &img_height);
578+
if(img.size() != Size(img_width,img_height))
579+
{
580+
close();
581+
return false;
582+
}
583+
tsize_t scanlength = TIFFScanlineSize(tif);
584+
tdata_t buf = _TIFFmalloc(scanlength);
585+
float* data;
586+
for (uint32 row = 0; row < img_height; row++)
587+
{
588+
if (TIFFReadScanline(tif, buf, row) != 1)
589+
{
590+
close();
591+
return false;
592+
}
593+
data=(float*)buf;
594+
for (uint32 i=0; i<img_width; i++)
595+
{
596+
img.at<float>(row,i) = data[i];
597+
}
598+
}
599+
_TIFFfree(buf);
600+
close();
601+
602+
return true;
603+
}
604+
562605
//////////////////////////////////////////////////////////////////////////////////////////
563606

564607
TiffEncoder::TiffEncoder()
@@ -818,7 +861,7 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const std::vector<int>& params)
818861
return true;
819862
}
820863

821-
bool TiffEncoder::writeHdr(const Mat& _img)
864+
bool TiffEncoder::write_32FC3(const Mat& _img)
822865
{
823866
Mat img;
824867
cvtColor(_img, img, COLOR_BGR2XYZ);
@@ -857,13 +900,58 @@ bool TiffEncoder::writeHdr(const Mat& _img)
857900
return true;
858901
}
859902

903+
bool TiffEncoder::write_32FC1(const Mat& _img)
904+
{
905+
906+
TIFF* tif;
907+
908+
TiffEncoderBufHelper buf_helper(m_buf);
909+
if ( m_buf )
910+
{
911+
tif = buf_helper.open();
912+
}
913+
else
914+
{
915+
tif = TIFFOpen(m_filename.c_str(), "w");
916+
}
917+
918+
if (!tif)
919+
{
920+
return false;
921+
}
922+
923+
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, _img.cols);
924+
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, _img.rows);
925+
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
926+
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
927+
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
928+
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
929+
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
930+
for (uint32 row = 0; row < (uint32)_img.rows; row++)
931+
{
932+
if (TIFFWriteScanline(tif, (tdata_t)_img.ptr<float>(row), row, 1) != 1)
933+
{
934+
TIFFClose(tif);
935+
return false;
936+
}
937+
}
938+
TIFFWriteDirectory(tif);
939+
TIFFClose(tif);
940+
941+
return true;
942+
}
943+
860944
bool TiffEncoder::write( const Mat& img, const std::vector<int>& params)
861945
{
862946
int depth = img.depth();
863947

864948
if(img.type() == CV_32FC3)
865949
{
866-
return writeHdr(img); // TODO Rename
950+
return write_32FC3(img);
951+
}
952+
if(img.type() == CV_32FC1)
953+
{
954+
return write_32FC1(img);
867955
}
868956

869957
CV_Assert(depth == CV_8U || depth == CV_16U);

modules/imgcodecs/src/grfmt_tiff.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ class TiffDecoder : public BaseImageDecoder
108108
protected:
109109
void* m_tif;
110110
int normalizeChannelsNumber(int channels) const;
111-
bool readHdrData(Mat& img);
111+
bool readData_32FC3(Mat& img);
112+
bool readData_32FC1(Mat& img);
112113
bool m_hdr;
113114
size_t m_buf_pos;
114115

@@ -135,7 +136,8 @@ class TiffEncoder : public BaseImageEncoder
135136
int count, int value );
136137

137138
bool writeLibTiff( const Mat& img, const std::vector<int>& params );
138-
bool writeHdr( const Mat& img );
139+
bool write_32FC3( const Mat& img );
140+
bool write_32FC1( const Mat& img );
139141

140142
private:
141143
TiffEncoder(const TiffEncoder &); // copy disabled

modules/imgcodecs/test/test_tiff.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,23 @@ TEST(Imgcodecs_Tiff, decode_infinite_rowsperstrip)
146146
EXPECT_EQ(0, remove(filename.c_str()));
147147
}
148148

149+
TEST(Imgcodecs_Tiff, readWrite_32FC1)
150+
{
151+
const string root = cvtest::TS::ptr()->get_data_path();
152+
const string filenameInput = root + "readwrite/test32FC1.tiff";
153+
const string filenameOutput = cv::tempfile(".tiff");
154+
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
155+
ASSERT_FALSE(img.empty());
156+
ASSERT_EQ(CV_32FC1,img.type());
157+
158+
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
159+
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
160+
ASSERT_EQ(img2.type(),img.type());
161+
ASSERT_EQ(img2.size(),img.size());
162+
EXPECT_GE(1e-3, cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE));
163+
EXPECT_EQ(0, remove(filenameOutput.c_str()));
164+
}
165+
149166
//==================================================================================================
150167

151168
typedef testing::TestWithParam<int> Imgcodecs_Tiff_Modes;

0 commit comments

Comments
 (0)