1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
8 //
9 //
10 // License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
22 //
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
26 //
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #include "test_precomp.hpp"
44
45 #include <fstream>
46
47 using namespace cv;
48 using namespace std;
49
50 static
mats_equal(const Mat & lhs,const Mat & rhs)51 bool mats_equal(const Mat& lhs, const Mat& rhs)
52 {
53 if (lhs.channels() != rhs.channels() ||
54 lhs.depth() != rhs.depth() ||
55 lhs.size().height != rhs.size().height ||
56 lhs.size().width != rhs.size().width)
57 {
58 return false;
59 }
60
61 Mat diff = (lhs != rhs);
62 const Scalar s = sum(diff);
63 for (int i = 0; i < s.channels; ++i)
64 {
65 if (s[i] != 0)
66 {
67 return false;
68 }
69 }
70
71 return true;
72 }
73
74 static
imread_compare(const string & filepath,int flags=IMREAD_COLOR)75 bool imread_compare(const string& filepath, int flags = IMREAD_COLOR)
76 {
77 vector<Mat> pages;
78 if (!imreadmulti(filepath, pages, flags) ||
79 pages.empty())
80 {
81 return false;
82 }
83
84 const Mat single = imread(filepath, flags);
85 return mats_equal(single, pages[0]);
86 }
87
TEST(Imgcodecs_imread,regression)88 TEST(Imgcodecs_imread, regression)
89 {
90 const char* const filenames[] =
91 {
92 #ifdef HAVE_JASPER
93 "Rome.jp2",
94 #endif
95 "color_palette_alpha.png",
96 "multipage.tif",
97 "rle.hdr",
98 "ordinary.bmp",
99 "rle8.bmp",
100 "test_1_c1.jpg"
101 };
102
103 const string folder = string(cvtest::TS::ptr()->get_data_path()) + "/readwrite/";
104
105 for (size_t i = 0; i < sizeof(filenames) / sizeof(filenames[0]); ++i)
106 {
107 const string path = folder + string(filenames[i]);
108 ASSERT_TRUE(imread_compare(path, IMREAD_UNCHANGED));
109 ASSERT_TRUE(imread_compare(path, IMREAD_GRAYSCALE));
110 ASSERT_TRUE(imread_compare(path, IMREAD_COLOR));
111 ASSERT_TRUE(imread_compare(path, IMREAD_ANYDEPTH));
112 ASSERT_TRUE(imread_compare(path, IMREAD_ANYCOLOR));
113 if (path.substr(path.length() - 3) != "hdr")
114 {
115 // GDAL does not support hdr
116 ASSERT_TRUE(imread_compare(path, IMREAD_LOAD_GDAL));
117 }
118 }
119 }
120
121 #ifdef HAVE_JASPER
TEST(Imgcodecs_jasper,regression)122 TEST(Imgcodecs_jasper, regression)
123 {
124 const string folder = string(cvtest::TS::ptr()->get_data_path()) + "/readwrite/";
125
126 ASSERT_TRUE(imread_compare(folder + "Bretagne2.jp2", IMREAD_COLOR));
127 ASSERT_TRUE(imread_compare(folder + "Bretagne2.jp2", IMREAD_GRAYSCALE));
128 ASSERT_TRUE(imread_compare(folder + "Grey.jp2", IMREAD_COLOR));
129 ASSERT_TRUE(imread_compare(folder + "Grey.jp2", IMREAD_GRAYSCALE));
130 }
131 #endif
132
133 class CV_GrfmtWriteBigImageTest : public cvtest::BaseTest
134 {
135 public:
run(int)136 void run(int)
137 {
138 try
139 {
140 ts->printf(cvtest::TS::LOG, "start reading big image\n");
141 Mat img = imread(string(ts->get_data_path()) + "readwrite/read.png");
142 ts->printf(cvtest::TS::LOG, "finish reading big image\n");
143 if (img.empty()) ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
144 ts->printf(cvtest::TS::LOG, "start writing big image\n");
145 imwrite(cv::tempfile(".png"), img);
146 ts->printf(cvtest::TS::LOG, "finish writing big image\n");
147 }
148 catch(...)
149 {
150 ts->set_failed_test_info(cvtest::TS::FAIL_EXCEPTION);
151 }
152 ts->set_failed_test_info(cvtest::TS::OK);
153 }
154 };
155
ext_from_int(int ext)156 string ext_from_int(int ext)
157 {
158 #ifdef HAVE_PNG
159 if (ext == 0) return ".png";
160 #endif
161 if (ext == 1) return ".bmp";
162 if (ext == 2) return ".pgm";
163 #ifdef HAVE_TIFF
164 if (ext == 3) return ".tiff";
165 #endif
166 return "";
167 }
168
169 class CV_GrfmtWriteSequenceImageTest : public cvtest::BaseTest
170 {
171 public:
run(int)172 void run(int)
173 {
174 try
175 {
176 const int img_r = 640;
177 const int img_c = 480;
178
179 for (int k = 1; k <= 5; ++k)
180 {
181 for (int ext = 0; ext < 4; ++ext) // 0 - png, 1 - bmp, 2 - pgm, 3 - tiff
182 {
183 if(ext_from_int(ext).empty())
184 continue;
185 for (int num_channels = 1; num_channels <= 4; num_channels++)
186 {
187 if (num_channels == 2) continue;
188 if (num_channels == 4 && ext!=3 /*TIFF*/) continue;
189
190 ts->printf(ts->LOG, "image type depth:%d channels:%d ext: %s\n", CV_8U, num_channels, ext_from_int(ext).c_str());
191 Mat img(img_r * k, img_c * k, CV_MAKETYPE(CV_8U, num_channels), Scalar::all(0));
192 circle(img, Point2i((img_c * k) / 2, (img_r * k) / 2), std::min((img_r * k), (img_c * k)) / 4 , Scalar::all(255));
193
194 string img_path = cv::tempfile(ext_from_int(ext).c_str());
195 ts->printf(ts->LOG, "writing image : %s\n", img_path.c_str());
196 imwrite(img_path, img);
197
198 ts->printf(ts->LOG, "reading test image : %s\n", img_path.c_str());
199 Mat img_test = imread(img_path, IMREAD_UNCHANGED);
200
201 if (img_test.empty()) ts->set_failed_test_info(ts->FAIL_MISMATCH);
202
203 CV_Assert(img.size() == img_test.size());
204 CV_Assert(img.type() == img_test.type());
205 CV_Assert(num_channels == img_test.channels());
206
207 double n = cvtest::norm(img, img_test, NORM_L2);
208 if ( n > 1.0)
209 {
210 ts->printf(ts->LOG, "norm = %f \n", n);
211 ts->set_failed_test_info(ts->FAIL_MISMATCH);
212 }
213 }
214 }
215
216 #ifdef HAVE_JPEG
217 for (int num_channels = 1; num_channels <= 3; num_channels+=2)
218 {
219 // jpeg
220 ts->printf(ts->LOG, "image type depth:%d channels:%d ext: %s\n", CV_8U, num_channels, ".jpg");
221 Mat img(img_r * k, img_c * k, CV_MAKETYPE(CV_8U, num_channels), Scalar::all(0));
222 circle(img, Point2i((img_c * k) / 2, (img_r * k) / 2), std::min((img_r * k), (img_c * k)) / 4 , Scalar::all(255));
223
224 string filename = cv::tempfile(".jpg");
225 imwrite(filename, img);
226 ts->printf(ts->LOG, "reading test image : %s\n", filename.c_str());
227 Mat img_test = imread(filename, IMREAD_UNCHANGED);
228
229 if (img_test.empty()) ts->set_failed_test_info(ts->FAIL_MISMATCH);
230
231 CV_Assert(img.size() == img_test.size());
232 CV_Assert(img.type() == img_test.type());
233
234 // JPEG format does not provide 100% accuracy
235 // using fuzzy image comparison
236 double n = cvtest::norm(img, img_test, NORM_L1);
237 double expected = 0.05 * img.size().area();
238 if ( n > expected)
239 {
240 ts->printf(ts->LOG, "norm = %f > expected = %f \n", n, expected);
241 ts->set_failed_test_info(ts->FAIL_MISMATCH);
242 }
243 }
244 #endif
245
246 #ifdef HAVE_TIFF
247 for (int num_channels = 1; num_channels <= 4; num_channels++)
248 {
249 if (num_channels == 2) continue;
250 // tiff
251 ts->printf(ts->LOG, "image type depth:%d channels:%d ext: %s\n", CV_16U, num_channels, ".tiff");
252 Mat img(img_r * k, img_c * k, CV_MAKETYPE(CV_16U, num_channels), Scalar::all(0));
253 circle(img, Point2i((img_c * k) / 2, (img_r * k) / 2), std::min((img_r * k), (img_c * k)) / 4 , Scalar::all(255));
254
255 string filename = cv::tempfile(".tiff");
256 imwrite(filename, img);
257 ts->printf(ts->LOG, "reading test image : %s\n", filename.c_str());
258 Mat img_test = imread(filename, IMREAD_UNCHANGED);
259
260 if (img_test.empty()) ts->set_failed_test_info(ts->FAIL_MISMATCH);
261
262 CV_Assert(img.size() == img_test.size());
263
264 ts->printf(ts->LOG, "img : %d ; %d \n", img.channels(), img.depth());
265 ts->printf(ts->LOG, "img_test : %d ; %d \n", img_test.channels(), img_test.depth());
266
267 CV_Assert(img.type() == img_test.type());
268
269
270 double n = cvtest::norm(img, img_test, NORM_L2);
271 if ( n > 1.0)
272 {
273 ts->printf(ts->LOG, "norm = %f \n", n);
274 ts->set_failed_test_info(ts->FAIL_MISMATCH);
275 }
276 }
277 #endif
278 }
279 }
280 catch(const cv::Exception & e)
281 {
282 ts->printf(ts->LOG, "Exception: %s\n" , e.what());
283 ts->set_failed_test_info(ts->FAIL_MISMATCH);
284 }
285 }
286 };
287
288 class CV_GrfmtReadBMPRLE8Test : public cvtest::BaseTest
289 {
290 public:
run(int)291 void run(int)
292 {
293 try
294 {
295 Mat rle = imread(string(ts->get_data_path()) + "readwrite/rle8.bmp");
296 Mat bmp = imread(string(ts->get_data_path()) + "readwrite/ordinary.bmp");
297 if (cvtest::norm(rle-bmp, NORM_L2)>1.e-10)
298 ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
299 }
300 catch(...)
301 {
302 ts->set_failed_test_info(cvtest::TS::FAIL_EXCEPTION);
303 }
304 ts->set_failed_test_info(cvtest::TS::OK);
305 }
306 };
307
308
309 #ifdef HAVE_PNG
TEST(Imgcodecs_Image,write_big)310 TEST(Imgcodecs_Image, write_big) { CV_GrfmtWriteBigImageTest test; test.safe_run(); }
311 #endif
312
TEST(Imgcodecs_Image,write_imageseq)313 TEST(Imgcodecs_Image, write_imageseq) { CV_GrfmtWriteSequenceImageTest test; test.safe_run(); }
314
TEST(Imgcodecs_Image,read_bmp_rle8)315 TEST(Imgcodecs_Image, read_bmp_rle8) { CV_GrfmtReadBMPRLE8Test test; test.safe_run(); }
316
317 #ifdef HAVE_PNG
318 class CV_GrfmtPNGEncodeTest : public cvtest::BaseTest
319 {
320 public:
run(int)321 void run(int)
322 {
323 try
324 {
325 vector<uchar> buff;
326 Mat im = Mat::zeros(1000,1000, CV_8U);
327 //randu(im, 0, 256);
328 vector<int> param;
329 param.push_back(IMWRITE_PNG_COMPRESSION);
330 param.push_back(3); //default(3) 0-9.
331 cv::imencode(".png" ,im ,buff, param);
332
333 // hangs
334 Mat im2 = imdecode(buff,IMREAD_ANYDEPTH);
335 }
336 catch(...)
337 {
338 ts->set_failed_test_info(cvtest::TS::FAIL_EXCEPTION);
339 }
340 ts->set_failed_test_info(cvtest::TS::OK);
341 }
342 };
343
TEST(Imgcodecs_Image,encode_png)344 TEST(Imgcodecs_Image, encode_png) { CV_GrfmtPNGEncodeTest test; test.safe_run(); }
345
TEST(Imgcodecs_ImreadVSCvtColor,regression)346 TEST(Imgcodecs_ImreadVSCvtColor, regression)
347 {
348 cvtest::TS& ts = *cvtest::TS::ptr();
349
350 const int MAX_MEAN_DIFF = 1;
351 const int MAX_ABS_DIFF = 10;
352
353 string imgName = string(ts.get_data_path()) + "/../cv/shared/lena.png";
354 Mat original_image = imread(imgName);
355 Mat gray_by_codec = imread(imgName, 0);
356 Mat gray_by_cvt;
357
358 cvtColor(original_image, gray_by_cvt, CV_BGR2GRAY);
359
360 Mat diff;
361 absdiff(gray_by_codec, gray_by_cvt, diff);
362
363 double actual_avg_diff = (double)mean(diff)[0];
364 double actual_maxval, actual_minval;
365 minMaxLoc(diff, &actual_minval, &actual_maxval);
366 //printf("actual avg = %g, actual maxdiff = %g, npixels = %d\n", actual_avg_diff, actual_maxval, (int)diff.total());
367
368 EXPECT_LT(actual_avg_diff, MAX_MEAN_DIFF);
369 EXPECT_LT(actual_maxval, MAX_ABS_DIFF);
370 }
371
372 //Test OpenCV issue 3075 is solved
373 class CV_GrfmtReadPNGColorPaletteWithAlphaTest : public cvtest::BaseTest
374 {
375 public:
run(int)376 void run(int)
377 {
378 try
379 {
380 // First Test : Read PNG with alpha, imread flag -1
381 Mat img = imread(string(ts->get_data_path()) + "readwrite/color_palette_alpha.png",-1);
382 if (img.empty()) ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
383
384 ASSERT_TRUE(img.channels() == 4);
385
386 unsigned char* img_data = img.ptr();
387
388 // Verification first pixel is red in BGRA
389 ASSERT_TRUE(img_data[0] == 0x00);
390 ASSERT_TRUE(img_data[1] == 0x00);
391 ASSERT_TRUE(img_data[2] == 0xFF);
392 ASSERT_TRUE(img_data[3] == 0xFF);
393
394 // Verification second pixel is red in BGRA
395 ASSERT_TRUE(img_data[4] == 0x00);
396 ASSERT_TRUE(img_data[5] == 0x00);
397 ASSERT_TRUE(img_data[6] == 0xFF);
398 ASSERT_TRUE(img_data[7] == 0xFF);
399
400 // Second Test : Read PNG without alpha, imread flag -1
401 img = imread(string(ts->get_data_path()) + "readwrite/color_palette_no_alpha.png",-1);
402 if (img.empty()) ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
403
404 ASSERT_TRUE(img.channels() == 3);
405
406 img_data = img.ptr();
407
408 // Verification first pixel is red in BGR
409 ASSERT_TRUE(img_data[0] == 0x00);
410 ASSERT_TRUE(img_data[1] == 0x00);
411 ASSERT_TRUE(img_data[2] == 0xFF);
412
413 // Verification second pixel is red in BGR
414 ASSERT_TRUE(img_data[3] == 0x00);
415 ASSERT_TRUE(img_data[4] == 0x00);
416 ASSERT_TRUE(img_data[5] == 0xFF);
417
418 // Third Test : Read PNG with alpha, imread flag 1
419 img = imread(string(ts->get_data_path()) + "readwrite/color_palette_alpha.png",1);
420 if (img.empty()) ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
421
422 ASSERT_TRUE(img.channels() == 3);
423
424 img_data = img.ptr();
425
426 // Verification first pixel is red in BGR
427 ASSERT_TRUE(img_data[0] == 0x00);
428 ASSERT_TRUE(img_data[1] == 0x00);
429 ASSERT_TRUE(img_data[2] == 0xFF);
430
431 // Verification second pixel is red in BGR
432 ASSERT_TRUE(img_data[3] == 0x00);
433 ASSERT_TRUE(img_data[4] == 0x00);
434 ASSERT_TRUE(img_data[5] == 0xFF);
435
436 // Fourth Test : Read PNG without alpha, imread flag 1
437 img = imread(string(ts->get_data_path()) + "readwrite/color_palette_no_alpha.png",1);
438 if (img.empty()) ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
439
440 ASSERT_TRUE(img.channels() == 3);
441
442 img_data = img.ptr();
443
444 // Verification first pixel is red in BGR
445 ASSERT_TRUE(img_data[0] == 0x00);
446 ASSERT_TRUE(img_data[1] == 0x00);
447 ASSERT_TRUE(img_data[2] == 0xFF);
448
449 // Verification second pixel is red in BGR
450 ASSERT_TRUE(img_data[3] == 0x00);
451 ASSERT_TRUE(img_data[4] == 0x00);
452 ASSERT_TRUE(img_data[5] == 0xFF);
453 }
454 catch(...)
455 {
456 ts->set_failed_test_info(cvtest::TS::FAIL_EXCEPTION);
457 }
458 ts->set_failed_test_info(cvtest::TS::OK);
459 }
460 };
461
TEST(Imgcodecs_Image,read_png_color_palette_with_alpha)462 TEST(Imgcodecs_Image, read_png_color_palette_with_alpha) { CV_GrfmtReadPNGColorPaletteWithAlphaTest test; test.safe_run(); }
463 #endif
464
465 #ifdef HAVE_JPEG
TEST(Imgcodecs_Jpeg,encode_empty)466 TEST(Imgcodecs_Jpeg, encode_empty)
467 {
468 cv::Mat img;
469 std::vector<uchar> jpegImg;
470
471 ASSERT_THROW(cv::imencode(".jpg", img, jpegImg), cv::Exception);
472 }
473
TEST(Imgcodecs_Jpeg,encode_decode_progressive_jpeg)474 TEST(Imgcodecs_Jpeg, encode_decode_progressive_jpeg)
475 {
476 cvtest::TS& ts = *cvtest::TS::ptr();
477 string input = string(ts.get_data_path()) + "../cv/shared/lena.png";
478 cv::Mat img = cv::imread(input);
479 ASSERT_FALSE(img.empty());
480
481 std::vector<int> params;
482 params.push_back(IMWRITE_JPEG_PROGRESSIVE);
483 params.push_back(1);
484
485 string output_progressive = cv::tempfile(".jpg");
486 EXPECT_NO_THROW(cv::imwrite(output_progressive, img, params));
487 cv::Mat img_jpg_progressive = cv::imread(output_progressive);
488
489 string output_normal = cv::tempfile(".jpg");
490 EXPECT_NO_THROW(cv::imwrite(output_normal, img));
491 cv::Mat img_jpg_normal = cv::imread(output_normal);
492
493 EXPECT_EQ(0, cvtest::norm(img_jpg_progressive, img_jpg_normal, NORM_INF));
494
495 remove(output_progressive.c_str());
496 }
497
TEST(Imgcodecs_Jpeg,encode_decode_optimize_jpeg)498 TEST(Imgcodecs_Jpeg, encode_decode_optimize_jpeg)
499 {
500 cvtest::TS& ts = *cvtest::TS::ptr();
501 string input = string(ts.get_data_path()) + "../cv/shared/lena.png";
502 cv::Mat img = cv::imread(input);
503 ASSERT_FALSE(img.empty());
504
505 std::vector<int> params;
506 params.push_back(IMWRITE_JPEG_OPTIMIZE);
507 params.push_back(1);
508
509 string output_optimized = cv::tempfile(".jpg");
510 EXPECT_NO_THROW(cv::imwrite(output_optimized, img, params));
511 cv::Mat img_jpg_optimized = cv::imread(output_optimized);
512
513 string output_normal = cv::tempfile(".jpg");
514 EXPECT_NO_THROW(cv::imwrite(output_normal, img));
515 cv::Mat img_jpg_normal = cv::imread(output_normal);
516
517 EXPECT_EQ(0, cvtest::norm(img_jpg_optimized, img_jpg_normal, NORM_INF));
518
519 remove(output_optimized.c_str());
520 }
521
TEST(Imgcodecs_Jpeg,encode_decode_rst_jpeg)522 TEST(Imgcodecs_Jpeg, encode_decode_rst_jpeg)
523 {
524 cvtest::TS& ts = *cvtest::TS::ptr();
525 string input = string(ts.get_data_path()) + "../cv/shared/lena.png";
526 cv::Mat img = cv::imread(input);
527 ASSERT_FALSE(img.empty());
528
529 std::vector<int> params;
530 params.push_back(IMWRITE_JPEG_RST_INTERVAL);
531 params.push_back(1);
532
533 string output_rst = cv::tempfile(".jpg");
534 EXPECT_NO_THROW(cv::imwrite(output_rst, img, params));
535 cv::Mat img_jpg_rst = cv::imread(output_rst);
536
537 string output_normal = cv::tempfile(".jpg");
538 EXPECT_NO_THROW(cv::imwrite(output_normal, img));
539 cv::Mat img_jpg_normal = cv::imread(output_normal);
540
541 EXPECT_EQ(0, cvtest::norm(img_jpg_rst, img_jpg_normal, NORM_INF));
542
543 remove(output_rst.c_str());
544 }
545
546 #endif
547
548
549 #ifdef HAVE_TIFF
550
551 // these defines are used to resolve conflict between tiff.h and opencv2/core/types_c.h
552 #define uint64 uint64_hack_
553 #define int64 int64_hack_
554 #include "tiff.h"
555
556 #ifdef ANDROID
557 // Test disabled as it uses a lot of memory.
558 // It is killed with SIGKILL by out of memory killer.
TEST(Imgcodecs_Tiff,DISABLED_decode_tile16384x16384)559 TEST(Imgcodecs_Tiff, DISABLED_decode_tile16384x16384)
560 #else
561 TEST(Imgcodecs_Tiff, decode_tile16384x16384)
562 #endif
563 {
564 // see issue #2161
565 cv::Mat big(16384, 16384, CV_8UC1, cv::Scalar::all(0));
566 string file3 = cv::tempfile(".tiff");
567 string file4 = cv::tempfile(".tiff");
568
569 std::vector<int> params;
570 params.push_back(TIFFTAG_ROWSPERSTRIP);
571 params.push_back(big.rows);
572 cv::imwrite(file4, big, params);
573 cv::imwrite(file3, big.colRange(0, big.cols - 1), params);
574 big.release();
575
576 try
577 {
578 cv::imread(file3, IMREAD_UNCHANGED);
579 EXPECT_NO_THROW(cv::imread(file4, IMREAD_UNCHANGED));
580 }
581 catch(const std::bad_alloc&)
582 {
583 // have no enough memory
584 }
585
586 remove(file3.c_str());
587 remove(file4.c_str());
588 }
589
TEST(Imgcodecs_Tiff,write_read_16bit_big_little_endian)590 TEST(Imgcodecs_Tiff, write_read_16bit_big_little_endian)
591 {
592 // see issue #2601 "16-bit Grayscale TIFF Load Failures Due to Buffer Underflow and Endianness"
593
594 // Setup data for two minimal 16-bit grayscale TIFF files in both endian formats
595 uchar tiff_sample_data[2][86] = { {
596 // Little endian
597 0x49, 0x49, 0x2a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xad, 0xde, 0xef, 0xbe, 0x06, 0x00, 0x00, 0x01,
598 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x00,
599 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
600 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01,
601 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x01, 0x04, 0x00, 0x01, 0x00,
602 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }, {
603 // Big endian
604 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x0c, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x06, 0x01, 0x00,
605 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x00,
606 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10,
607 0x00, 0x00, 0x01, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x11,
608 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x01, 0x17, 0x00, 0x04, 0x00, 0x00,
609 0x00, 0x01, 0x00, 0x00, 0x00, 0x04 }
610 };
611
612 // Test imread() for both a little endian TIFF and big endian TIFF
613 for (int i = 0; i < 2; i++)
614 {
615 string filename = cv::tempfile(".tiff");
616
617 // Write sample TIFF file
618 FILE* fp = fopen(filename.c_str(), "wb");
619 ASSERT_TRUE(fp != NULL);
620 ASSERT_EQ((size_t)1, fwrite(tiff_sample_data, 86, 1, fp));
621 fclose(fp);
622
623 Mat img = imread(filename, IMREAD_UNCHANGED);
624
625 EXPECT_EQ(1, img.rows);
626 EXPECT_EQ(2, img.cols);
627 EXPECT_EQ(CV_16U, img.type());
628 EXPECT_EQ(sizeof(ushort), img.elemSize());
629 EXPECT_EQ(1, img.channels());
630 EXPECT_EQ(0xDEAD, img.at<ushort>(0,0));
631 EXPECT_EQ(0xBEEF, img.at<ushort>(0,1));
632
633 remove(filename.c_str());
634 }
635 }
636
637 class CV_GrfmtReadTifTiledWithNotFullTiles: public cvtest::BaseTest
638 {
639 public:
run(int)640 void run(int)
641 {
642 try
643 {
644 /* see issue #3472 - dealing with tiled images where the tile size is
645 * not a multiple of image size.
646 * The tiled images were created with 'convert' from ImageMagick,
647 * using the command 'convert <input> -define tiff:tile-geometry=128x128 -depth [8|16] <output>
648 * Note that the conversion to 16 bits expands the range from 0-255 to 0-255*255,
649 * so the test converts back but rounding errors cause small differences.
650 */
651 cv::Mat img = imread(string(ts->get_data_path()) + "readwrite/non_tiled.tif",-1);
652 if (img.empty()) ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
653 ASSERT_TRUE(img.channels() == 3);
654 cv::Mat tiled8 = imread(string(ts->get_data_path()) + "readwrite/tiled_8.tif", -1);
655 if (tiled8.empty()) ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
656 ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, tiled8);
657
658 cv::Mat tiled16 = imread(string(ts->get_data_path()) + "readwrite/tiled_16.tif", -1);
659 if (tiled16.empty()) ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
660 ASSERT_TRUE(tiled16.elemSize() == 6);
661 tiled16.convertTo(tiled8, CV_8UC3, 1./256.);
662 ASSERT_PRED_FORMAT2(cvtest::MatComparator(2, 0), img, tiled8);
663 // What about 32, 64 bit?
664 }
665 catch(...)
666 {
667 ts->set_failed_test_info(cvtest::TS::FAIL_EXCEPTION);
668 }
669 ts->set_failed_test_info(cvtest::TS::OK);
670 }
671 };
672
TEST(Imgcodecs_Tiff,decode_tile_remainder)673 TEST(Imgcodecs_Tiff, decode_tile_remainder)
674 {
675 CV_GrfmtReadTifTiledWithNotFullTiles test; test.safe_run();
676 }
677
TEST(Imgcodecs_Tiff,decode_infinite_rowsperstrip)678 TEST(Imgcodecs_Tiff, decode_infinite_rowsperstrip)
679 {
680 const uchar sample_data[142] = {
681 0x49, 0x49, 0x2a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x56, 0x54,
682 0x56, 0x5a, 0x59, 0x55, 0x5a, 0x00, 0x0a, 0x00, 0x00, 0x01,
683 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
684 0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00,
685 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
686 0x08, 0x00, 0x00, 0x00, 0x03, 0x01, 0x03, 0x00, 0x01, 0x00,
687 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00,
688 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01,
689 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
690 0x15, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
691 0x00, 0x00, 0x16, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
692 0xff, 0xff, 0xff, 0xff, 0x17, 0x01, 0x04, 0x00, 0x01, 0x00,
693 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x03, 0x00,
694 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00
696 };
697
698 const string filename = cv::tempfile(".tiff");
699 std::ofstream outfile(filename.c_str(), std::ofstream::binary);
700 outfile.write(reinterpret_cast<const char *>(sample_data), sizeof sample_data);
701 outfile.close();
702
703 EXPECT_NO_THROW(cv::imread(filename, IMREAD_UNCHANGED));
704
705 remove(filename.c_str());
706 }
707
708 class CV_GrfmtReadTifMultiPage : public cvtest::BaseTest
709 {
710 private:
compare(int flags)711 void compare(int flags)
712 {
713 const string folder = string(cvtest::TS::ptr()->get_data_path()) + "/readwrite/";
714 const int page_count = 6;
715
716 vector<Mat> pages;
717 bool res = imreadmulti(folder + "multipage.tif", pages, flags);
718 ASSERT_TRUE(res == true);
719 ASSERT_EQ(static_cast<size_t>(page_count), pages.size());
720
721 for (int i = 0; i < page_count; i++)
722 {
723 char buffer[256];
724 sprintf(buffer, "%smultipage_p%d.tif", folder.c_str(), i + 1);
725 const string filepath(buffer);
726 const Mat page = imread(filepath, flags);
727 ASSERT_TRUE(mats_equal(page, pages[i]));
728 }
729 }
730
731 public:
run(int)732 void run(int)
733 {
734 compare(IMREAD_UNCHANGED);
735 compare(IMREAD_GRAYSCALE);
736 compare(IMREAD_COLOR);
737 compare(IMREAD_ANYDEPTH);
738 compare(IMREAD_ANYCOLOR);
739 // compare(IMREAD_LOAD_GDAL); // GDAL does not support multi-page TIFFs
740 }
741 };
742
TEST(Imgcodecs_Tiff,decode_multipage)743 TEST(Imgcodecs_Tiff, decode_multipage)
744 {
745 CV_GrfmtReadTifMultiPage test; test.safe_run();
746 }
747
748 #endif
749
750 #ifdef HAVE_WEBP
751
TEST(Imgcodecs_WebP,encode_decode_lossless_webp)752 TEST(Imgcodecs_WebP, encode_decode_lossless_webp)
753 {
754 cvtest::TS& ts = *cvtest::TS::ptr();
755 string input = string(ts.get_data_path()) + "../cv/shared/lena.png";
756 cv::Mat img = cv::imread(input);
757 ASSERT_FALSE(img.empty());
758
759 string output = cv::tempfile(".webp");
760 EXPECT_NO_THROW(cv::imwrite(output, img)); // lossless
761
762 cv::Mat img_webp = cv::imread(output);
763
764 std::vector<unsigned char> buf;
765
766 FILE * wfile = NULL;
767
768 wfile = fopen(output.c_str(), "rb");
769 if (wfile != NULL)
770 {
771 fseek(wfile, 0, SEEK_END);
772 size_t wfile_size = ftell(wfile);
773 fseek(wfile, 0, SEEK_SET);
774
775 buf.resize(wfile_size);
776
777 size_t data_size = fread(&buf[0], 1, wfile_size, wfile);
778
779 if(wfile)
780 {
781 fclose(wfile);
782 }
783
784 if (data_size != wfile_size)
785 {
786 EXPECT_TRUE(false);
787 }
788 }
789
790 remove(output.c_str());
791
792 cv::Mat decode = cv::imdecode(buf, IMREAD_COLOR);
793 ASSERT_FALSE(decode.empty());
794 EXPECT_TRUE(cvtest::norm(decode, img_webp, NORM_INF) == 0);
795
796 ASSERT_FALSE(img_webp.empty());
797
798 EXPECT_TRUE(cvtest::norm(img, img_webp, NORM_INF) == 0);
799 }
800
TEST(Imgcodecs_WebP,encode_decode_lossy_webp)801 TEST(Imgcodecs_WebP, encode_decode_lossy_webp)
802 {
803 cvtest::TS& ts = *cvtest::TS::ptr();
804 std::string input = std::string(ts.get_data_path()) + "../cv/shared/lena.png";
805 cv::Mat img = cv::imread(input);
806 ASSERT_FALSE(img.empty());
807
808 for(int q = 100; q>=0; q-=20)
809 {
810 std::vector<int> params;
811 params.push_back(IMWRITE_WEBP_QUALITY);
812 params.push_back(q);
813 string output = cv::tempfile(".webp");
814
815 EXPECT_NO_THROW(cv::imwrite(output, img, params));
816 cv::Mat img_webp = cv::imread(output);
817 remove(output.c_str());
818 EXPECT_FALSE(img_webp.empty());
819 EXPECT_EQ(3, img_webp.channels());
820 EXPECT_EQ(512, img_webp.cols);
821 EXPECT_EQ(512, img_webp.rows);
822 }
823 }
824
TEST(Imgcodecs_WebP,encode_decode_with_alpha_webp)825 TEST(Imgcodecs_WebP, encode_decode_with_alpha_webp)
826 {
827 cvtest::TS& ts = *cvtest::TS::ptr();
828 std::string input = std::string(ts.get_data_path()) + "../cv/shared/lena.png";
829 cv::Mat img = cv::imread(input);
830 ASSERT_FALSE(img.empty());
831
832 std::vector<cv::Mat> imgs;
833 cv::split(img, imgs);
834 imgs.push_back(cv::Mat(imgs[0]));
835 imgs[imgs.size() - 1] = cv::Scalar::all(128);
836 cv::merge(imgs, img);
837
838 string output = cv::tempfile(".webp");
839
840 EXPECT_NO_THROW(cv::imwrite(output, img));
841 cv::Mat img_webp = cv::imread(output);
842 remove(output.c_str());
843 EXPECT_FALSE(img_webp.empty());
844 EXPECT_EQ(4, img_webp.channels());
845 EXPECT_EQ(512, img_webp.cols);
846 EXPECT_EQ(512, img_webp.rows);
847 }
848
849 #endif
850
TEST(Imgcodecs_Hdr,regression)851 TEST(Imgcodecs_Hdr, regression)
852 {
853 string folder = string(cvtest::TS::ptr()->get_data_path()) + "/readwrite/";
854 string name_rle = folder + "rle.hdr";
855 string name_no_rle = folder + "no_rle.hdr";
856 Mat img_rle = imread(name_rle, -1);
857 ASSERT_FALSE(img_rle.empty()) << "Could not open " << name_rle;
858 Mat img_no_rle = imread(name_no_rle, -1);
859 ASSERT_FALSE(img_no_rle.empty()) << "Could not open " << name_no_rle;
860
861 double min = 0.0, max = 1.0;
862 minMaxLoc(abs(img_rle - img_no_rle), &min, &max);
863 ASSERT_FALSE(max > DBL_EPSILON);
864 string tmp_file_name = tempfile(".hdr");
865 vector<int>param(1);
866 for(int i = 0; i < 2; i++) {
867 param[0] = i;
868 imwrite(tmp_file_name, img_rle, param);
869 Mat written_img = imread(tmp_file_name, -1);
870 ASSERT_FALSE(written_img.empty()) << "Could not open " << tmp_file_name;
871 minMaxLoc(abs(img_rle - written_img), &min, &max);
872 ASSERT_FALSE(max > DBL_EPSILON);
873 }
874 }
875