odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

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