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