diff --git a/modules/imgcodecs/src/grfmt_tiff.cpp b/modules/imgcodecs/src/grfmt_tiff.cpp index 0aa64e3143..8c594a3417 100644 --- a/modules/imgcodecs/src/grfmt_tiff.cpp +++ b/modules/imgcodecs/src/grfmt_tiff.cpp @@ -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(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(row,i) = data[i]; + } + } + _TIFFfree(buf); + close(); + + return true; +} + ////////////////////////////////////////////////////////////////////////////////////////// TiffEncoder::TiffEncoder() @@ -818,7 +861,7 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const std::vector& 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(row), row, 1) != 1) + { + TIFFClose(tif); + return false; + } + } + TIFFWriteDirectory(tif); + TIFFClose(tif); + + return true; +} + bool TiffEncoder::write( const Mat& img, const std::vector& 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); diff --git a/modules/imgcodecs/src/grfmt_tiff.hpp b/modules/imgcodecs/src/grfmt_tiff.hpp index 95c61798bc..2485e2d892 100644 --- a/modules/imgcodecs/src/grfmt_tiff.hpp +++ b/modules/imgcodecs/src/grfmt_tiff.hpp @@ -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& params ); - bool writeHdr( const Mat& img ); + bool write_32FC3( const Mat& img ); + bool write_32FC1( const Mat& img ); private: TiffEncoder(const TiffEncoder &); // copy disabled diff --git a/modules/imgcodecs/test/test_tiff.cpp b/modules/imgcodecs/test/test_tiff.cpp index 6ef0c17482..0f6a279b9a 100644 --- a/modules/imgcodecs/test/test_tiff.cpp +++ b/modules/imgcodecs/test/test_tiff.cpp @@ -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 Imgcodecs_Tiff_Modes;