codec_test.cpp (5902B)
1 // This file is part of Blend2D project <https://blend2d.com> 2 // 3 // See blend2d.h or LICENSE.md for license and copyright information 4 // SPDX-License-Identifier: Zlib 5 6 #include "../api-build_test_p.h" 7 #if defined(BL_TEST) 8 9 #include "../array.h" 10 #include "../context.h" 11 #include "../image.h" 12 #include "../imagecodec.h" 13 #include "../imagedecoder.h" 14 #include "../imageencoder.h" 15 #include "../random.h" 16 17 #include "../../../testing/commons/imagediff.h" 18 19 // bl::Codecs - Tests 20 // ================== 21 22 namespace bl::Codecs::Tests { 23 24 static void render_simple_image(BLImage& image, BLRandom& rnd, uint32_t cmd_count) noexcept { 25 BLContext ctx(image); 26 ctx.clear_all(); 27 28 double w = image.width(); 29 double h = image.height(); 30 double s = bl_min(w, h); 31 32 for (uint32_t i = 0; i < cmd_count; i++) { 33 uint32_t shape = rnd.next_uint32() & 0x3u; 34 BLRgba32 color = BLRgba32(rnd.next_uint32() | 0xFF000000u); 35 36 ctx.set_fill_style(color); 37 38 switch (shape) { 39 case 0: { 40 double x0 = rnd.next_double() * w; 41 double y0 = rnd.next_double() * h; 42 double x1 = rnd.next_double() * w; 43 double y1 = rnd.next_double() * h; 44 45 double rx = bl_min(x0, x1); 46 double ry = bl_min(y0, y1); 47 double rw = bl_max(x0, x1) - rx; 48 double rh = bl_max(y0, y1) - ry; 49 50 ctx.fill_rect(rx, ry, rw, rh); 51 break; 52 } 53 54 case 1: { 55 double x0 = rnd.next_double() * w; 56 double y0 = rnd.next_double() * h; 57 double x1 = rnd.next_double() * w; 58 double y1 = rnd.next_double() * h; 59 double x2 = rnd.next_double() * w; 60 double y2 = rnd.next_double() * h; 61 62 ctx.fill_triangle(x0, y0, x1, y1, x2, y2); 63 break; 64 } 65 66 case 2: { 67 double cx = rnd.next_double() * w; 68 double cy = rnd.next_double() * h; 69 double r = rnd.next_double() * s; 70 71 ctx.fill_circle(cx, cy, r); 72 break; 73 } 74 75 case 3: { 76 double cx = rnd.next_double() * w; 77 double cy = rnd.next_double() * h; 78 double r = rnd.next_double() * s; 79 double start = rnd.next_double() * 3; 80 double sweep = rnd.next_double() * 6; 81 82 ctx.fill_pie(cx, cy, r, start, sweep); 83 break; 84 } 85 } 86 } 87 } 88 89 struct TestOptions { 90 uint32_t compression_level = 0xFFFFFFFFu; 91 92 BL_INLINE bool has_compression_level() const noexcept { return compression_level != 0xFFFFFFFFu; } 93 }; 94 95 static void test_encoding_decoding_random_images(BLSizeI size, BLFormat fmt, BLImageCodec& codec, BLRandom& rnd, uint32_t test_count, uint32_t cmd_count, const TestOptions& test_options) noexcept { 96 for (uint32_t i = 0; i < test_count; i++) { 97 BLImage image1; 98 99 EXPECT_SUCCESS(image1.create(size.w, size.h, fmt)); 100 render_simple_image(image1, rnd, cmd_count); 101 102 BLImageEncoder encoder; 103 EXPECT_SUCCESS(codec.create_encoder(&encoder)); 104 105 if (test_options.has_compression_level()) { 106 EXPECT_SUCCESS(encoder.set_property("compression", BLVar(test_options.compression_level))); 107 } 108 109 BLArray<uint8_t> encoded_data; 110 encoder.write_frame(encoded_data, image1); 111 112 BLImageDecoder decoder; 113 EXPECT_SUCCESS(codec.create_decoder(&decoder)); 114 115 BLImage image2; 116 EXPECT_SUCCESS(decoder.read_frame(image2, encoded_data)); 117 118 ImageUtils::DiffInfo diff_info = ImageUtils::diff_info(image1, image2); 119 EXPECT_EQ(diff_info.max_diff, 0u); 120 } 121 } 122 123 static constexpr BLSizeI image_codec_test_sizes[] = { 124 { 1, 1 }, 125 { 1, 2 }, 126 { 2, 2 }, 127 { 3, 3 }, 128 { 4, 4 }, 129 { 5, 4 }, 130 { 6, 6 }, 131 { 1, 7 }, 132 { 7, 1 }, 133 { 11, 13 }, 134 { 15, 15 }, 135 { 16, 15 }, 136 { 99, 54 }, 137 { 132, 23 }, 138 { 301, 301 } 139 }; 140 141 UNIT(image_codec_bmp, BL_TEST_GROUP_IMAGE_CODEC_ROUNDTRIP) { 142 static constexpr uint32_t kCmdCount = 10; 143 static constexpr uint32_t kTestCount = 100; 144 145 for (BLSizeI image_size : image_codec_test_sizes) { 146 BLImageCodec codec; 147 EXPECT_SUCCESS(codec.find_by_name("BMP")); 148 149 BLRandom rnd(0x123456789ABCDEFu); 150 TestOptions test_options{}; 151 152 INFO("Testing BMP encoder & decoder with %dx%d images", image_size.w, image_size.h); 153 test_encoding_decoding_random_images(image_size, BL_FORMAT_XRGB32, codec, rnd, kTestCount, kCmdCount, test_options); 154 test_encoding_decoding_random_images(image_size, BL_FORMAT_PRGB32, codec, rnd, kTestCount, kCmdCount, test_options); 155 } 156 } 157 158 UNIT(image_codec_png, BL_TEST_GROUP_IMAGE_CODEC_ROUNDTRIP) { 159 static constexpr uint32_t kCmdCount = 10; 160 static constexpr uint32_t kTestCount = 100; 161 162 for (BLSizeI image_size : image_codec_test_sizes) { 163 INFO("Testing PNG encoder & decoder with %dx%d images", image_size.w, image_size.h); 164 165 BLImageCodec codec; 166 EXPECT_SUCCESS(codec.find_by_name("PNG")); 167 168 BLRandom rnd(0x123456789ABCDEFu); 169 for (uint32_t compression_level = 0; compression_level <= 12; compression_level++) { 170 TestOptions test_options{}; 171 test_options.compression_level = compression_level; 172 173 test_encoding_decoding_random_images(image_size, BL_FORMAT_XRGB32, codec, rnd, kTestCount, kCmdCount, test_options); 174 test_encoding_decoding_random_images(image_size, BL_FORMAT_PRGB32, codec, rnd, kTestCount, kCmdCount, test_options); 175 } 176 } 177 } 178 179 UNIT(image_codec_qoi, BL_TEST_GROUP_IMAGE_CODEC_ROUNDTRIP) { 180 static constexpr uint32_t kCmdCount = 10; 181 static constexpr uint32_t kTestCount = 100; 182 183 for (BLSizeI image_size : image_codec_test_sizes) { 184 BLImageCodec codec; 185 EXPECT_SUCCESS(codec.find_by_name("QOI")); 186 187 BLRandom rnd(0x123456789ABCDEFu); 188 TestOptions test_options{}; 189 190 INFO("Testing QOI encoder & decoder with %dx%d images", image_size.w, image_size.h); 191 test_encoding_decoding_random_images(image_size, BL_FORMAT_XRGB32, codec, rnd, kTestCount, kCmdCount, test_options); 192 test_encoding_decoding_random_images(image_size, BL_FORMAT_PRGB32, codec, rnd, kTestCount, kCmdCount, test_options); 193 } 194 } 195 196 } // {bl::Codecs::Tests} 197 198 #endif // BL_TEST