From f4a7754cc0495b587ef29fa5b8c2006513cfd615 Mon Sep 17 00:00:00 2001 From: Harvey <619328684@qq.com> Date: Tue, 1 Feb 2022 01:54:27 +0800 Subject: [PATCH] Merge pull request #21428 from Harvey-Huang:TIFF TiffEncoder write support more depth type * TiffEncoder write support more depth type * testing code * update testing code * add fallthrough --- modules/imgcodecs/src/grfmt_tiff.cpp | 21 +++++++++++++++++---- modules/imgcodecs/test/test_tiff.cpp | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_tiff.cpp b/modules/imgcodecs/src/grfmt_tiff.cpp index 05cc99c16c..cb4afb9f25 100644 --- a/modules/imgcodecs/src/grfmt_tiff.cpp +++ b/modules/imgcodecs/src/grfmt_tiff.cpp @@ -721,7 +721,7 @@ ImageEncoder TiffEncoder::newEncoder() const bool TiffEncoder::isFormatSupported( int depth ) const { - return depth == CV_8U || depth == CV_16U || depth == CV_32F || depth == CV_64F; + return depth == CV_8U || depth == CV_8S || depth == CV_16U || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F; } void TiffEncoder::writeTag( WLByteStream& strm, TiffTag tag, @@ -865,7 +865,7 @@ bool TiffEncoder::writeLibTiff( const std::vector& img_vec, const std::vect int width = img.cols, height = img.rows; int type = img.type(); int depth = CV_MAT_DEPTH(type); - CV_CheckType(type, depth == CV_8U || depth == CV_16U || depth == CV_32F || depth == CV_64F, ""); + CV_CheckType(type, depth == CV_8U || depth == CV_8S || depth == CV_16U || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F, ""); CV_CheckType(type, channels >= 1 && channels <= 4, ""); CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width)); @@ -888,19 +888,31 @@ bool TiffEncoder::writeLibTiff( const std::vector& img_vec, const std::vect int page_compression = compression; int bitsPerChannel = -1; + uint16 sample_format = SAMPLEFORMAT_INT; switch (depth) { case CV_8U: + sample_format = SAMPLEFORMAT_UINT; + /* FALLTHRU */ + case CV_8S: { bitsPerChannel = 8; break; } + case CV_16U: + sample_format = SAMPLEFORMAT_UINT; + /* FALLTHRU */ + case CV_16S: { bitsPerChannel = 16; break; } + case CV_32F: + sample_format = SAMPLEFORMAT_IEEEFP; + /* FALLTHRU */ + case CV_32S: { bitsPerChannel = 32; page_compression = COMPRESSION_NONE; @@ -910,6 +922,7 @@ bool TiffEncoder::writeLibTiff( const std::vector& img_vec, const std::vect { bitsPerChannel = 64; page_compression = COMPRESSION_NONE; + sample_format = SAMPLEFORMAT_IEEEFP; break; } default: @@ -935,7 +948,7 @@ bool TiffEncoder::writeLibTiff( const std::vector& img_vec, const std::vect CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)); CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsPerStrip)); - CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, depth >= CV_32F ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT)); + CV_TIFF_CHECK_CALL(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, sample_format)); if (page_compression != COMPRESSION_NONE) { @@ -1034,7 +1047,7 @@ bool TiffEncoder::write( const Mat& img, const std::vector& params) int type = img.type(); int depth = CV_MAT_DEPTH(type); - CV_CheckType(type, depth == CV_8U || depth == CV_16U || depth == CV_32F || depth == CV_64F, ""); + CV_CheckType(type, depth == CV_8U || depth == CV_8S || depth == CV_16U || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F, ""); std::vector img_vec; img_vec.push_back(img); diff --git a/modules/imgcodecs/test/test_tiff.cpp b/modules/imgcodecs/test/test_tiff.cpp index 9a0dd2a746..1c6e4a6b29 100644 --- a/modules/imgcodecs/test/test_tiff.cpp +++ b/modules/imgcodecs/test/test_tiff.cpp @@ -147,6 +147,26 @@ TEST(Imgcodecs_Tiff, decode_infinite_rowsperstrip) EXPECT_EQ(0, remove(filename.c_str())); } +TEST(Imgcodecs_Tiff, readWrite_unsigned) +{ + const string root = cvtest::TS::ptr()->get_data_path(); + const string filenameInput = root + "readwrite/gray_8u.tif"; + const string filenameOutput = cv::tempfile(".tiff"); + const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED); + ASSERT_FALSE(img.empty()); + ASSERT_EQ(CV_8UC1, img.type()); + + Mat matS8; + img.convertTo(matS8, CV_8SC1); + + ASSERT_TRUE(cv::imwrite(filenameOutput, matS8)); + const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED); + ASSERT_EQ(img2.type(), matS8.type()); + ASSERT_EQ(img2.size(), matS8.size()); + EXPECT_LE(cvtest::norm(matS8, img2, NORM_INF | NORM_RELATIVE), 1e-3); + EXPECT_EQ(0, remove(filenameOutput.c_str())); +} + TEST(Imgcodecs_Tiff, readWrite_32FC1) { const string root = cvtest::TS::ptr()->get_data_path();