test_read_write.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. #include "test_precomp.hpp"
  5. #include "test_common.hpp"
  6. namespace opencv_test { namespace {
  7. /* < <file_name, image_size>, <imread mode, scale> > */
  8. typedef tuple< tuple<string, Size>, tuple<ImreadModes, int> > Imgcodecs_Resize_t;
  9. typedef testing::TestWithParam< Imgcodecs_Resize_t > Imgcodecs_Resize;
  10. /* resize_flag_and_dims = <imread_flag, scale>*/
  11. const tuple <ImreadModes, int> resize_flag_and_dims[] =
  12. {
  13. make_tuple(IMREAD_UNCHANGED, 1),
  14. make_tuple(IMREAD_REDUCED_GRAYSCALE_2, 2),
  15. make_tuple(IMREAD_REDUCED_GRAYSCALE_4, 4),
  16. make_tuple(IMREAD_REDUCED_GRAYSCALE_8, 8),
  17. make_tuple(IMREAD_REDUCED_COLOR_2, 2),
  18. make_tuple(IMREAD_REDUCED_COLOR_4, 4),
  19. make_tuple(IMREAD_REDUCED_COLOR_8, 8)
  20. };
  21. const tuple<string, Size> images[] =
  22. {
  23. #ifdef HAVE_JPEG
  24. make_tuple<string, Size>("../cv/imgproc/stuff.jpg", Size(640, 480)),
  25. #endif
  26. #ifdef HAVE_PNG
  27. make_tuple<string, Size>("../cv/shared/pic1.png", Size(400, 300)),
  28. #endif
  29. make_tuple<string, Size>("../highgui/readwrite/ordinary.bmp", Size(480, 272)),
  30. };
  31. TEST_P(Imgcodecs_Resize, imread_reduce_flags)
  32. {
  33. const string file_name = findDataFile(get<0>(get<0>(GetParam())));
  34. const Size imageSize = get<1>(get<0>(GetParam()));
  35. const int imread_flag = get<0>(get<1>(GetParam()));
  36. const int scale = get<1>(get<1>(GetParam()));
  37. const int cols = imageSize.width / scale;
  38. const int rows = imageSize.height / scale;
  39. {
  40. Mat img = imread(file_name, imread_flag);
  41. ASSERT_FALSE(img.empty());
  42. EXPECT_EQ(cols, img.cols);
  43. EXPECT_EQ(rows, img.rows);
  44. }
  45. }
  46. //==================================================================================================
  47. TEST_P(Imgcodecs_Resize, imdecode_reduce_flags)
  48. {
  49. const string file_name = findDataFile(get<0>(get<0>(GetParam())));
  50. const Size imageSize = get<1>(get<0>(GetParam()));
  51. const int imread_flag = get<0>(get<1>(GetParam()));
  52. const int scale = get<1>(get<1>(GetParam()));
  53. const int cols = imageSize.width / scale;
  54. const int rows = imageSize.height / scale;
  55. const std::ios::openmode mode = std::ios::in | std::ios::binary;
  56. std::ifstream ifs(file_name.c_str(), mode);
  57. ASSERT_TRUE(ifs.is_open());
  58. ifs.seekg(0, std::ios::end);
  59. const size_t sz = static_cast<size_t>(ifs.tellg());
  60. ifs.seekg(0, std::ios::beg);
  61. std::vector<char> content(sz);
  62. ifs.read((char*)content.data(), sz);
  63. ASSERT_FALSE(ifs.fail());
  64. {
  65. Mat img = imdecode(Mat(content), imread_flag);
  66. ASSERT_FALSE(img.empty());
  67. EXPECT_EQ(cols, img.cols);
  68. EXPECT_EQ(rows, img.rows);
  69. }
  70. }
  71. //==================================================================================================
  72. INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Resize,
  73. testing::Combine(
  74. testing::ValuesIn(images),
  75. testing::ValuesIn(resize_flag_and_dims)
  76. )
  77. );
  78. //==================================================================================================
  79. TEST(Imgcodecs_Image, read_write_bmp)
  80. {
  81. const size_t IMAGE_COUNT = 10;
  82. const double thresDbell = 32;
  83. for (size_t i = 0; i < IMAGE_COUNT; ++i)
  84. {
  85. stringstream s; s << i;
  86. const string digit = s.str();
  87. const string src_name = TS::ptr()->get_data_path() + "../python/images/QCIF_0" + digit + ".bmp";
  88. const string dst_name = cv::tempfile((digit + ".bmp").c_str());
  89. Mat image = imread(src_name);
  90. ASSERT_FALSE(image.empty());
  91. resize(image, image, Size(968, 757), 0.0, 0.0, INTER_CUBIC);
  92. imwrite(dst_name, image);
  93. Mat loaded = imread(dst_name);
  94. ASSERT_FALSE(loaded.empty());
  95. double psnr = cvtest::PSNR(loaded, image);
  96. EXPECT_GT(psnr, thresDbell);
  97. vector<uchar> from_file;
  98. FILE *f = fopen(dst_name.c_str(), "rb");
  99. fseek(f, 0, SEEK_END);
  100. long len = ftell(f);
  101. from_file.resize((size_t)len);
  102. fseek(f, 0, SEEK_SET);
  103. from_file.resize(fread(&from_file[0], 1, from_file.size(), f));
  104. fclose(f);
  105. vector<uchar> buf;
  106. imencode(".bmp", image, buf);
  107. ASSERT_EQ(buf, from_file);
  108. Mat buf_loaded = imdecode(Mat(buf), 1);
  109. ASSERT_FALSE(buf_loaded.empty());
  110. psnr = cvtest::PSNR(buf_loaded, image);
  111. EXPECT_GT(psnr, thresDbell);
  112. EXPECT_EQ(0, remove(dst_name.c_str()));
  113. }
  114. }
  115. //==================================================================================================
  116. typedef string Ext;
  117. typedef testing::TestWithParam<Ext> Imgcodecs_Image;
  118. const string exts[] = {
  119. #ifdef HAVE_PNG
  120. "png",
  121. #endif
  122. #ifdef HAVE_TIFF
  123. "tiff",
  124. #endif
  125. #ifdef HAVE_JPEG
  126. "jpg",
  127. #endif
  128. #if (defined(HAVE_JASPER) && defined(OPENCV_IMGCODECS_ENABLE_JASPER_TESTS)) \
  129. || defined(HAVE_OPENJPEG)
  130. "jp2",
  131. #endif
  132. #if 0 /*defined HAVE_OPENEXR && !defined __APPLE__*/
  133. "exr",
  134. #endif
  135. "bmp",
  136. #ifdef HAVE_IMGCODEC_PXM
  137. "ppm",
  138. #endif
  139. #ifdef HAVE_IMGCODEC_SUNRASTER
  140. "ras",
  141. #endif
  142. };
  143. static
  144. void test_image_io(const Mat& image, const std::string& fname, const std::string& ext, int imreadFlag, double psnrThreshold)
  145. {
  146. vector<uchar> buf;
  147. ASSERT_NO_THROW(imencode("." + ext, image, buf));
  148. ASSERT_NO_THROW(imwrite(fname, image));
  149. FILE *f = fopen(fname.c_str(), "rb");
  150. fseek(f, 0, SEEK_END);
  151. long len = ftell(f);
  152. cout << "File size: " << len << " bytes" << endl;
  153. EXPECT_GT(len, 1024) << "File is small. Test or implementation is broken";
  154. fseek(f, 0, SEEK_SET);
  155. vector<uchar> file_buf((size_t)len);
  156. EXPECT_EQ(len, (long)fread(&file_buf[0], 1, (size_t)len, f));
  157. fclose(f); f = NULL;
  158. EXPECT_EQ(buf, file_buf) << "imwrite() / imencode() calls must provide the same output (bit-exact)";
  159. Mat buf_loaded = imdecode(Mat(buf), imreadFlag);
  160. EXPECT_FALSE(buf_loaded.empty());
  161. Mat loaded = imread(fname, imreadFlag);
  162. EXPECT_FALSE(loaded.empty());
  163. EXPECT_EQ(0, cv::norm(loaded, buf_loaded, NORM_INF)) << "imread() and imdecode() calls must provide the same result (bit-exact)";
  164. double psnr = cvtest::PSNR(loaded, image);
  165. EXPECT_GT(psnr, psnrThreshold);
  166. // not necessary due bitexact check above
  167. //double buf_psnr = cvtest::PSNR(buf_loaded, image);
  168. //EXPECT_GT(buf_psnr, psnrThreshold);
  169. #if 0 // debug
  170. if (psnr <= psnrThreshold /*|| buf_psnr <= thresDbell*/)
  171. {
  172. cout << "File: " << fname << endl;
  173. imshow("origin", image);
  174. imshow("imread", loaded);
  175. imshow("imdecode", buf_loaded);
  176. waitKey();
  177. }
  178. #endif
  179. }
  180. TEST_P(Imgcodecs_Image, read_write_BGR)
  181. {
  182. const string ext = this->GetParam();
  183. const string fname = cv::tempfile(ext.c_str());
  184. double psnrThreshold = 100;
  185. if (ext == "jpg")
  186. psnrThreshold = 32;
  187. #if defined(HAVE_JASPER)
  188. if (ext == "jp2")
  189. psnrThreshold = 95;
  190. #elif defined(HAVE_OPENJPEG)
  191. if (ext == "jp2")
  192. psnrThreshold = 35;
  193. #endif
  194. Mat image = generateTestImageBGR();
  195. EXPECT_NO_THROW(test_image_io(image, fname, ext, IMREAD_COLOR, psnrThreshold));
  196. EXPECT_EQ(0, remove(fname.c_str()));
  197. }
  198. TEST_P(Imgcodecs_Image, read_write_GRAYSCALE)
  199. {
  200. const string ext = this->GetParam();
  201. if (false
  202. || ext == "ppm" // grayscale is not implemented
  203. || ext == "ras" // broken (black result)
  204. )
  205. throw SkipTestException("GRAYSCALE mode is not supported");
  206. const string fname = cv::tempfile(ext.c_str());
  207. double psnrThreshold = 100;
  208. if (ext == "jpg")
  209. psnrThreshold = 40;
  210. #if defined(HAVE_JASPER)
  211. if (ext == "jp2")
  212. psnrThreshold = 70;
  213. #elif defined(HAVE_OPENJPEG)
  214. if (ext == "jp2")
  215. psnrThreshold = 35;
  216. #endif
  217. Mat image = generateTestImageGrayscale();
  218. EXPECT_NO_THROW(test_image_io(image, fname, ext, IMREAD_GRAYSCALE, psnrThreshold));
  219. EXPECT_EQ(0, remove(fname.c_str()));
  220. }
  221. INSTANTIATE_TEST_CASE_P(imgcodecs, Imgcodecs_Image, testing::ValuesIn(exts));
  222. TEST(Imgcodecs_Image, regression_9376)
  223. {
  224. String path = findDataFile("readwrite/regression_9376.bmp");
  225. Mat m = imread(path);
  226. ASSERT_FALSE(m.empty());
  227. EXPECT_EQ(32, m.cols);
  228. EXPECT_EQ(32, m.rows);
  229. }
  230. //==================================================================================================
  231. TEST(Imgcodecs_Image, write_umat)
  232. {
  233. const string src_name = TS::ptr()->get_data_path() + "../python/images/baboon.bmp";
  234. const string dst_name = cv::tempfile(".bmp");
  235. Mat image1 = imread(src_name);
  236. ASSERT_FALSE(image1.empty());
  237. UMat image1_umat = image1.getUMat(ACCESS_RW);
  238. imwrite(dst_name, image1_umat);
  239. Mat image2 = imread(dst_name);
  240. ASSERT_FALSE(image2.empty());
  241. EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), image1, image2);
  242. EXPECT_EQ(0, remove(dst_name.c_str()));
  243. }
  244. }} // namespace