test_gif.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html
  4. #include "test_precomp.hpp"
  5. #ifdef HAVE_IMGCODEC_GIF
  6. namespace opencv_test { namespace {
  7. const string gifsuite_files_multi[]={
  8. "basi3p01",
  9. "basi3p02",
  10. "basi3p04",
  11. "basn3p01",
  12. "basn3p02",
  13. "basn3p04",
  14. "ccwn3p08",
  15. "ch1n3p04",
  16. "cs3n3p08",
  17. "cs5n3p08",
  18. "cs8n3p08",
  19. "g03n3p04",
  20. "g04n3p04",
  21. "g05n3p04",
  22. "g07n3p04",
  23. "g10n3p04",
  24. "g25n3p04",
  25. "s32i3p04",
  26. "s32n3p04",
  27. "tp0n3p08",
  28. };
  29. const string gifsuite_files_read_single[] = {
  30. "basi3p01",
  31. "basi3p02",
  32. "basi3p04",
  33. "basn3p01",
  34. "basn3p02",
  35. "basn3p04",
  36. "ccwn3p08",
  37. "cdfn2c08",
  38. "cdhn2c08",
  39. "cdsn2c08",
  40. "cdun2c08",
  41. "ch1n3p04",
  42. "cs3n3p08",
  43. "cs5n2c08",
  44. "cs5n3p08",
  45. "cs8n2c08",
  46. "cs8n3p08",
  47. "exif2c08",
  48. "g03n2c08",
  49. "g03n3p04",
  50. "g04n2c08",
  51. "g04n3p04",
  52. "g05n2c08",
  53. "g05n3p04",
  54. "g07n2c08",
  55. "g07n3p04",
  56. "g10n2c08",
  57. "g10n3p04"
  58. };
  59. const string gifsuite_files_read_write_suite[]={
  60. "g25n2c08",
  61. "g25n3p04",
  62. "s01i3p01",
  63. "s01n3p01",
  64. "s02i3p01",
  65. "s02n3p01",
  66. "s03i3p01",
  67. "s03n3p01",
  68. "s04i3p01",
  69. "s04n3p01",
  70. "s05i3p02",
  71. "s05n3p02",
  72. "s06i3p02",
  73. "s06n3p02",
  74. "s07i3p02",
  75. "s07n3p02",
  76. "s08i3p02",
  77. "s08n3p02",
  78. "s09i3p02",
  79. "s09n3p02",
  80. "s32i3p04",
  81. "s32n3p04",
  82. "s33i3p04",
  83. "s33n3p04",
  84. "s34i3p04",
  85. "s34n3p04",
  86. "s35i3p04",
  87. "s35n3p04",
  88. "s36i3p04",
  89. "s36n3p04",
  90. "s37i3p04",
  91. "s37n3p04",
  92. "s38i3p04",
  93. "s38n3p04",
  94. "s39i3p04",
  95. "s39n3p04",
  96. "s40i3p04",
  97. "s40n3p04",
  98. "tp0n3p08",
  99. };
  100. const std::pair<string,int> gifsuite_files_bgra[]={
  101. make_pair("gif_bgra1",53287),
  102. make_pair("gif_bgra2",52651),
  103. make_pair("gif_bgra3",54809),
  104. make_pair("gif_bgra4",57562),
  105. make_pair("gif_bgra5",56733),
  106. make_pair("gif_bgra6",52110),
  107. };
  108. TEST(Imgcodecs_Gif, read_gif_multi)
  109. {
  110. const string root = cvtest::TS::ptr()->get_data_path();
  111. const string filename = root + "gifsuite/gif_multi.gif";
  112. vector<cv::Mat> img_vec_8UC4;
  113. ASSERT_NO_THROW(cv::imreadmulti(filename, img_vec_8UC4,0,20,IMREAD_UNCHANGED));
  114. EXPECT_EQ(img_vec_8UC4.size(), imcount(filename));
  115. vector<cv::Mat> img_vec_8UC3;
  116. for(const auto & i : img_vec_8UC4){
  117. cv::Mat img_tmp;
  118. cvtColor(i,img_tmp,COLOR_BGRA2BGR);
  119. img_vec_8UC3.push_back(img_tmp);
  120. }
  121. const long unsigned int expected_size=20;
  122. EXPECT_EQ(img_vec_8UC3.size(),expected_size);
  123. for(long unsigned int i=0;i<img_vec_8UC3.size();i++){
  124. cv::Mat img=img_vec_8UC3[i];
  125. const string png_filename = root + "pngsuite/" + gifsuite_files_multi[i] + ".png";
  126. cv::Mat img_png;
  127. ASSERT_NO_THROW(img_png = imread(png_filename,IMREAD_UNCHANGED));
  128. ASSERT_FALSE(img_png.empty());
  129. EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, img_png);
  130. }
  131. }
  132. typedef testing::TestWithParam<string> Imgcodecs_Gif_GifSuite_SingleFrame;
  133. TEST_P(Imgcodecs_Gif_GifSuite_SingleFrame, read_gif_single)
  134. {
  135. const string root = cvtest::TS::ptr()->get_data_path();
  136. const string filename = root + "gifsuite/" + GetParam() + ".gif";
  137. const string png_filename=root + "pngsuite/" + GetParam() + ".png";
  138. const long unsigned int expected_size = 1;
  139. EXPECT_EQ(expected_size, imcount(filename));
  140. cv::Mat img_8UC4;
  141. ASSERT_NO_THROW(img_8UC4 = cv::imread(filename, IMREAD_UNCHANGED));
  142. ASSERT_FALSE(img_8UC4.empty());
  143. cv::Mat img_8UC3;
  144. ASSERT_NO_THROW(cvtColor(img_8UC4, img_8UC3, COLOR_BGRA2BGR));
  145. cv::Mat img_png;
  146. ASSERT_NO_THROW(img_png = cv::imread(png_filename, IMREAD_UNCHANGED));
  147. ASSERT_FALSE(img_png.empty());
  148. EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img_8UC3, img_png);
  149. }
  150. INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Gif_GifSuite_SingleFrame,
  151. testing::ValuesIn(gifsuite_files_read_single));
  152. TEST(Imgcodecs_Gif, read_gif_big){
  153. const string root = cvtest::TS::ptr()->get_data_path();
  154. const string gif_filename = root + "gifsuite/gif_big.gif";
  155. const string png_filename = root + "gifsuite/gif_big.png";
  156. cv::Mat img_8UC4;
  157. ASSERT_NO_THROW(img_8UC4 = imread(gif_filename, IMREAD_UNCHANGED));
  158. ASSERT_FALSE(img_8UC4.empty());
  159. cv::Mat img_8UC3;
  160. const int expected_col=1303;
  161. const int expected_row=1391;
  162. EXPECT_EQ(expected_col, img_8UC4.cols);
  163. EXPECT_EQ(expected_row, img_8UC4.rows);
  164. ASSERT_NO_THROW(cvtColor(img_8UC4, img_8UC3,COLOR_BGRA2BGR));
  165. EXPECT_EQ(expected_col, img_8UC3.cols);
  166. EXPECT_EQ(expected_row, img_8UC3.rows);
  167. cv::Mat img_png;
  168. ASSERT_NO_THROW(img_png=imread(png_filename, IMREAD_UNCHANGED));
  169. ASSERT_FALSE(img_png.empty());
  170. cv::Mat img_png_8UC3;
  171. ASSERT_NO_THROW(cvtColor(img_png,img_png_8UC3, COLOR_BGRA2BGR));
  172. EXPECT_EQ(img_8UC3.size, img_png_8UC3.size);
  173. EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img_8UC3, img_png_8UC3);
  174. }
  175. typedef testing::TestWithParam<std::pair<string,int>> Imgcodecs_Gif_GifSuite_SingleFrame_BGRA;
  176. TEST_P(Imgcodecs_Gif_GifSuite_SingleFrame_BGRA, read_gif_single_bgra){
  177. const string root = cvtest::TS::ptr()->get_data_path();
  178. const string gif_filename = root + "gifsuite/" + GetParam().first + ".gif";
  179. const string png_filename = root + "gifsuite/" + GetParam().first + ".png";
  180. cv::Mat gif_img;
  181. cv::Mat png_img;
  182. ASSERT_NO_THROW(gif_img = cv::imread(gif_filename, IMREAD_UNCHANGED));
  183. ASSERT_FALSE(gif_img.empty());
  184. ASSERT_NO_THROW(png_img = cv::imread(png_filename, IMREAD_UNCHANGED));
  185. ASSERT_FALSE(png_img.empty());
  186. EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), gif_img, png_img);
  187. int transparent_count = 0;
  188. for(int i=0; i<gif_img.rows; i++){
  189. for(int j=0; j<gif_img.cols; j++){
  190. cv::Vec4b pixel1 = gif_img.at<cv::Vec4b>(i,j);
  191. if((int)(pixel1[3]) == 0){
  192. transparent_count++;
  193. }
  194. }
  195. }
  196. EXPECT_EQ(transparent_count,GetParam().second);
  197. }
  198. INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Gif_GifSuite_SingleFrame_BGRA ,
  199. testing::ValuesIn(gifsuite_files_bgra));
  200. TEST(Imgcodecs_Gif,read_gif_multi_bgra){
  201. const string root = cvtest::TS::ptr()->get_data_path();
  202. const string gif_filename = root + "gifsuite/gif_multi_bgra.gif";
  203. vector<cv::Mat> img_vec;
  204. ASSERT_NO_THROW(cv::imreadmulti(gif_filename, img_vec, IMREAD_UNCHANGED));
  205. EXPECT_EQ(imcount(gif_filename), img_vec.size());
  206. const int fixed_transparent_count = 53211;
  207. for(auto & frame_count : img_vec){
  208. int transparent_count=0;
  209. for(int i=0; i<frame_count.rows; i++){
  210. for(int j=0; j<frame_count.cols; j++){
  211. cv::Vec4b pixel1 = frame_count.at<cv::Vec4b>(i,j);
  212. if((int)(pixel1[3]) == 0){
  213. transparent_count++;
  214. }
  215. }
  216. }
  217. EXPECT_EQ(fixed_transparent_count,transparent_count);
  218. }
  219. }
  220. TEST(Imgcodecs_Gif, read_gif_special){
  221. const string root = cvtest::TS::ptr()->get_data_path();
  222. const string gif_filename1 = root + "gifsuite/special1.gif";
  223. const string png_filename1 = root + "gifsuite/special1.png";
  224. const string gif_filename2 = root + "gifsuite/special2.gif";
  225. const string png_filename2 = root + "gifsuite/special2.png";
  226. cv::Mat gif_img1;
  227. ASSERT_NO_THROW(gif_img1 = cv::imread(gif_filename1,IMREAD_COLOR));
  228. ASSERT_FALSE(gif_img1.empty());
  229. cv::Mat png_img1;
  230. ASSERT_NO_THROW(png_img1 = cv::imread(png_filename1,IMREAD_COLOR));
  231. ASSERT_FALSE(png_img1.empty());
  232. EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), gif_img1, png_img1);
  233. cv::Mat gif_img2;
  234. ASSERT_NO_THROW(gif_img2 = cv::imread(gif_filename2,IMREAD_COLOR));
  235. ASSERT_FALSE(gif_img2.empty());
  236. cv::Mat png_img2;
  237. ASSERT_NO_THROW(png_img2 = cv::imread(png_filename2,IMREAD_COLOR));
  238. ASSERT_FALSE(png_img2.empty());
  239. EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), gif_img2, png_img2);
  240. }
  241. TEST(Imgcodecs_Gif,write_gif_flags){
  242. vector<uchar> buff;
  243. const int expected_rows=611;
  244. const int expected_cols=293;
  245. Mat img_gt = Mat::ones(expected_rows, expected_cols, CV_8UC3);
  246. const vector<int> param = { IMWRITE_GIF_QUALITY, IMWRITE_GIF_FAST_NO_DITHER, IMWRITE_GIF_DITHER, 3};
  247. bool ret = false;
  248. EXPECT_NO_THROW(ret = imencode(".gif", img_gt, buff, param));
  249. EXPECT_TRUE(ret);
  250. Mat img;
  251. EXPECT_NO_THROW(img = imdecode(buff, IMREAD_COLOR));
  252. EXPECT_FALSE(img.empty());
  253. EXPECT_EQ(img.cols, expected_cols);
  254. EXPECT_EQ(img.rows, expected_rows);
  255. EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, img_gt);
  256. }
  257. TEST(Imgcodecs_Gif, write_gif_big) {
  258. const string root = cvtest::TS::ptr()->get_data_path();
  259. const string png_filename = root + "gifsuite/gif_big.png";
  260. const string gif_filename = cv::tempfile(".gif");
  261. cv::Mat img;
  262. ASSERT_NO_THROW(img = cv::imread(png_filename, IMREAD_UNCHANGED));
  263. ASSERT_FALSE(img.empty());
  264. EXPECT_EQ(1303, img.cols);
  265. EXPECT_EQ(1391, img.rows);
  266. ASSERT_NO_THROW(imwrite(gif_filename, img));
  267. cv::Mat img_gif;
  268. ASSERT_NO_THROW(img_gif = cv::imread(gif_filename, IMREAD_UNCHANGED));
  269. ASSERT_FALSE(img_gif.empty());
  270. EXPECT_EQ(1303, img_gif.cols);
  271. EXPECT_EQ(1391, img_gif.rows);
  272. EXPECT_EQ(0, remove(gif_filename.c_str()));
  273. }
  274. typedef testing::TestWithParam<string> Imgcodecs_Gif_GifSuite_Read_Write_Suite;
  275. TEST_P(Imgcodecs_Gif_GifSuite_Read_Write_Suite ,read_gif_single)
  276. {
  277. const string root = cvtest::TS::ptr()->get_data_path();
  278. const string png_filename = root + "pngsuite/"+GetParam()+".png";
  279. const string gif_filename = cv::tempfile(".gif");
  280. cv::Mat img;
  281. ASSERT_NO_THROW(img = cv::imread(png_filename, IMREAD_UNCHANGED));
  282. ASSERT_FALSE(img.empty());
  283. vector<int> param;
  284. param.push_back(IMWRITE_GIF_QUALITY);
  285. param.push_back(8);
  286. param.push_back(IMWRITE_GIF_DITHER);
  287. param.push_back(3);
  288. ASSERT_NO_THROW(imwrite(gif_filename, img, param));
  289. cv::Mat img_gif;
  290. ASSERT_NO_THROW(img_gif = cv::imread(gif_filename, IMREAD_UNCHANGED));
  291. ASSERT_FALSE(img_gif.empty());
  292. cv::Mat img_8UC3;
  293. ASSERT_NO_THROW(cv::cvtColor(img_gif, img_8UC3, COLOR_BGRA2BGR));
  294. EXPECT_PRED_FORMAT2(cvtest::MatComparator(29, 0), img, img_8UC3);
  295. EXPECT_EQ(0, remove(gif_filename.c_str()));
  296. }
  297. INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Gif_GifSuite_Read_Write_Suite ,
  298. testing::ValuesIn(gifsuite_files_read_write_suite));
  299. TEST(Imgcodecs_Gif, write_gif_multi) {
  300. const string root = cvtest::TS::ptr()->get_data_path();
  301. const string gif_filename = cv::tempfile(".gif");
  302. vector<cv::Mat> img_vec;
  303. for (long unsigned int i = 0; i < 20; i++) {
  304. const string png_filename = root + "pngsuite/" + gifsuite_files_multi[i] + ".png";
  305. cv::Mat img;
  306. ASSERT_NO_THROW(img = cv::imread(png_filename, IMREAD_UNCHANGED));
  307. ASSERT_FALSE(img.empty());
  308. img_vec.push_back(img);
  309. }
  310. vector<int> param;
  311. param.push_back(IMWRITE_GIF_QUALITY);
  312. param.push_back(8);
  313. param.push_back(IMWRITE_GIF_DITHER);
  314. param.push_back(3);
  315. ASSERT_NO_THROW(cv::imwritemulti(gif_filename, img_vec, param));
  316. vector<cv::Mat> img_vec_gif;
  317. ASSERT_NO_THROW(cv::imreadmulti(gif_filename, img_vec_gif));
  318. EXPECT_EQ(img_vec.size(), img_vec_gif.size());
  319. for (long unsigned int i = 0; i < img_vec.size(); i++) {
  320. cv::Mat img_8UC3;
  321. ASSERT_NO_THROW(cv::cvtColor(img_vec_gif[i], img_8UC3, COLOR_BGRA2BGR));
  322. EXPECT_PRED_FORMAT2(cvtest::MatComparator(29, 0), img_vec[i], img_8UC3);
  323. }
  324. EXPECT_EQ(0, remove(gif_filename.c_str()));
  325. }
  326. TEST(Imgcodecs_Gif, encode_IMREAD_GRAYSCALE) {
  327. cv::Mat src;
  328. cv::Mat decoded;
  329. vector<uint8_t> buf;
  330. vector<int> param;
  331. bool ret = false;
  332. src = cv::Mat(240,240,CV_8UC3,cv::Scalar(128,64,32));
  333. EXPECT_NO_THROW(ret = imencode(".gif", src, buf, param));
  334. EXPECT_TRUE(ret);
  335. EXPECT_NO_THROW(decoded = imdecode(buf, cv::IMREAD_GRAYSCALE));
  336. EXPECT_FALSE(decoded.empty());
  337. EXPECT_EQ(decoded.channels(), 1);
  338. }
  339. // See https://github.com/opencv/opencv/issues/26924
  340. TEST(Imgcodecs_Gif, decode_disposal_method)
  341. {
  342. const string root = cvtest::TS::ptr()->get_data_path();
  343. const string filename = root + "gifsuite/disposalMethod.gif";
  344. cv::Animation anim;
  345. bool ret = false;
  346. EXPECT_NO_THROW(ret = imreadanimation(filename, anim, cv::IMREAD_UNCHANGED));
  347. EXPECT_TRUE(ret);
  348. /* [Detail of this test]
  349. * disposalMethod.gif has 5 frames to draw 8x8 rectangles with each color index, offsets and disposal method.
  350. * frame 1 draws {1, ... ,1} rectangle at (1,1) with DisposalMethod = 0.
  351. * frame 2 draws {2, ... ,2} rectangle at (2,2) with DisposalMethod = 3.
  352. * frame 3 draws {3, ... ,3} rectangle at (3,3) with DisposalMethod = 1.
  353. * frame 4 draws {4, ... ,4} rectangle at (4,4) with DisposalMethod = 2.
  354. * frame 5 draws {5, ... ,5} rectangle at (5,5) with DisposalMethod = 1.
  355. *
  356. * To convenience to test, color[N] in the color table has RGB(32*N, some, some).
  357. * color[0] = RGB(0,0,0) (background color).
  358. * color[1] = RGB(32,0,0)
  359. * color[2] = RGB(64,0,255)
  360. * color[3] = RGB(96,255,0)
  361. * color[4] = RGB(128,128,128)
  362. * color[5] = RGB(160,255,255)
  363. */
  364. const int refIds[5][6] =
  365. {// { 0, 0, 0, 0, 0, 0} 0 is background color.
  366. { 0, 1, 1, 1, 1, 1}, // 1 is to be not disposed.
  367. { 0, 1, 2, 2, 2, 2}, // 2 is to be restored to previous.
  368. { 0, 1, 1, 3, 3, 3}, // 3 is to be left in place.
  369. { 0, 1, 1, 3, 4, 4}, // 4 is to be restored to the background color.
  370. { 0, 1, 1, 3, 0, 5}, // 5 is to be left in place.
  371. };
  372. for(int i = 0 ; i < 5; i++)
  373. {
  374. cv::Mat frame = anim.frames[i];
  375. EXPECT_FALSE(frame.empty());
  376. EXPECT_EQ(frame.type(), CV_8UC4);
  377. for(int j = 0; j < 6; j ++ )
  378. {
  379. const cv::Scalar p = frame.at<Vec4b>(j,j);
  380. EXPECT_EQ( p[2], refIds[i][j] * 32 ) << " i = " << i << " j = " << j << " pixels = " << p;
  381. }
  382. }
  383. }
  384. // See https://github.com/opencv/opencv/issues/26970
  385. typedef testing::TestWithParam<int> Imgcodecs_Gif_loop_count;
  386. TEST_P(Imgcodecs_Gif_loop_count, imwriteanimation)
  387. {
  388. const string gif_filename = cv::tempfile(".gif");
  389. int loopCount = GetParam();
  390. cv::Animation anim(loopCount);
  391. vector<cv::Mat> src;
  392. for(int n = 1; n <= 5 ; n ++ )
  393. {
  394. cv::Mat frame(64, 64, CV_8UC3, cv::Scalar::all(0));
  395. cv::putText(frame, cv::format("%d", n), cv::Point(0,64), cv::FONT_HERSHEY_PLAIN, 4.0, cv::Scalar::all(255));
  396. anim.frames.push_back(frame);
  397. anim.durations.push_back(1000 /* ms */);
  398. }
  399. bool ret = false;
  400. #if 0
  401. // To output gif image for test.
  402. EXPECT_NO_THROW(ret = imwriteanimation(cv::format("gif_loop-%d.gif", loopCount), anim));
  403. EXPECT_TRUE(ret);
  404. #endif
  405. EXPECT_NO_THROW(ret = imwriteanimation(gif_filename, anim));
  406. EXPECT_TRUE(ret);
  407. // Read raw GIF data.
  408. std::ifstream ifs(gif_filename);
  409. std::stringstream ss;
  410. ss << ifs.rdbuf();
  411. string tmp = ss.str();
  412. std::vector<uint8_t> buf(tmp.begin(), tmp.end());
  413. std::vector<uint8_t> netscape = {0x21, 0xFF, 0x0B, 'N','E','T','S','C','A','P','E','2','.','0'};
  414. auto pos = std::search(buf.begin(), buf.end(), netscape.begin(), netscape.end());
  415. if(loopCount == 1) {
  416. EXPECT_EQ(pos, buf.end()) << "Netscape Application Block should not be included if Animation.loop_count == 1";
  417. } else {
  418. EXPECT_NE(pos, buf.end()) << "Netscape Application Block should be included if Animation.loop_count != 1";
  419. }
  420. remove(gif_filename.c_str());
  421. }
  422. INSTANTIATE_TEST_CASE_P(/*nothing*/,
  423. Imgcodecs_Gif_loop_count,
  424. testing::Values(
  425. -1,
  426. 0, // Default, loop-forever
  427. 1,
  428. 2,
  429. 65534,
  430. 65535, // Maximum Limit
  431. 65536
  432. )
  433. );
  434. typedef testing::TestWithParam<int> Imgcodecs_Gif_duration;
  435. TEST_P(Imgcodecs_Gif_duration, imwriteanimation)
  436. {
  437. const string gif_filename = cv::tempfile(".gif");
  438. cv::Animation anim;
  439. int duration = GetParam();
  440. vector<cv::Mat> src;
  441. for(int n = 1; n <= 5 ; n ++ )
  442. {
  443. cv::Mat frame(64, 64, CV_8UC3, cv::Scalar::all(0));
  444. cv::putText(frame, cv::format("%d", n), cv::Point(0,64), cv::FONT_HERSHEY_PLAIN, 4.0, cv::Scalar::all(255));
  445. anim.frames.push_back(frame);
  446. anim.durations.push_back(duration /* ms */);
  447. }
  448. bool ret = false;
  449. #if 0
  450. // To output gif image for test.
  451. EXPECT_NO_THROW(ret = imwriteanimation(cv::format("gif_duration-%d.gif", duration), anim));
  452. EXPECT_EQ(ret, ( (0 <= duration) && (duration <= 655350) ) );
  453. #endif
  454. EXPECT_NO_THROW(ret = imwriteanimation(gif_filename, anim));
  455. EXPECT_EQ(ret, ( (0 <= duration) && (duration <= 655350) ) );
  456. remove(gif_filename.c_str());
  457. }
  458. INSTANTIATE_TEST_CASE_P(/*nothing*/,
  459. Imgcodecs_Gif_duration,
  460. testing::Values(
  461. -1, // Unsupported
  462. 0, // Undefined Behaviour
  463. 1,
  464. 9,
  465. 10,
  466. 50,
  467. 100, // 10 FPS
  468. 1000, // 1 FPS
  469. 655340,
  470. 655350, // Maximum Limit
  471. 655360 // Unsupported
  472. )
  473. );
  474. }//opencv_test
  475. }//namespace
  476. #endif