libs/core/src/eu/core/image.cc
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "eu/core/image.h" | ||
| 2 | |||
| 3 | #include "eu/assert/assert.h" | ||
| 4 | |||
| 5 | namespace eu::core | ||
| 6 | { | ||
| 7 | |||
| 8 | |||
| 9 | |||
| 10 | ✗ | Image::Image() = default; | |
| 11 | |||
| 12 | ✗ | std::size_t bytes_from_size(int width, int height, int bpp) | |
| 13 | { | ||
| 14 | ✗ | return sizet_from_int(width) * sizet_from_int(height) * sizet_from_int(bpp); | |
| 15 | } | ||
| 16 | |||
| 17 | ✗ | bool Image::is_valid() const | |
| 18 | { | ||
| 19 | ✗ | return width > 0 && height > 0 && data.size() == bytes_from_size(width, height, 4); | |
| 20 | } | ||
| 21 | |||
| 22 | |||
| 23 | |||
| 24 | ✗ | void Image::setup_with_alpha_support(int w, int h) | |
| 25 | { | ||
| 26 | ✗ | width = w; | |
| 27 | ✗ | height = h; | |
| 28 | ✗ | data.resize(bytes_from_size(width, height, 4), 0); | |
| 29 | ✗ | } | |
| 30 | |||
| 31 | |||
| 32 | |||
| 33 | ✗ | void Image::make_invalid() | |
| 34 | { | ||
| 35 | ✗ | width = 0; | |
| 36 | ✗ | height = 0; | |
| 37 | ✗ | data.clear(); | |
| 38 | ✗ | } | |
| 39 | |||
| 40 | |||
| 41 | |||
| 42 | ✗ | void Image::set_pixel(int x, int y, int r, unsigned char g, unsigned char b, unsigned char a) | |
| 43 | { | ||
| 44 | ✗ | const int index = (y * width + x) * 4; | |
| 45 | ✗ | data[index + 0] = r; | |
| 46 | ✗ | data[index + 1] = g; | |
| 47 | ✗ | data[index + 2] = b; | |
| 48 | ✗ | data[index + 3] = a; | |
| 49 | ✗ | } | |
| 50 | |||
| 51 | ✗ | void Image::set_pixel(int x, int y, const PixelColor& color) | |
| 52 | { | ||
| 53 | ✗ | set_pixel(x, y, color.r, color.g, color.b, color.a); | |
| 54 | ✗ | } | |
| 55 | |||
| 56 | |||
| 57 | ✗ | PixelColor Image::get_pixel(int x, int y) const | |
| 58 | { | ||
| 59 | ✗ | ASSERTX(x >= 0 && x < width && y >= 0 && y < height, x, y, width, height); | |
| 60 | ✗ | const auto index = (y * width + x) * 4; | |
| 61 | return { | ||
| 62 | ✗ | .r = data[index + 0], | |
| 63 | ✗ | .g = data[index + 1], | |
| 64 | ✗ | .b = data[index + 2], | |
| 65 | ✗ | .a = data[index + 3] | |
| 66 | ✗ | }; | |
| 67 | ✗ | } | |
| 68 | |||
| 69 | |||
| 70 | |||
| 71 | ✗ | void paste_image(Image* dst, int dst_x, int dst_y, const Image& src) | |
| 72 | { | ||
| 73 | // Assert valid images | ||
| 74 | ✗ | ASSERT(dst != nullptr); | |
| 75 | ✗ | ASSERT(dst->is_valid()); | |
| 76 | ✗ | ASSERT(src.is_valid()); | |
| 77 | |||
| 78 | ✗ | for (int local_y = 0; local_y < src.height; local_y += 1) | |
| 79 | { | ||
| 80 | ✗ | const auto y = dst_y + local_y; | |
| 81 | ✗ | if (y < 0 || y >= dst->height) | |
| 82 | { | ||
| 83 | // if y is outside the destination image, skip the entire horizontal row | ||
| 84 | ✗ | continue; | |
| 85 | } | ||
| 86 | |||
| 87 | ✗ | for (int local_x = 0; local_x < src.width; local_x += 1) | |
| 88 | { | ||
| 89 | ✗ | const auto x = dst_x + local_x; | |
| 90 | ✗ | if (x < 0 || x >= dst->width) | |
| 91 | { | ||
| 92 | // if x is outside the destination image, skip this pixel | ||
| 93 | ✗ | continue; | |
| 94 | } | ||
| 95 | |||
| 96 | ✗ | const auto src_color = src.get_pixel(local_x, local_y); | |
| 97 | ✗ | dst->set_pixel(x, y, src_color); | |
| 98 | } | ||
| 99 | } | ||
| 100 | ✗ | } | |
| 101 | |||
| 102 | |||
| 103 | } | ||
| 104 |