test_exr.impl.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html
  4. //#define GENERATE_DATA
  5. namespace opencv_test { namespace {
  6. size_t getFileSize(const string& filename)
  7. {
  8. std::ifstream ifs(filename.c_str(), std::ios::in | std::ios::binary);
  9. if (ifs.is_open())
  10. {
  11. ifs.seekg(0, std::ios::end);
  12. return (size_t)ifs.tellg();
  13. }
  14. return 0;
  15. }
  16. TEST(Imgcodecs_EXR, readWrite_32FC1)
  17. { // Y channels
  18. const string root = cvtest::TS::ptr()->get_data_path();
  19. const string filenameInput = root + "readwrite/test32FC1.exr";
  20. const string filenameOutput = cv::tempfile(".exr");
  21. #ifndef GENERATE_DATA
  22. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  23. #else
  24. const Size sz(64, 32);
  25. Mat img(sz, CV_32FC1, Scalar(0.5, 0.1, 1));
  26. img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0));
  27. ASSERT_TRUE(cv::imwrite(filenameInput, img));
  28. #endif
  29. ASSERT_FALSE(img.empty());
  30. ASSERT_EQ(CV_32FC1,img.type());
  31. ASSERT_TRUE(cv::imwrite(filenameOutput, img));
  32. // Check generated file size to ensure that it's compressed with proper options
  33. ASSERT_LE(396u, getFileSize(filenameOutput)); // OpenEXR 2
  34. ASSERT_LE( getFileSize(filenameOutput), 440u); // OpenEXR 3.2+
  35. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  36. ASSERT_EQ(img2.type(), img.type());
  37. ASSERT_EQ(img2.size(), img.size());
  38. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  39. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  40. }
  41. TEST(Imgcodecs_EXR, readWrite_32FC3)
  42. { // RGB channels
  43. const string root = cvtest::TS::ptr()->get_data_path();
  44. const string filenameInput = root + "readwrite/test32FC3.exr";
  45. const string filenameOutput = cv::tempfile(".exr");
  46. #ifndef GENERATE_DATA
  47. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  48. #else
  49. const Size sz(64, 32);
  50. Mat img(sz, CV_32FC3, Scalar(0.5, 0.1, 1));
  51. img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0));
  52. ASSERT_TRUE(cv::imwrite(filenameInput, img));
  53. #endif
  54. ASSERT_FALSE(img.empty());
  55. ASSERT_EQ(CV_32FC3, img.type());
  56. ASSERT_TRUE(cv::imwrite(filenameOutput, img));
  57. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  58. ASSERT_EQ(img2.type(), img.type());
  59. ASSERT_EQ(img2.size(), img.size());
  60. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  61. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  62. }
  63. TEST(Imgcodecs_EXR, readWrite_32FC7)
  64. { // 0-6 channels (multispectral)
  65. const string root = cvtest::TS::ptr()->get_data_path();
  66. const string filenameInput = root + "readwrite/test32FC7.exr";
  67. const string filenameOutput = cv::tempfile(".exr");
  68. #ifndef GENERATE_DATA
  69. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  70. #else
  71. const Size sz(3, 5);
  72. Mat img(sz, CV_32FC7);
  73. img.at<cv::Vec<float, 7>>(0, 0)[0] = 101.125;
  74. img.at<cv::Vec<float, 7>>(2, 1)[3] = 203.500;
  75. img.at<cv::Vec<float, 7>>(4, 2)[6] = 305.875;
  76. ASSERT_TRUE(cv::imwrite(filenameInput, img));
  77. #endif
  78. ASSERT_FALSE(img.empty());
  79. ASSERT_EQ(CV_MAKETYPE(CV_32F, 7), img.type());
  80. ASSERT_TRUE(cv::imwrite(filenameOutput, img));
  81. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  82. EXPECT_EQ(img2.type(), img.type());
  83. EXPECT_EQ(img2.size(), img.size());
  84. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  85. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  86. const Mat img3 = cv::imread(filenameInput, IMREAD_GRAYSCALE);
  87. ASSERT_TRUE(img3.empty());
  88. const Mat img4 = cv::imread(filenameInput, IMREAD_COLOR);
  89. ASSERT_TRUE(img4.empty());
  90. }
  91. TEST(Imgcodecs_EXR, readWrite_32FC1_half)
  92. {
  93. const string root = cvtest::TS::ptr()->get_data_path();
  94. const string filenameInput = root + "readwrite/test32FC1_half.exr";
  95. const string filenameOutput = cv::tempfile(".exr");
  96. std::vector<int> params;
  97. params.push_back(IMWRITE_EXR_TYPE);
  98. params.push_back(IMWRITE_EXR_TYPE_HALF);
  99. #ifndef GENERATE_DATA
  100. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  101. #else
  102. const Size sz(64, 32);
  103. Mat img(sz, CV_32FC1, Scalar(0.5, 0.1, 1));
  104. img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0));
  105. ASSERT_TRUE(cv::imwrite(filenameInput, img, params));
  106. #endif
  107. ASSERT_FALSE(img.empty());
  108. ASSERT_EQ(CV_32FC1,img.type());
  109. ASSERT_TRUE(cv::imwrite(filenameOutput, img, params));
  110. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  111. ASSERT_EQ(img2.type(), img.type());
  112. ASSERT_EQ(img2.size(), img.size());
  113. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  114. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  115. }
  116. TEST(Imgcodecs_EXR, readWrite_32FC3_half)
  117. {
  118. const string root = cvtest::TS::ptr()->get_data_path();
  119. const string filenameInput = root + "readwrite/test32FC3_half.exr";
  120. const string filenameOutput = cv::tempfile(".exr");
  121. std::vector<int> params;
  122. params.push_back(IMWRITE_EXR_TYPE);
  123. params.push_back(IMWRITE_EXR_TYPE_HALF);
  124. #ifndef GENERATE_DATA
  125. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  126. #else
  127. const Size sz(64, 32);
  128. Mat img(sz, CV_32FC3, Scalar(0.5, 0.1, 1));
  129. img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0));
  130. ASSERT_TRUE(cv::imwrite(filenameInput, img, params));
  131. #endif
  132. ASSERT_FALSE(img.empty());
  133. ASSERT_EQ(CV_32FC3, img.type());
  134. ASSERT_TRUE(cv::imwrite(filenameOutput, img, params));
  135. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  136. ASSERT_EQ(img2.type(), img.type());
  137. ASSERT_EQ(img2.size(), img.size());
  138. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  139. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  140. }
  141. TEST(Imgcodecs_EXR, readWrite_32FC1_PIZ)
  142. {
  143. const string root = cvtest::TS::ptr()->get_data_path();
  144. const string filenameInput = root + "readwrite/test32FC1.exr";
  145. const string filenameOutput = cv::tempfile(".exr");
  146. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  147. ASSERT_FALSE(img.empty());
  148. ASSERT_EQ(CV_32FC1, img.type());
  149. std::vector<int> params;
  150. params.push_back(IMWRITE_EXR_COMPRESSION);
  151. params.push_back(IMWRITE_EXR_COMPRESSION_PIZ);
  152. ASSERT_TRUE(cv::imwrite(filenameOutput, img, params));
  153. // Check generated file size to ensure that it's compressed with proper options
  154. ASSERT_EQ(849u, getFileSize(filenameOutput));
  155. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  156. ASSERT_EQ(img2.type(), img.type());
  157. ASSERT_EQ(img2.size(), img.size());
  158. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  159. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  160. }
  161. // Note: YC to GRAYSCALE (IMREAD_GRAYSCALE | IMREAD_ANYDEPTH)
  162. // outputs a black image,
  163. // as does Y to RGB (IMREAD_COLOR | IMREAD_ANYDEPTH).
  164. // This behavoir predates adding EXR alpha support issue
  165. // 16115.
  166. TEST(Imgcodecs_EXR, read_YA_ignore_alpha)
  167. {
  168. const string root = cvtest::TS::ptr()->get_data_path();
  169. const string filenameInput = root + "readwrite/test_YA.exr";
  170. const Mat img = cv::imread(filenameInput, IMREAD_GRAYSCALE | IMREAD_ANYDEPTH);
  171. ASSERT_FALSE(img.empty());
  172. ASSERT_EQ(CV_32FC1, img.type());
  173. // Writing Y covered by test 32FC1
  174. }
  175. TEST(Imgcodecs_EXR, read_YA_unchanged)
  176. {
  177. const string root = cvtest::TS::ptr()->get_data_path();
  178. const string filenameInput = root + "readwrite/test_YA.exr";
  179. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  180. ASSERT_FALSE(img.empty());
  181. ASSERT_EQ(CV_32FC2, img.type());
  182. // Cannot test writing, 2 channel writing not supported by loadsave
  183. }
  184. TEST(Imgcodecs_EXR, read_YC_changeDepth)
  185. {
  186. const string root = cvtest::TS::ptr()->get_data_path();
  187. const string filenameInput = root + "readwrite/test_YRYBY.exr";
  188. const Mat img = cv::imread(filenameInput, IMREAD_COLOR);
  189. ASSERT_FALSE(img.empty());
  190. ASSERT_EQ(CV_8UC3, img.type());
  191. const Mat img_rgb = cv::imread(filenameInput, IMREAD_COLOR_RGB);
  192. ASSERT_FALSE(img_rgb.empty());
  193. ASSERT_EQ(CV_8UC3, img_rgb.type());
  194. cvtColor(img_rgb, img_rgb, COLOR_RGB2BGR);
  195. // See https://github.com/opencv/opencv/issues/26705
  196. // If ALGO_HINT_ACCURATE is set, norm should be 0.
  197. // If ALGO_HINT_APPROX is set, norm should be 1(or 0).
  198. EXPECT_LE(cvtest::norm(img, img_rgb, NORM_INF),
  199. (cv::getDefaultAlgorithmHint() == ALGO_HINT_ACCURATE)?0:1);
  200. // Cannot test writing, EXR encoder doesn't support 8U depth
  201. }
  202. TEST(Imgcodecs_EXR, readwrite_YCA_ignore_alpha)
  203. {
  204. const string root = cvtest::TS::ptr()->get_data_path();
  205. const string filenameInput = root + "readwrite/test_YRYBYA.exr";
  206. const string filenameOutput = cv::tempfile(".exr");
  207. const Mat img = cv::imread(filenameInput, IMREAD_COLOR | IMREAD_ANYDEPTH);
  208. ASSERT_FALSE(img.empty());
  209. ASSERT_EQ(CV_32FC3, img.type());
  210. ASSERT_TRUE(cv::imwrite(filenameOutput, img));
  211. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  212. ASSERT_EQ(img2.type(), img.type());
  213. ASSERT_EQ(img2.size(), img.size());
  214. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  215. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  216. }
  217. TEST(Imgcodecs_EXR, read_YC_unchanged)
  218. {
  219. const string root = cvtest::TS::ptr()->get_data_path();
  220. const string filenameInput = root + "readwrite/test_YRYBY.exr";
  221. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  222. ASSERT_FALSE(img.empty());
  223. ASSERT_EQ(CV_32FC3, img.type());
  224. // Writing YC covered by test readwrite_YCA_ignore_alpha
  225. }
  226. TEST(Imgcodecs_EXR, readwrite_YCA_unchanged)
  227. {
  228. const string root = cvtest::TS::ptr()->get_data_path();
  229. const string filenameInput = root + "readwrite/test_YRYBYA.exr";
  230. const string filenameOutput = cv::tempfile(".exr");
  231. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  232. ASSERT_FALSE(img.empty());
  233. ASSERT_EQ(CV_32FC4, img.type());
  234. ASSERT_TRUE(cv::imwrite(filenameOutput, img));
  235. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  236. ASSERT_EQ(img2.type(), img.type());
  237. ASSERT_EQ(img2.size(), img.size());
  238. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  239. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  240. }
  241. TEST(Imgcodecs_EXR, readwrite_RGBA_togreyscale)
  242. {
  243. const string root = cvtest::TS::ptr()->get_data_path();
  244. const string filenameInput = root + "readwrite/test_GeneratedRGBA.exr";
  245. const string filenameOutput = cv::tempfile(".exr");
  246. const Mat img = cv::imread(filenameInput, IMREAD_GRAYSCALE | IMREAD_ANYDEPTH);
  247. ASSERT_FALSE(img.empty());
  248. ASSERT_EQ(CV_32FC1, img.type());
  249. ASSERT_TRUE(cv::imwrite(filenameOutput, img));
  250. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  251. ASSERT_EQ(img2.type(), img.type());
  252. ASSERT_EQ(img2.size(), img.size());
  253. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  254. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  255. }
  256. TEST(Imgcodecs_EXR, read_RGBA_ignore_alpha)
  257. {
  258. const string root = cvtest::TS::ptr()->get_data_path();
  259. const string filenameInput = root + "readwrite/test_GeneratedRGBA.exr";
  260. const Mat img = cv::imread(filenameInput, IMREAD_COLOR | IMREAD_ANYDEPTH);
  261. ASSERT_FALSE(img.empty());
  262. ASSERT_EQ(CV_32FC3, img.type());
  263. // Writing RGB covered by test 32FC3
  264. }
  265. TEST(Imgcodecs_EXR, read_RGBA_unchanged)
  266. {
  267. const string root = cvtest::TS::ptr()->get_data_path();
  268. const string filenameInput = root + "readwrite/test_GeneratedRGBA.exr";
  269. const string filenameOutput = cv::tempfile(".exr");
  270. #ifndef GENERATE_DATA
  271. const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
  272. #else
  273. const Size sz(64, 32);
  274. Mat img(sz, CV_32FC4, Scalar(0.5, 0.1, 1, 1));
  275. img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0, 1));
  276. img(Rect(10, 20, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 1, 0, 0));
  277. ASSERT_TRUE(cv::imwrite(filenameInput, img));
  278. #endif
  279. ASSERT_FALSE(img.empty());
  280. ASSERT_EQ(CV_32FC4, img.type());
  281. ASSERT_TRUE(cv::imwrite(filenameOutput, img));
  282. const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
  283. ASSERT_EQ(img2.type(), img.type());
  284. ASSERT_EQ(img2.size(), img.size());
  285. EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
  286. EXPECT_EQ(0, remove(filenameOutput.c_str()));
  287. }
  288. // See https://github.com/opencv/opencv/pull/26211
  289. // ( related with https://github.com/opencv/opencv/issues/26207 )
  290. TEST(Imgcodecs_EXR, imencode_regression_26207_extra)
  291. {
  292. // CV_8U is not supported depth for EXR Encoder.
  293. const cv::Mat src(100, 100, CV_8UC1, cv::Scalar::all(0));
  294. std::vector<uchar> buf;
  295. bool ret = false;
  296. EXPECT_ANY_THROW(ret = imencode(".exr", src, buf));
  297. EXPECT_FALSE(ret);
  298. }
  299. TEST(Imgcodecs_EXR, imwrite_regression_26207_extra)
  300. {
  301. // CV_8U is not supported depth for EXR Encoder.
  302. const cv::Mat src(100, 100, CV_8UC1, cv::Scalar::all(0));
  303. const string filename = cv::tempfile(".exr");
  304. bool ret = false;
  305. EXPECT_ANY_THROW(ret = imwrite(filename, src));
  306. EXPECT_FALSE(ret);
  307. remove(filename.c_str());
  308. }
  309. }} // namespace