// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html #include "test_precomp.hpp" #include "test_common.hpp" namespace opencv_test { namespace { #if defined(HAVE_PNG) || defined(HAVE_SPNG) TEST(Imgcodecs_Png, write_big) { const string root = cvtest::TS::ptr()->get_data_path(); const string filename = root + "readwrite/read.png"; Mat img; ASSERT_NO_THROW(img = imread(filename)); ASSERT_FALSE(img.empty()); EXPECT_EQ(13043, img.cols); EXPECT_EQ(13917, img.rows); vector buff; bool status = false; ASSERT_NO_THROW(status = imencode(".png", img, buff, { IMWRITE_PNG_ZLIBBUFFER_SIZE, 1024*1024 })); ASSERT_TRUE(status); #ifdef HAVE_PNG EXPECT_EQ((size_t)816219, buff.size()); #else EXPECT_EQ((size_t)817407, buff.size()); #endif } TEST(Imgcodecs_Png, encode) { vector buff; Mat img_gt = Mat::zeros(1000, 1000, CV_8U); vector param; param.push_back(IMWRITE_PNG_COMPRESSION); param.push_back(3); //default(3) 0-9. bool status = false; EXPECT_NO_THROW(status = imencode(".png", img_gt, buff, param)); ASSERT_TRUE(status); Mat img; EXPECT_NO_THROW(img = imdecode(buff, IMREAD_ANYDEPTH)); // hang EXPECT_FALSE(img.empty()); EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, img_gt); } TEST(Imgcodecs_Png, regression_ImreadVSCvtColor) { const string root = cvtest::TS::ptr()->get_data_path(); const string imgName = root + "../cv/shared/lena.png"; Mat original_image = imread(imgName); Mat gray_by_codec = imread(imgName, IMREAD_GRAYSCALE); Mat gray_by_cvt; cvtColor(original_image, gray_by_cvt, COLOR_BGR2GRAY); Mat diff; absdiff(gray_by_codec, gray_by_cvt, diff); EXPECT_LT(cvtest::mean(diff)[0], 1.); EXPECT_PRED_FORMAT2(cvtest::MatComparator(10, 0), gray_by_codec, gray_by_cvt); } // Test OpenCV issue 3075 is solved TEST(Imgcodecs_Png, read_color_palette_with_alpha) { const string root = cvtest::TS::ptr()->get_data_path(); Mat img; // First Test : Read PNG with alpha, imread flag -1 img = imread(root + "readwrite/color_palette_alpha.png", IMREAD_UNCHANGED); ASSERT_FALSE(img.empty()); ASSERT_TRUE(img.channels() == 4); // pixel is red in BGRA EXPECT_EQ(img.at(0, 0), Vec4b(0, 0, 255, 255)); EXPECT_EQ(img.at(0, 1), Vec4b(0, 0, 255, 255)); // Second Test : Read PNG without alpha, imread flag -1 img = imread(root + "readwrite/color_palette_no_alpha.png", IMREAD_UNCHANGED); ASSERT_FALSE(img.empty()); ASSERT_TRUE(img.channels() == 3); // pixel is red in BGR EXPECT_EQ(img.at(0, 0), Vec3b(0, 0, 255)); EXPECT_EQ(img.at(0, 1), Vec3b(0, 0, 255)); // Third Test : Read PNG with alpha, imread flag 1 img = imread(root + "readwrite/color_palette_alpha.png", IMREAD_COLOR); ASSERT_FALSE(img.empty()); ASSERT_TRUE(img.channels() == 3); // pixel is red in BGR EXPECT_EQ(img.at(0, 0), Vec3b(0, 0, 255)); EXPECT_EQ(img.at(0, 1), Vec3b(0, 0, 255)); img = imread(root + "readwrite/color_palette_alpha.png", IMREAD_COLOR_RGB); ASSERT_FALSE(img.empty()); ASSERT_TRUE(img.channels() == 3); // pixel is red in RGB EXPECT_EQ(img.at(0, 0), Vec3b(255, 0, 0)); EXPECT_EQ(img.at(0, 1), Vec3b(255, 0, 0)); // Fourth Test : Read PNG without alpha, imread flag 1 img = imread(root + "readwrite/color_palette_no_alpha.png", IMREAD_COLOR); ASSERT_FALSE(img.empty()); ASSERT_TRUE(img.channels() == 3); // pixel is red in BGR EXPECT_EQ(img.at(0, 0), Vec3b(0, 0, 255)); EXPECT_EQ(img.at(0, 1), Vec3b(0, 0, 255)); img = imread(root + "readwrite/color_palette_no_alpha.png", IMREAD_COLOR_RGB); ASSERT_FALSE(img.empty()); ASSERT_TRUE(img.channels() == 3); // pixel is red in RGB EXPECT_EQ(img.at(0, 0), Vec3b(255, 0, 0)); EXPECT_EQ(img.at(0, 1), Vec3b(255, 0, 0)); } // IHDR shall be first. // See https://github.com/opencv/opencv/issues/27295 TEST(Imgcodecs_Png, decode_regression27295) { vector buff; Mat src = Mat::zeros(240, 180, CV_8UC3); vector param; EXPECT_NO_THROW(imencode(".png", src, buff, param)); Mat img; // If IHDR chunk found as the first chunk, output shall not be empty. // 8 means PNG signature length. // 4 means length field(uint32_t). EXPECT_EQ(buff[8+4+0], 'I'); EXPECT_EQ(buff[8+4+1], 'H'); EXPECT_EQ(buff[8+4+2], 'D'); EXPECT_EQ(buff[8+4+3], 'R'); EXPECT_NO_THROW(img = imdecode(buff, IMREAD_COLOR)); EXPECT_FALSE(img.empty()); // If Non-IHDR chunk found as the first chunk, output shall be empty. buff[8+4+0] = 'i'; // Not 'I' buff[8+4+1] = 'H'; buff[8+4+2] = 'D'; buff[8+4+3] = 'R'; EXPECT_NO_THROW(img = imdecode(buff, IMREAD_COLOR)); EXPECT_TRUE(img.empty()); // If CgBI chunk (Apple private) found as the first chunk, output shall be empty with special message. buff[8+4+0] = 'C'; buff[8+4+1] = 'g'; buff[8+4+2] = 'B'; buff[8+4+3] = 'I'; EXPECT_NO_THROW(img = imdecode(buff, IMREAD_COLOR)); EXPECT_TRUE(img.empty()); } // The program must not crash even when decoding a corrupted APNG image. // See https://github.com/opencv/opencv/issues/27744 #if defined(HAVE_PNG) // APNG is supported only with using libpng TEST(Imgcodecs_Png, decode_regression27744) { // Create APNG stream Animation anim; for(size_t i = 0 ; i < 3 ; i++) { Mat frame(120, 120, CV_8UC3, Scalar(0,0,0)); putText(frame, cv::format("%d", static_cast(i)), Point(5, 28), FONT_HERSHEY_SIMPLEX, .5, Scalar(100, 255, 0, 255), 2); anim.frames.push_back(frame); anim.durations.push_back(30); } bool ret = false; vector buff; EXPECT_NO_THROW(ret = imencodeanimation(".png", anim, buff)); ASSERT_TRUE(ret) << "imencodeanimation() returns false"; // Find IDAT chunk const vector IDAT = {'I', 'D', 'A', 'T' }; std::vector::iterator it = std::search(buff.begin(), buff.end(), IDAT.begin(), IDAT.end()); ASSERT_FALSE(it == buff.end()) << "IDAT chunk not found"; // Determine the range to test // APNG stream contains as { len0, len1, len2, len3, 'I', 'D', 'A' 'T', ... } size_t idx = std::distance(buff.begin(), it); // 'I' position size_t len = (buff[idx-4] << 24) + (buff[idx-3] << 16) + (buff[idx-2] << 8) + (buff[idx-1]); // IDAT chunk length idx = idx + 4; // Move to IDAT body // Test for(size_t i = 0; i < len; i++, idx++) { vector work = buff; work[idx] = static_cast((static_cast(work[idx]) + 1) & 0xff); Mat dst; EXPECT_NO_THROW(dst = imdecode(work, cv::IMREAD_COLOR)); if(dst.empty()) { // libpng detects some error, but the program is not crashed. Test is passed. break; } } } #endif typedef testing::TestWithParam Imgcodecs_Png_PngSuite; // Parameterized test for decoding PNG files from the PNGSuite test set TEST_P(Imgcodecs_Png_PngSuite, decode) { // Construct full paths for the PNG image and corresponding ground truth XML file const string root = cvtest::TS::ptr()->get_data_path(); const string filename = root + "pngsuite/" + GetParam() + ".png"; const string xml_filename = root + "pngsuite/" + GetParam() + ".xml"; // Load the XML file containing the ground truth data FileStorage fs(xml_filename, FileStorage::READ); ASSERT_TRUE(fs.isOpened()); // Ensure the file was opened successfully // Load the image using IMREAD_UNCHANGED to preserve original format Mat src = imread(filename, IMREAD_UNCHANGED); ASSERT_FALSE(src.empty()); // Ensure the image was loaded successfully // Load the ground truth matrix from XML Mat gt; fs.getFirstTopLevelNode() >> gt; // Compare the image loaded with IMREAD_UNCHANGED to the ground truth EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), src, gt); // Declare matrices for ground truth in different imread flag combinations Mat gt_0, gt_1, gt_2, gt_3, gt_256, gt_258; // Handle grayscale 8-bit and 16-bit images if (gt.channels() == 1) { gt.copyTo(gt_2); // For IMREAD_ANYDEPTH if (gt.depth() == CV_16U) gt_2.convertTo(gt_0, CV_8U, 1. / 256); else gt_0 = gt_2; // For IMREAD_GRAYSCALE cvtColor(gt_2, gt_3, COLOR_GRAY2BGR); // For IMREAD_COLOR | IMREAD_ANYDEPTH if (gt.depth() == CV_16U) gt_3.convertTo(gt_1, CV_8U, 1. / 256); else gt_1 = gt_3; // For IMREAD_COLOR gt_256 = gt_1; // For IMREAD_COLOR_RGB gt_258 = gt_3; // For IMREAD_COLOR_RGB | IMREAD_ANYDEPTH } // Handle color images (3 or 4 channels) with 8-bit and 16-bit depth if (gt.channels() > 1) { // Convert to grayscale cvtColor(gt, gt_2, COLOR_BGRA2GRAY); if (gt.depth() == CV_16U) gt_2.convertTo(gt_0, CV_8U, 1. / 256); else gt_0 = gt_2; // Convert to 3-channel BGR if (gt.channels() == 3) gt.copyTo(gt_3); else cvtColor(gt, gt_3, COLOR_BGRA2BGR); if (gt.depth() == CV_16U) gt_3.convertTo(gt_1, CV_8U, 1. / 256); else gt_1 = gt_3; // Convert to RGB for IMREAD_COLOR_RGB variants cvtColor(gt_1, gt_256, COLOR_BGR2RGB); cvtColor(gt_3, gt_258, COLOR_BGR2RGB); } // Perform comparisons with different imread flags EXPECT_PRED_FORMAT2(cvtest::MatComparator(1, 0), imread(filename, IMREAD_GRAYSCALE), gt_0); EXPECT_PRED_FORMAT2(cvtest::MatComparator(1, 0), imread(filename, IMREAD_COLOR), gt_1); EXPECT_PRED_FORMAT2(cvtest::MatComparator(4, 0), imread(filename, IMREAD_ANYDEPTH), gt_2); EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), imread(filename, IMREAD_COLOR | IMREAD_ANYDEPTH), gt_3); EXPECT_PRED_FORMAT2(cvtest::MatComparator(1, 0), imread(filename, IMREAD_COLOR_RGB), gt_256); EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), imread(filename, IMREAD_COLOR_RGB | IMREAD_ANYDEPTH), gt_258); // Uncomment this block to write out the decoded images for visual/manual inspection // or for regenerating expected ground truth PNGs (for example, after changing decoder logic). #if 0 imwrite(filename + "_0.png", imread(filename, IMREAD_GRAYSCALE)); imwrite(filename + "_1.png", imread(filename, IMREAD_COLOR)); imwrite(filename + "_2.png", imread(filename, IMREAD_ANYDEPTH)); imwrite(filename + "_3.png", imread(filename, IMREAD_COLOR | IMREAD_ANYDEPTH)); imwrite(filename + "_256.png", imread(filename, IMREAD_COLOR_RGB)); imwrite(filename + "_258.png", imread(filename, IMREAD_COLOR_RGB | IMREAD_ANYDEPTH)); #endif // Uncomment this block to verify that saved images (from above) load identically // when read back with IMREAD_UNCHANGED. Helps ensure write-read symmetry. #if 0 EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), imread(filename, IMREAD_GRAYSCALE), imread(filename + "_0.png", IMREAD_UNCHANGED)); EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), imread(filename, IMREAD_COLOR), imread(filename + "_1.png", IMREAD_UNCHANGED)); EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), imread(filename, IMREAD_ANYDEPTH), imread(filename + "_2.png", IMREAD_UNCHANGED)); EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), imread(filename, IMREAD_COLOR | IMREAD_ANYDEPTH), imread(filename + "_3.png", IMREAD_UNCHANGED)); EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), imread(filename, IMREAD_COLOR_RGB), imread(filename + "_256.png", IMREAD_UNCHANGED)); EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), imread(filename, IMREAD_COLOR_RGB | IMREAD_ANYDEPTH), imread(filename + "_258.png", IMREAD_UNCHANGED)); #endif } const string pngsuite_files[] = { "basi0g01", "basi0g02", "basi0g04", "basi0g08", "basi0g16", "basi2c08", "basi2c16", "basi3p01", "basi3p02", "basi3p04", "basi3p08", "basi4a08", "basi4a16", "basi6a08", "basi6a16", "basn0g01", "basn0g02", "basn0g04", "basn0g08", "basn0g16", "basn2c08", "basn2c16", "basn3p01", "basn3p02", "basn3p04", "basn3p08", "basn4a08", "basn4a16", "basn6a08", "basn6a16", "bgai4a08", "bgai4a16", "bgan6a08", "bgan6a16", "bgbn4a08", "bggn4a16", "bgwn6a08", "bgyn6a16", "ccwn2c08", "ccwn3p08", "cdfn2c08", "cdhn2c08", "cdsn2c08", "cdun2c08", "ch1n3p04", "ch2n3p08", "cm0n0g04", "cm7n0g04", "cm9n0g04", "cs3n2c16", "cs3n3p08", "cs5n2c08", "cs5n3p08", "cs8n2c08", "cs8n3p08", "ct0n0g04", "ct1n0g04", "cten0g04", "ctfn0g04", "ctgn0g04", "cthn0g04", "ctjn0g04", "ctzn0g04", "exif2c08", "f00n0g08", "f00n2c08", "f01n0g08", "f01n2c08", "f02n0g08", "f02n2c08", "f03n0g08", "f03n2c08", "f04n0g08", "f04n2c08", "f99n0g04", "g03n0g16", "g04n0g16", "g05n0g16", "g07n0g16", "g10n0g16", "g10n2c08", "g10n3p04", "g25n0g16", "oi1n0g16", "oi1n2c16", "oi2n0g16", "oi2n2c16", "oi4n0g16", "oi4n2c16", "oi9n0g16", "oi9n2c16", "pp0n2c16", "pp0n6a08", "ps1n0g08", "ps1n2c16", "ps2n0g08", "ps2n2c16", "s01i3p01", "s01n3p01", "s02i3p01", "s02n3p01", "s03i3p01", "s03n3p01", "s04i3p01", "s04n3p01", "s05i3p02", "s05n3p02", "s06i3p02", "s06n3p02", "s07i3p02", "s07n3p02", "s08i3p02", "s08n3p02", "s09i3p02", "s09n3p02", "s32i3p04", "s32n3p04", "s33i3p04", "s33n3p04", "s34i3p04", "s34n3p04", "s35i3p04", "s35n3p04", "s36i3p04", "s36n3p04", "s37i3p04", "s37n3p04", "s38i3p04", "s38n3p04", "s39i3p04", "s39n3p04", "s40i3p04", "s40n3p04", "tbbn0g04", "tbbn2c16", "tbbn3p08", "tbgn2c16", "tbgn3p08", "tbrn2c08", "tbwn0g16", "tbwn3p08", "tbyn3p08", "tm3n3p02", "tp0n0g08", "tp0n2c08", "tp0n3p08", "tp1n3p08", "z00n2c08", "z03n2c08", "z06n2c08", "z09n2c08", }; INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Png_PngSuite, testing::ValuesIn(pngsuite_files)); typedef testing::TestWithParam Imgcodecs_Png_PngSuite_Gamma; // Parameterized test for decoding PNG files from the PNGSuite test set TEST_P(Imgcodecs_Png_PngSuite_Gamma, decode) { // Construct full paths for the PNG image and corresponding ground truth XML file const string root = cvtest::TS::ptr()->get_data_path(); const string filename = root + "pngsuite/" + GetParam() + ".png"; const string xml_filename = root + "pngsuite/" + GetParam() + ".xml"; // Load the XML file containing the ground truth data FileStorage fs(xml_filename, FileStorage::READ); ASSERT_TRUE(fs.isOpened()); // Ensure the file was opened successfully // Load the image using IMREAD_UNCHANGED to preserve original format Mat src = imread(filename, IMREAD_UNCHANGED); ASSERT_FALSE(src.empty()); // Ensure the image was loaded successfully // Load the ground truth matrix from XML Mat gt; fs.getFirstTopLevelNode() >> gt; // Compare the image loaded with IMREAD_UNCHANGED to the ground truth EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), src, gt); } const string pngsuite_files_gamma[] = { "g03n2c08", "g03n3p04", "g04n2c08", "g04n3p04", "g05n2c08", "g05n3p04", "g07n2c08", "g07n3p04", "g25n2c08", "g25n3p04" }; INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Png_PngSuite_Gamma, testing::ValuesIn(pngsuite_files_gamma)); typedef testing::TestWithParam Imgcodecs_Png_PngSuite_Corrupted; TEST_P(Imgcodecs_Png_PngSuite_Corrupted, decode) { const string root = cvtest::TS::ptr()->get_data_path(); const string filename = root + "pngsuite/" + GetParam() + ".png"; Mat src = imread(filename, IMREAD_UNCHANGED); // Corrupted files should not be read EXPECT_TRUE(src.empty()); } const string pngsuite_files_corrupted[] = { "xc1n0g08", "xc9n2c08", "xcrn0g04", "xcsn0g01", "xd0n2c08", "xd3n2c08", "xd9n2c08", "xdtn0g01", "xhdn0g08", "xlfn0g04", "xs1n0g01", "xs2n0g01", "xs4n0g01", "xs7n0g01", }; INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Png_PngSuite_Corrupted, testing::ValuesIn(pngsuite_files_corrupted)); CV_ENUM(PNGStrategy, IMWRITE_PNG_STRATEGY_DEFAULT, IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY, IMWRITE_PNG_STRATEGY_RLE, IMWRITE_PNG_STRATEGY_FIXED); CV_ENUM(PNGFilters, IMWRITE_PNG_FILTER_NONE, IMWRITE_PNG_FILTER_SUB, IMWRITE_PNG_FILTER_UP, IMWRITE_PNG_FILTER_AVG, IMWRITE_PNG_FILTER_PAETH, IMWRITE_PNG_FAST_FILTERS, IMWRITE_PNG_ALL_FILTERS); typedef testing::TestWithParam> Imgcodecs_Png_Encode; TEST_P(Imgcodecs_Png_Encode, params) { const string root = cvtest::TS::ptr()->get_data_path(); const string filename = root + "pngsuite/" + get<0>(GetParam()); const int strategy = get<1>(GetParam()); const int filter = get<2>(GetParam()); const int compression_level = get<3>(GetParam()); std::vector file_buf; readFileBytes(filename, file_buf); Mat src = imdecode(file_buf, IMREAD_UNCHANGED); EXPECT_FALSE(src.empty()) << "Cannot decode test image " << filename; vector buf; imencode(".png", src, buf, { IMWRITE_PNG_COMPRESSION, compression_level, IMWRITE_PNG_STRATEGY, strategy, IMWRITE_PNG_FILTER, filter }); EXPECT_EQ(buf.size(), file_buf.size()); } INSTANTIATE_TEST_CASE_P(/**/, Imgcodecs_Png_Encode, testing::Values( make_tuple("f00n0g08.png", IMWRITE_PNG_STRATEGY_DEFAULT, IMWRITE_PNG_FILTER_NONE, 6), make_tuple("f00n2c08.png", IMWRITE_PNG_STRATEGY_DEFAULT, IMWRITE_PNG_FILTER_NONE, 6), make_tuple("f01n0g08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_FILTER_SUB, 6), make_tuple("f01n2c08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_FILTER_SUB, 6), make_tuple("f02n0g08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_FILTER_UP, 6), make_tuple("f02n2c08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_FILTER_UP, 6), make_tuple("f03n0g08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_FILTER_AVG, 6), make_tuple("f03n2c08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_FILTER_AVG, 6), make_tuple("f04n0g08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_FILTER_PAETH, 6), make_tuple("f04n2c08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_FILTER_PAETH, 6), make_tuple("z03n2c08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_ALL_FILTERS, 3), make_tuple("z06n2c08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_ALL_FILTERS, 6), make_tuple("z09n2c08.png", IMWRITE_PNG_STRATEGY_FILTERED, IMWRITE_PNG_ALL_FILTERS, 9))); typedef testing::TestWithParam> Imgcodecs_Png_ImwriteFlags; TEST_P(Imgcodecs_Png_ImwriteFlags, compression_level) { const string root = cvtest::TS::ptr()->get_data_path(); const string filename = root + get<0>(GetParam()); const int compression_level = get<1>(GetParam()); const size_t compression_level_output_size = get<2>(GetParam()); Mat src = imread(filename, IMREAD_UNCHANGED); EXPECT_FALSE(src.empty()) << "Cannot read test image " << filename; vector buf; imencode(".png", src, buf, { IMWRITE_PNG_COMPRESSION, compression_level }); EXPECT_EQ(buf.size(), compression_level_output_size); } INSTANTIATE_TEST_CASE_P(/**/, Imgcodecs_Png_ImwriteFlags, testing::Values( make_tuple("../perf/512x512.png", 0, 788279), make_tuple("../perf/512x512.png", 1, 179503), make_tuple("../perf/512x512.png", 2, 176007), make_tuple("../perf/512x512.png", 3, 170497), make_tuple("../perf/512x512.png", 4, 163357), make_tuple("../perf/512x512.png", 5, 159190), make_tuple("../perf/512x512.png", 6, 156621), make_tuple("../perf/512x512.png", 7, 155696), make_tuple("../perf/512x512.png", 8, 153708), make_tuple("../perf/512x512.png", 9, 152181))); // See https://github.com/opencv/opencv/issues/27614 typedef testing::TestWithParam Imgcodecs_Png_ZLIBBUFFER_SIZE; TEST_P(Imgcodecs_Png_ZLIBBUFFER_SIZE, encode_regression_27614) { Mat img(320,240,CV_8UC3,cv::Scalar(64,76,43)); vector buff; bool status = false; ASSERT_NO_THROW(status = imencode(".png", img, buff, { IMWRITE_PNG_ZLIBBUFFER_SIZE, GetParam() })); ASSERT_TRUE(status); } INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Png_ZLIBBUFFER_SIZE, testing::Values(5, 6, // Minimum limit 8192, // Default value 131072, // 128 KiB 262144, // 256 KiB 1048576, // Maximum limit 1048577)); #endif // HAVE_PNG }} // namespace