Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgcodecs/test/test_tiff.cpp
16354 views
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
6
namespace opencv_test { namespace {
7
8
#ifdef HAVE_TIFF
9
10
// these defines are used to resolve conflict between tiff.h and opencv2/core/types_c.h
11
#define uint64 uint64_hack_
12
#define int64 int64_hack_
13
#include "tiff.h"
14
15
#ifdef __ANDROID__
16
// Test disabled as it uses a lot of memory.
17
// It is killed with SIGKILL by out of memory killer.
18
TEST(Imgcodecs_Tiff, DISABLED_decode_tile16384x16384)
19
#else
20
TEST(Imgcodecs_Tiff, decode_tile16384x16384)
21
#endif
22
{
23
// see issue #2161
24
cv::Mat big(16384, 16384, CV_8UC1, cv::Scalar::all(0));
25
string file3 = cv::tempfile(".tiff");
26
string file4 = cv::tempfile(".tiff");
27
28
std::vector<int> params;
29
params.push_back(TIFFTAG_ROWSPERSTRIP);
30
params.push_back(big.rows);
31
EXPECT_NO_THROW(cv::imwrite(file4, big, params));
32
EXPECT_NO_THROW(cv::imwrite(file3, big.colRange(0, big.cols - 1), params));
33
big.release();
34
35
try
36
{
37
cv::imread(file3, IMREAD_UNCHANGED);
38
EXPECT_NO_THROW(cv::imread(file4, IMREAD_UNCHANGED));
39
}
40
catch(const std::bad_alloc&)
41
{
42
// not enough memory
43
}
44
45
EXPECT_EQ(0, remove(file3.c_str()));
46
EXPECT_EQ(0, remove(file4.c_str()));
47
}
48
49
TEST(Imgcodecs_Tiff, write_read_16bit_big_little_endian)
50
{
51
// see issue #2601 "16-bit Grayscale TIFF Load Failures Due to Buffer Underflow and Endianness"
52
53
// Setup data for two minimal 16-bit grayscale TIFF files in both endian formats
54
uchar tiff_sample_data[2][86] = { {
55
// Little endian
56
0x49, 0x49, 0x2a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xad, 0xde, 0xef, 0xbe, 0x06, 0x00, 0x00, 0x01,
57
0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x00,
58
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
59
0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01,
60
0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x01, 0x04, 0x00, 0x01, 0x00,
61
0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }, {
62
// Big endian
63
0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x0c, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x06, 0x01, 0x00,
64
0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x00,
65
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10,
66
0x00, 0x00, 0x01, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x11,
67
0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x01, 0x17, 0x00, 0x04, 0x00, 0x00,
68
0x00, 0x01, 0x00, 0x00, 0x00, 0x04 }
69
};
70
71
// Test imread() for both a little endian TIFF and big endian TIFF
72
for (int i = 0; i < 2; i++)
73
{
74
string filename = cv::tempfile(".tiff");
75
76
// Write sample TIFF file
77
FILE* fp = fopen(filename.c_str(), "wb");
78
ASSERT_TRUE(fp != NULL);
79
ASSERT_EQ((size_t)1, fwrite(tiff_sample_data, 86, 1, fp));
80
fclose(fp);
81
82
Mat img = imread(filename, IMREAD_UNCHANGED);
83
84
EXPECT_EQ(1, img.rows);
85
EXPECT_EQ(2, img.cols);
86
EXPECT_EQ(CV_16U, img.type());
87
EXPECT_EQ(sizeof(ushort), img.elemSize());
88
EXPECT_EQ(1, img.channels());
89
EXPECT_EQ(0xDEAD, img.at<ushort>(0,0));
90
EXPECT_EQ(0xBEEF, img.at<ushort>(0,1));
91
92
EXPECT_EQ(0, remove(filename.c_str()));
93
}
94
}
95
96
TEST(Imgcodecs_Tiff, decode_tile_remainder)
97
{
98
/* see issue #3472 - dealing with tiled images where the tile size is
99
* not a multiple of image size.
100
* The tiled images were created with 'convert' from ImageMagick,
101
* using the command 'convert <input> -define tiff:tile-geometry=128x128 -depth [8|16] <output>
102
* Note that the conversion to 16 bits expands the range from 0-255 to 0-255*255,
103
* so the test converts back but rounding errors cause small differences.
104
*/
105
const string root = cvtest::TS::ptr()->get_data_path();
106
cv::Mat img = imread(root + "readwrite/non_tiled.tif",-1);
107
ASSERT_FALSE(img.empty());
108
ASSERT_TRUE(img.channels() == 3);
109
cv::Mat tiled8 = imread(root + "readwrite/tiled_8.tif", -1);
110
ASSERT_FALSE(tiled8.empty());
111
ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, tiled8);
112
cv::Mat tiled16 = imread(root + "readwrite/tiled_16.tif", -1);
113
ASSERT_FALSE(tiled16.empty());
114
ASSERT_TRUE(tiled16.elemSize() == 6);
115
tiled16.convertTo(tiled8, CV_8UC3, 1./256.);
116
ASSERT_PRED_FORMAT2(cvtest::MatComparator(2, 0), img, tiled8);
117
// What about 32, 64 bit?
118
}
119
120
TEST(Imgcodecs_Tiff, decode_infinite_rowsperstrip)
121
{
122
const uchar sample_data[142] = {
123
0x49, 0x49, 0x2a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x56, 0x54,
124
0x56, 0x5a, 0x59, 0x55, 0x5a, 0x00, 0x0a, 0x00, 0x00, 0x01,
125
0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
126
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00,
127
0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
128
0x08, 0x00, 0x00, 0x00, 0x03, 0x01, 0x03, 0x00, 0x01, 0x00,
129
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00,
130
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01,
131
0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
132
0x15, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
133
0x00, 0x00, 0x16, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
134
0xff, 0xff, 0xff, 0xff, 0x17, 0x01, 0x04, 0x00, 0x01, 0x00,
135
0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x03, 0x00,
136
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
137
0x00, 0x00
138
};
139
140
const string filename = cv::tempfile(".tiff");
141
std::ofstream outfile(filename.c_str(), std::ofstream::binary);
142
outfile.write(reinterpret_cast<const char *>(sample_data), sizeof sample_data);
143
outfile.close();
144
145
EXPECT_NO_THROW(cv::imread(filename, IMREAD_UNCHANGED));
146
147
EXPECT_EQ(0, remove(filename.c_str()));
148
}
149
150
TEST(Imgcodecs_Tiff, readWrite_32FC1)
151
{
152
const string root = cvtest::TS::ptr()->get_data_path();
153
const string filenameInput = root + "readwrite/test32FC1.tiff";
154
const string filenameOutput = cv::tempfile(".tiff");
155
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
156
ASSERT_FALSE(img.empty());
157
ASSERT_EQ(CV_32FC1,img.type());
158
159
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
160
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
161
ASSERT_EQ(img2.type(),img.type());
162
ASSERT_EQ(img2.size(),img.size());
163
EXPECT_GE(1e-3, cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE));
164
EXPECT_EQ(0, remove(filenameOutput.c_str()));
165
}
166
167
//==================================================================================================
168
169
typedef testing::TestWithParam<int> Imgcodecs_Tiff_Modes;
170
171
TEST_P(Imgcodecs_Tiff_Modes, decode_multipage)
172
{
173
const int mode = GetParam();
174
const string root = cvtest::TS::ptr()->get_data_path();
175
const string filename = root + "readwrite/multipage.tif";
176
const string page_files[] = {
177
"readwrite/multipage_p1.tif",
178
"readwrite/multipage_p2.tif",
179
"readwrite/multipage_p3.tif",
180
"readwrite/multipage_p4.tif",
181
"readwrite/multipage_p5.tif",
182
"readwrite/multipage_p6.tif"
183
};
184
const size_t page_count = sizeof(page_files)/sizeof(page_files[0]);
185
vector<Mat> pages;
186
bool res = imreadmulti(filename, pages, mode);
187
ASSERT_TRUE(res == true);
188
ASSERT_EQ(page_count, pages.size());
189
for (size_t i = 0; i < page_count; i++)
190
{
191
const Mat page = imread(root + page_files[i], mode);
192
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), page, pages[i]);
193
}
194
}
195
196
const int all_modes[] =
197
{
198
IMREAD_UNCHANGED,
199
IMREAD_GRAYSCALE,
200
IMREAD_COLOR,
201
IMREAD_ANYDEPTH,
202
IMREAD_ANYCOLOR
203
};
204
205
INSTANTIATE_TEST_CASE_P(AllModes, Imgcodecs_Tiff_Modes, testing::ValuesIn(all_modes));
206
207
//==================================================================================================
208
209
TEST(Imgcodecs_Tiff_Modes, write_multipage)
210
{
211
const string root = cvtest::TS::ptr()->get_data_path();
212
const string filename = root + "readwrite/multipage.tif";
213
const string page_files[] = {
214
"readwrite/multipage_p1.tif",
215
"readwrite/multipage_p2.tif",
216
"readwrite/multipage_p3.tif",
217
"readwrite/multipage_p4.tif",
218
"readwrite/multipage_p5.tif",
219
"readwrite/multipage_p6.tif"
220
};
221
const size_t page_count = sizeof(page_files) / sizeof(page_files[0]);
222
vector<Mat> pages;
223
for (size_t i = 0; i < page_count; i++)
224
{
225
const Mat page = imread(root + page_files[i]);
226
pages.push_back(page);
227
}
228
229
string tmp_filename = cv::tempfile(".tiff");
230
bool res = imwrite(tmp_filename, pages);
231
ASSERT_TRUE(res);
232
233
vector<Mat> read_pages;
234
imreadmulti(tmp_filename, read_pages);
235
for (size_t i = 0; i < page_count; i++)
236
{
237
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), read_pages[i], pages[i]);
238
}
239
}
240
241
//==================================================================================================
242
243
TEST(Imgcodecs_Tiff, imdecode_no_exception_temporary_file_removed)
244
{
245
const string root = cvtest::TS::ptr()->get_data_path();
246
const string filename = root + "../cv/shared/lena.png";
247
cv::Mat img = cv::imread(filename);
248
ASSERT_FALSE(img.empty());
249
std::vector<uchar> buf;
250
EXPECT_NO_THROW(cv::imencode(".tiff", img, buf));
251
EXPECT_NO_THROW(cv::imdecode(buf, IMREAD_UNCHANGED));
252
}
253
254
#endif
255
256
}} // namespace
257
258