Skip to content

Commit 67dfdee

Browse files
committed
Merge pull request opencv#16922 from alalek:imgcodecs_test_io_grayscale
2 parents 222a485 + 6d85fa3 commit 67dfdee

File tree

3 files changed

+151
-39
lines changed

3 files changed

+151
-39
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
7+
namespace opencv_test {
8+
9+
static
10+
Mat generateTestImageBGR_()
11+
{
12+
Size sz(640, 480);
13+
Mat result(sz, CV_8UC3, Scalar::all(0));
14+
15+
const string fname = cvtest::findDataFile("../cv/shared/baboon.png");
16+
Mat image = imread(fname, IMREAD_COLOR);
17+
CV_Assert(!image.empty());
18+
CV_CheckEQ(image.size(), Size(512, 512), "");
19+
Rect roi((640-512) / 2, 0, 512, 480);
20+
image(Rect(0, 0, 512, 480)).copyTo(result(roi));
21+
result(Rect(0, 0, 5, 5)).setTo(Scalar(0, 0, 255)); // R
22+
result(Rect(5, 0, 5, 5)).setTo(Scalar(0, 255, 0)); // G
23+
result(Rect(10, 0, 5, 5)).setTo(Scalar(255, 0, 0)); // B
24+
result(Rect(0, 5, 5, 5)).setTo(Scalar(128, 128, 128)); // gray
25+
//imshow("test_image", result); waitKey();
26+
return result;
27+
}
28+
Mat generateTestImageBGR()
29+
{
30+
static Mat image = generateTestImageBGR_(); // initialize once
31+
CV_Assert(!image.empty());
32+
return image;
33+
}
34+
35+
static
36+
Mat generateTestImageGrayscale_()
37+
{
38+
Mat imageBGR = generateTestImageBGR();
39+
CV_Assert(!imageBGR.empty());
40+
41+
Mat result;
42+
cvtColor(imageBGR, result, COLOR_BGR2GRAY);
43+
return result;
44+
}
45+
Mat generateTestImageGrayscale()
46+
{
47+
static Mat image = generateTestImageGrayscale_(); // initialize once
48+
return image;
49+
}
50+
51+
} // namespace
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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+
5+
#ifndef OPENCV_TEST_IMGCODECS_COMMON_HPP
6+
#define OPENCV_TEST_IMGCODECS_COMMON_HPP
7+
8+
namespace opencv_test {
9+
10+
Mat generateTestImageBGR();
11+
Mat generateTestImageGrayscale();
12+
13+
} // namespace
14+
15+
#endif // OPENCV_TEST_IMGCODECS_COMMON_HPP

modules/imgcodecs/test/test_read_write.cpp

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// It is subject to the license terms in the LICENSE file found in the top-level directory
33
// of this distribution and at http://opencv.org/license.html
44
#include "test_precomp.hpp"
5+
#include "test_common.hpp"
56

67
namespace opencv_test { namespace {
78

@@ -145,45 +146,6 @@ TEST(Imgcodecs_Image, read_write_bmp)
145146
typedef string Ext;
146147
typedef testing::TestWithParam<Ext> Imgcodecs_Image;
147148

148-
TEST_P(Imgcodecs_Image, read_write)
149-
{
150-
const string ext = this->GetParam();
151-
const string full_name = cv::tempfile(ext.c_str());
152-
const string _name = TS::ptr()->get_data_path() + "../cv/shared/baboon.png";
153-
const double thresDbell = 32;
154-
155-
Mat image = imread(_name);
156-
image.convertTo(image, CV_8UC3);
157-
ASSERT_FALSE(image.empty());
158-
159-
imwrite(full_name, image);
160-
Mat loaded = imread(full_name);
161-
ASSERT_FALSE(loaded.empty());
162-
163-
double psnr = cvtest::PSNR(loaded, image);
164-
EXPECT_GT(psnr, thresDbell);
165-
166-
vector<uchar> from_file;
167-
FILE *f = fopen(full_name.c_str(), "rb");
168-
fseek(f, 0, SEEK_END);
169-
long len = ftell(f);
170-
from_file.resize((size_t)len);
171-
fseek(f, 0, SEEK_SET);
172-
from_file.resize(fread(&from_file[0], 1, from_file.size(), f));
173-
fclose(f);
174-
vector<uchar> buf;
175-
imencode("." + ext, image, buf);
176-
ASSERT_EQ(buf, from_file);
177-
178-
Mat buf_loaded = imdecode(Mat(buf), 1);
179-
ASSERT_FALSE(buf_loaded.empty());
180-
181-
psnr = cvtest::PSNR(buf_loaded, image);
182-
EXPECT_GT(psnr, thresDbell);
183-
184-
EXPECT_EQ(0, remove(full_name.c_str()));
185-
}
186-
187149
const string exts[] = {
188150
#ifdef HAVE_PNG
189151
"png",
@@ -209,6 +171,90 @@ const string exts[] = {
209171
#endif
210172
};
211173

174+
static
175+
void test_image_io(const Mat& image, const std::string& fname, const std::string& ext, int imreadFlag, double psnrThreshold)
176+
{
177+
vector<uchar> buf;
178+
ASSERT_NO_THROW(imencode("." + ext, image, buf));
179+
180+
ASSERT_NO_THROW(imwrite(fname, image));
181+
182+
FILE *f = fopen(fname.c_str(), "rb");
183+
fseek(f, 0, SEEK_END);
184+
long len = ftell(f);
185+
cout << "File size: " << len << " bytes" << endl;
186+
EXPECT_GT(len, 1024) << "File is small. Test or implementation is broken";
187+
fseek(f, 0, SEEK_SET);
188+
vector<uchar> file_buf((size_t)len);
189+
EXPECT_EQ(len, (long)fread(&file_buf[0], 1, (size_t)len, f));
190+
fclose(f); f = NULL;
191+
192+
EXPECT_EQ(buf, file_buf) << "imwrite() / imencode() calls must provide the same output (bit-exact)";
193+
194+
Mat buf_loaded = imdecode(Mat(buf), imreadFlag);
195+
EXPECT_FALSE(buf_loaded.empty());
196+
197+
Mat loaded = imread(fname, imreadFlag);
198+
EXPECT_FALSE(loaded.empty());
199+
200+
EXPECT_EQ(0, cv::norm(loaded, buf_loaded, NORM_INF)) << "imread() and imdecode() calls must provide the same result (bit-exact)";
201+
202+
double psnr = cvtest::PSNR(loaded, image);
203+
EXPECT_GT(psnr, psnrThreshold);
204+
205+
// not necessary due bitexact check above
206+
//double buf_psnr = cvtest::PSNR(buf_loaded, image);
207+
//EXPECT_GT(buf_psnr, psnrThreshold);
208+
209+
#if 0 // debug
210+
if (psnr <= psnrThreshold /*|| buf_psnr <= thresDbell*/)
211+
{
212+
cout << "File: " << fname << endl;
213+
imshow("origin", image);
214+
imshow("imread", loaded);
215+
imshow("imdecode", buf_loaded);
216+
waitKey();
217+
}
218+
#endif
219+
}
220+
221+
TEST_P(Imgcodecs_Image, read_write_BGR)
222+
{
223+
const string ext = this->GetParam();
224+
const string fname = cv::tempfile(ext.c_str());
225+
226+
double psnrThreshold = 100;
227+
if (ext == "jpg")
228+
psnrThreshold = 32;
229+
230+
Mat image = generateTestImageBGR();
231+
EXPECT_NO_THROW(test_image_io(image, fname, ext, IMREAD_COLOR, psnrThreshold));
232+
233+
EXPECT_EQ(0, remove(fname.c_str()));
234+
}
235+
236+
TEST_P(Imgcodecs_Image, read_write_GRAYSCALE)
237+
{
238+
const string ext = this->GetParam();
239+
240+
if (false
241+
|| ext == "ppm" // grayscale is not implemented
242+
|| ext == "ras" // broken (black result)
243+
)
244+
throw SkipTestException("GRAYSCALE mode is not supported");
245+
246+
const string fname = cv::tempfile(ext.c_str());
247+
248+
double psnrThreshold = 100;
249+
if (ext == "jpg")
250+
psnrThreshold = 40;
251+
252+
Mat image = generateTestImageGrayscale();
253+
EXPECT_NO_THROW(test_image_io(image, fname, ext, IMREAD_GRAYSCALE, psnrThreshold));
254+
255+
EXPECT_EQ(0, remove(fname.c_str()));
256+
}
257+
212258
INSTANTIATE_TEST_CASE_P(imgcodecs, Imgcodecs_Image, testing::ValuesIn(exts));
213259

214260
TEST(Imgcodecs_Image, regression_9376)

0 commit comments

Comments
 (0)