Worldstone
 All Classes Files Functions Variables Enumerations Enumerator Macros Pages
ImageViewTests.cpp
Go to the documentation of this file.
1 
6 #include <Platform.h>
7 #include <SystemUtils.h>
8 #include <doctest.h>
9 #include "ImageView.h"
10 
11 using WorldStone::Vector;
14 
15 static_assert(std::is_copy_constructible<ImageView<uint8_t>>::value,
16  "Image view copy must be possible");
17 static_assert(std::is_copy_assignable<ImageView<uint8_t>>::value,
18  "Image view copy must be possible");
19 static_assert(std::is_convertible<ImageView<uint8_t>, ImageView<const uint8_t>>::value,
20  "Must be able to convert to an ImageView to an ImageView of const values.");
21 
22 static_assert(std::is_assignable<decltype(ImageView<uint8_t>().operator()(0, 0)), uint8_t>::value,
23  "Must be able to assign values using operator()(size_t,size_t)");
24 
26 static_assert(
27  !std::is_assignable<decltype(ImmutableImageView().operator()(0, 0)), uint8_t>::value,
28  "Must not be able to assign using operator()(size_t,size_t) on an ImageView<const Color>");
29 
30 TEST_CASE("ImageView")
31 {
32  const size_t size = 10_z;
33  const uint8_t initColor = 0;
34  Vector<uint8_t> buffer(size * size, initColor);
35  SUBCASE("Using a valid view")
36  {
37  ImageView<uint8_t> view;
38  CHECK(!view.isValid());
39 
40  CHECK(view.buffer == nullptr);
41  view.buffer = buffer.data();
42  CHECK(!view.isValid());
43 
44  CHECK(view.width == 0);
45  view.width = size;
46  CHECK(!view.isValid());
47 
48  CHECK(view.height == 0);
49  view.height = size;
50  CHECK(!view.isValid());
51 
52  CHECK(view.stride == 0);
53  view.stride = view.width;
54  CHECK(view.isValid());
55 
56  CHECK(view == ImageView<uint8_t>{buffer.data(), size, size, size});
57  CHECK(view != ImageView<uint8_t>{});
58 
59  for (int x = 0; x < size; x++)
60  {
61  for (int y = 0; y < size; y++)
62  {
63  CHECK(view(x, y) == initColor);
64  }
65  }
66  const uint8_t testColor = 5;
67  view(0, 0) = testColor;
68  CHECK(buffer[0] == testColor);
69  CHECK(view(0, 0) == testColor);
70  view(0, 1) = testColor;
71  CHECK(buffer[0 + 1 * size] == testColor);
72  CHECK(view(0, 1) == testColor);
73 
74  const ImageView<const uint8_t> viewOnConst = view;
75  CHECK(viewOnConst(0, 1) == testColor);
76  }
77  SUBCASE("Check invalid views")
78  {
79  ImageView<uint8_t> view;
80  CHECK(!view.isValid());
81  // Invalid when any of the fields is null
82  view = {nullptr, size, size, size};
83  CHECK(!view.isValid());
84  view = {buffer.data(), 0, size, size};
85  CHECK(!view.isValid());
86  view = {buffer.data(), size, 0, size};
87  CHECK(!view.isValid());
88  view = {buffer.data(), size, size, 0};
89  CHECK(!view.isValid());
90  // Invalid if stride is more than width
91  view = {buffer.data(), size + 1, size, size};
92  CHECK(!view.isValid());
93  }
94 }
95 
96 TEST_CASE("SimpleImageViewProvider")
97 {
98  SimpleImageProvider<uint8_t> imageProvider;
99  CHECK(imageProvider.getImagesNumber() == 0);
100  SUBCASE("Asking for an image of valid dimensions")
101  {
102  ImageView<uint8_t> newImageView = imageProvider.getNewImage(256, 128);
103  CHECK(newImageView.isValid());
104  CHECK(newImageView.width == 256);
105  CHECK(newImageView.height == 128);
106  REQUIRE(imageProvider.getImagesNumber() == 1);
107  CHECK(imageProvider.getImage(0) == newImageView);
108  newImageView = imageProvider.getNewImage(1024, 2048);
109  CHECK(newImageView.width == 1024);
110  CHECK(newImageView.height == 2048);
111  REQUIRE(imageProvider.getImagesNumber() == 2);
112 
113  // Make sure we can move data from the provider
114  Vector<uint8_t> imageBuffer = imageProvider.moveImageBuffer(1);
115  CHECK(imageBuffer.size() >= newImageView.width * newImageView.height);
116  CHECK(imageBuffer.data() == newImageView.buffer);
117  // Make sure that the views returned after moving are not valid anymore
118  if (imageProvider.getImagesNumber() == 2) {
119  CHECK(!imageProvider.getImage(1).isValid());
120  }
121  }
122  SUBCASE("Asking for an image of invalid dimensions returns invalid ImageView")
123  {
124  ImageView<uint8_t> invalidImageView = imageProvider.getNewImage(256, 0);
125  CHECK(!invalidImageView.isValid());
126  invalidImageView = imageProvider.getNewImage(0, 256);
127  CHECK(!invalidImageView.isValid());
128  CHECK(imageProvider.getImagesNumber() == 0);
129  }
130 }
Color * buffer
Pointer to the memory considered as the first pixel.
Definition: ImageView.h:28
size_t stride
Actual width of the buffer scanlines.
Definition: ImageView.h:31
bool isValid() const
Checks if the view seems to be valid based on its characteristics.
Definition: ImageView.h:41
size_t width
Width of the image, can be dfferent from the one of the buffer.
Definition: ImageView.h:29
size_t getImagesNumber() const
Definition: ImageView.h:165
Vector< Color > moveImageBuffer(size_t imageIndex)
Move an image buffer out of the provider.
Definition: ImageView.h:184
A simple image provider that allocates a new buffer for each call to getNewImage() ...
Definition: ImageView.h:140
ImageView< Color > getImage(size_t imageIndex)
Definition: ImageView.h:168
A view on an image buffer of type Color.
Definition: ImageView.h:25
size_t height
Number of scanlines of the image.
Definition: ImageView.h:30
TEST_CASE("DCC decoding BaalSpirit.dcc")
Try to decode BaalSpirit.dcc.
Implements image manipulation helpers.
ImageView< Color > getNewImage(size_t width, size_t height) override
Allocates a new Image of dimensions width * height.
Definition: ImageView.h:156
Platform specific tools and macros.