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 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 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 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 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: 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 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: 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: 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 310 TEST(Imgcodecs_Image, write_big) { CV_GrfmtWriteBigImageTest test; test.safe_run(); } 311 #endif 312 313 TEST(Imgcodecs_Image, write_imageseq) { CV_GrfmtWriteSequenceImageTest test; test.safe_run(); } 314 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: 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 344 TEST(Imgcodecs_Image, encode_png) { CV_GrfmtPNGEncodeTest test; test.safe_run(); } 345 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: 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 462 TEST(Imgcodecs_Image, read_png_color_palette_with_alpha) { CV_GrfmtReadPNGColorPaletteWithAlphaTest test; test.safe_run(); } 463 #endif 464 465 #ifdef HAVE_JPEG 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 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 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 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. 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 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: 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 673 TEST(Imgcodecs_Tiff, decode_tile_remainder) 674 { 675 CV_GrfmtReadTifTiledWithNotFullTiles test; test.safe_run(); 676 } 677 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: 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: 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 743 TEST(Imgcodecs_Tiff, decode_multipage) 744 { 745 CV_GrfmtReadTifMultiPage test; test.safe_run(); 746 } 747 748 #endif 749 750 #ifdef HAVE_WEBP 751 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 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 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 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