Skip to content

Commit c131c12

Browse files
asmorkalovDaniel Rydstrom
andauthored
Merge pull request opencv#19540 from asmorkalov:as/openexr_comression_options
OpenEXR compression options * Adding possibility to select the compression type for the OpenEXR format. There are compression modes other than the default that are more suited for certain data. Mainly grainy/noisy data. * Code review fixes. Co-authored-by: Daniel Rydstrom <daniel.rydstrom@sick.se>
1 parent ca7518c commit c131c12

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

modules/imgcodecs/include/opencv2/imgcodecs.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ enum ImwriteFlags {
9595
IMWRITE_PNG_BILEVEL = 18, //!< Binary level PNG, 0 or 1, default is 0.
9696
IMWRITE_PXM_BINARY = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1.
9797
IMWRITE_EXR_TYPE = (3 << 4) + 0, /* 48 */ //!< override EXR storage type (FLOAT (FP32) is default)
98+
IMWRITE_EXR_COMPRESSION = (3 << 4) + 1, /* 49 */ //!< override EXR compression type (ZIP_COMPRESSION = 3 is default)
9899
IMWRITE_WEBP_QUALITY = 64, //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used.
99100
IMWRITE_PAM_TUPLETYPE = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format
100101
IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set; see libtiff documentation for valid values
@@ -110,6 +111,19 @@ enum ImwriteEXRTypeFlags {
110111
IMWRITE_EXR_TYPE_FLOAT = 2 //!< store as FP32 (default)
111112
};
112113

114+
enum ImwriteEXRCompressionFlags {
115+
IMWRITE_EXR_COMPRESSION_NO = 0, //!< no compression
116+
IMWRITE_EXR_COMPRESSION_RLE = 1, //!< run length encoding
117+
IMWRITE_EXR_COMPRESSION_ZIPS = 2, //!< zlib compression, one scan line at a time
118+
IMWRITE_EXR_COMPRESSION_ZIP = 3, //!< zlib compression, in blocks of 16 scan lines
119+
IMWRITE_EXR_COMPRESSION_PIZ = 4, //!< piz-based wavelet compression
120+
IMWRITE_EXR_COMPRESSION_PXR24 = 5, //!< lossy 24-bit float compression
121+
IMWRITE_EXR_COMPRESSION_B44 = 6, //!< lossy 4-by-4 pixel block compression, fixed compression rate
122+
IMWRITE_EXR_COMPRESSION_B44A = 7, //!< lossy 4-by-4 pixel block compression, flat fields are compressed more
123+
IMWRITE_EXR_COMPRESSION_DWAA = 8, //!< lossy DCT based compression, in blocks of 32 scanlines. More efficient for partial buffer access.
124+
IMWRITE_EXR_COMPRESSION_DWAB = 9, //!< lossy DCT based compression, in blocks of 256 scanlines. More efficient space wise and faster to decode full frames than DWAA_COMPRESSION.
125+
};
126+
113127
//! Imwrite PNG specific flags used to tune the compression algorithm.
114128
/** These flags will be modify the way of PNG image compression and will be passed to the underlying zlib processing stage.
115129

modules/imgcodecs/src/grfmt_exr.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,45 @@ bool ExrEncoder::write( const Mat& img, const std::vector<int>& params )
589589
type = FLOAT;
590590
break;
591591
default:
592-
throw std::runtime_error( "IMWRITE_EXR_TYPE is invalid or not supported" );
592+
CV_Error(Error::StsBadArg, "IMWRITE_EXR_TYPE is invalid or not supported");
593+
}
594+
}
595+
if ( params[i] == IMWRITE_EXR_COMPRESSION )
596+
{
597+
switch ( params[i + 1] )
598+
{
599+
case IMWRITE_EXR_COMPRESSION_NO:
600+
header.compression() = NO_COMPRESSION;
601+
break;
602+
case IMWRITE_EXR_COMPRESSION_RLE:
603+
header.compression() = RLE_COMPRESSION;
604+
break;
605+
case IMWRITE_EXR_COMPRESSION_ZIPS:
606+
header.compression() = ZIPS_COMPRESSION;
607+
break;
608+
case IMWRITE_EXR_COMPRESSION_ZIP:
609+
header.compression() = ZIP_COMPRESSION;
610+
break;
611+
case IMWRITE_EXR_COMPRESSION_PIZ:
612+
header.compression() = PIZ_COMPRESSION;
613+
break;
614+
case IMWRITE_EXR_COMPRESSION_PXR24:
615+
header.compression() = PXR24_COMPRESSION;
616+
break;
617+
case IMWRITE_EXR_COMPRESSION_B44:
618+
header.compression() = B44_COMPRESSION;
619+
break;
620+
case IMWRITE_EXR_COMPRESSION_B44A:
621+
header.compression() = B44A_COMPRESSION;
622+
break;
623+
case IMWRITE_EXR_COMPRESSION_DWAA:
624+
header.compression() = DWAA_COMPRESSION;
625+
break;
626+
case IMWRITE_EXR_COMPRESSION_DWAB:
627+
header.compression() = DWAB_COMPRESSION;
628+
break;
629+
default:
630+
CV_Error(Error::StsBadArg, "IMWRITE_EXR_COMPRESSION is invalid or not supported");
593631
}
594632
}
595633
}

modules/imgcodecs/test/test_exr.impl.hpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66

77
namespace opencv_test { namespace {
88

9+
size_t getFileSize(const string& filename)
10+
{
11+
std::ifstream ifs(filename.c_str(), std::ios::in | std::ios::binary);
12+
if (ifs.is_open())
13+
{
14+
ifs.seekg(0, std::ios::end);
15+
return ifs.tellg();
16+
}
17+
return 0;
18+
}
19+
920
TEST(Imgcodecs_EXR, readWrite_32FC1)
1021
{
1122
const string root = cvtest::TS::ptr()->get_data_path();
@@ -23,6 +34,8 @@ TEST(Imgcodecs_EXR, readWrite_32FC1)
2334
ASSERT_EQ(CV_32FC1,img.type());
2435

2536
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
37+
// Check generated file size to ensure that it's compressed with proper options
38+
ASSERT_EQ(396u, getFileSize(filenameOutput));
2639
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
2740
ASSERT_EQ(img2.type(), img.type());
2841
ASSERT_EQ(img2.size(), img.size());
@@ -113,5 +126,29 @@ TEST(Imgcodecs_EXR, readWrite_32FC3_half)
113126
EXPECT_EQ(0, remove(filenameOutput.c_str()));
114127
}
115128

129+
TEST(Imgcodecs_EXR, readWrite_32FC1_PIZ)
130+
{
131+
const string root = cvtest::TS::ptr()->get_data_path();
132+
const string filenameInput = root + "readwrite/test32FC1.exr";
133+
const string filenameOutput = cv::tempfile(".exr");
134+
135+
136+
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
137+
ASSERT_FALSE(img.empty());
138+
ASSERT_EQ(CV_32FC1, img.type());
139+
140+
std::vector<int> params;
141+
params.push_back(IMWRITE_EXR_COMPRESSION);
142+
params.push_back(IMWRITE_EXR_COMPRESSION_PIZ);
143+
ASSERT_TRUE(cv::imwrite(filenameOutput, img, params));
144+
// Check generated file size to ensure that it's compressed with proper options
145+
ASSERT_EQ(849u, getFileSize(filenameOutput));
146+
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
147+
ASSERT_EQ(img2.type(), img.type());
148+
ASSERT_EQ(img2.size(), img.size());
149+
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
150+
EXPECT_EQ(0, remove(filenameOutput.c_str()));
151+
}
152+
116153

117154
}} // namespace

0 commit comments

Comments
 (0)