Added tests for image reading
This commit is contained in:
parent
f279ffb50f
commit
eb4fc0e964
@ -6,7 +6,7 @@ using namespace Leonetienne::BmpPP;
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
||||||
/*
|
|
||||||
BMP bmp({800, 600}, Colormode::RGB);
|
BMP bmp({800, 600}, Colormode::RGB);
|
||||||
|
|
||||||
for (int x = 0; x < 800; x++)
|
for (int x = 0; x < 800; x++)
|
||||||
@ -20,7 +20,9 @@ int main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
bmp.Write("write.bmp");
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
BMP bmp;
|
BMP bmp;
|
||||||
|
|
||||||
@ -32,7 +34,7 @@ int main() {
|
|||||||
if (!bmp.Write("testwrite.bmp"))
|
if (!bmp.Write("testwrite.bmp"))
|
||||||
std::cerr << "What the hell" << std::endl;
|
std::cerr << "What the hell" << std::endl;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define BMPPP_BMP_H
|
#define BMPPP_BMP_H
|
||||||
|
|
||||||
#include <Eule/Vector2.h>
|
#include <Eule/Vector2.h>
|
||||||
|
#include <Eule/Rect.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "Colormodes.h"
|
#include "Colormodes.h"
|
||||||
@ -87,6 +88,9 @@ namespace Leonetienne::BmpPP {
|
|||||||
//! Will swap two channels. Useful for, for example, easy BGR to RGB conversion.
|
//! Will swap two channels. Useful for, for example, easy BGR to RGB conversion.
|
||||||
void SwapChannels(const std::size_t& channel1, const std::size_t& channel2);
|
void SwapChannels(const std::size_t& channel1, const std::size_t& channel2);
|
||||||
|
|
||||||
|
//! Will copy the specified rectangle-area, and return it as a new image
|
||||||
|
BMP Crop(const Eule::Rect& area);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Eule::Vector2i size;
|
Eule::Vector2i size;
|
||||||
Colormode colormode;
|
Colormode colormode;
|
||||||
|
@ -21,4 +21,12 @@ add_executable(Test
|
|||||||
BmpHeader.cpp
|
BmpHeader.cpp
|
||||||
ReInitialize.cpp
|
ReInitialize.cpp
|
||||||
Uninitialized.cpp
|
Uninitialized.cpp
|
||||||
|
Read.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Move test images to build dir
|
||||||
|
ADD_CUSTOM_COMMAND(
|
||||||
|
TARGET ${PROJECT_NAME} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
${CMAKE_SOURCE_DIR}/TestAssets/ $<TARGET_FILE_DIR:${PROJECT_NAME}>
|
||||||
)
|
)
|
||||||
|
131
Test/Read.cpp
Normal file
131
Test/Read.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include <Bmp.h>
|
||||||
|
#include "Catch2.h"
|
||||||
|
#include <tuple>
|
||||||
|
#include <Eule/Math.h>
|
||||||
|
|
||||||
|
using namespace Leonetienne::BmpPP;
|
||||||
|
using namespace Eule;
|
||||||
|
|
||||||
|
#define IMSIZE Vector2i(800, 600)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
inline std::tuple<std::uint8_t, std::uint8_t, std::uint8_t, std::uint8_t>
|
||||||
|
ColorGradient(const Vector2i& pos)
|
||||||
|
{
|
||||||
|
std::uint8_t r, g, b, a;
|
||||||
|
|
||||||
|
// This assumes IMSIZE.x >= IMSIZE.y
|
||||||
|
|
||||||
|
r = ((float)pos.x / (float)IMSIZE.x) * 255.0f;
|
||||||
|
g = (1.0f - (float)pos.x / (float)IMSIZE.x) * 255.0f;
|
||||||
|
b = (1.0f - (float)pos.y / (float)IMSIZE.x) * 255.0f;
|
||||||
|
a = Math::Clamp(((float)pos.y / (float)IMSIZE.x) * 2 * 255.0f, 0.0, 255.0);
|
||||||
|
|
||||||
|
return std::make_tuple(r, g, b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that reading an image works at all, without throwing an exception or crashing the program
|
||||||
|
TEST_CASE(__FILE__"/ReadingDoesntCrash", "[Read]")
|
||||||
|
{
|
||||||
|
SECTION("RGB image with BITMAPV5HEADER") {
|
||||||
|
// Read RGB gradient image
|
||||||
|
BMP bmp("base_gradient.bmp");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("RGBA image with BITMAPV5HEADER") {
|
||||||
|
// Read RGBA gradient image
|
||||||
|
BMP bmp("basea_gradient.bmp");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that an image is initialized after being read
|
||||||
|
TEST_CASE(__FILE__"/InitializedAfterReading", "[Read]")
|
||||||
|
{
|
||||||
|
// Read RGB gradient image
|
||||||
|
BMP bmp("base_gradient.bmp");
|
||||||
|
|
||||||
|
REQUIRE(bmp.IsInitialized());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that images read the correct metadata (bit depth and resolution)
|
||||||
|
TEST_CASE(__FILE__"/MetadataIsCorrect", "[Read]")
|
||||||
|
{
|
||||||
|
// Read RGB gradient image
|
||||||
|
SECTION("RGB image with BITMAPV5HEADER") {
|
||||||
|
// Read RGB gradient image
|
||||||
|
BMP bmp("base_gradient.bmp");
|
||||||
|
|
||||||
|
REQUIRE(bmp.GetDimensions() == IMSIZE);
|
||||||
|
REQUIRE(bmp.GetColormode() == Colormode::RGB);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("RGBA image with BITMAPV5HEADER") {
|
||||||
|
// Read RGBA gradient image
|
||||||
|
BMP bmp("basea_gradient.bmp");
|
||||||
|
|
||||||
|
REQUIRE(bmp.GetDimensions() == IMSIZE);
|
||||||
|
REQUIRE(bmp.GetColormode() == Colormode::RGBA);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that reading an image works, by comparing the resulting pixel
|
||||||
|
// values with the algorithm that created them
|
||||||
|
TEST_CASE(__FILE__"/CompareRGB", "[Read]")
|
||||||
|
{
|
||||||
|
// Read RGB gradient image
|
||||||
|
BMP bmp("base_gradient.bmp");
|
||||||
|
|
||||||
|
// Compare each pixel to the algorithm that has once created it
|
||||||
|
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
|
||||||
|
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
|
||||||
|
|
||||||
|
const auto expected_pixel_values = ColorGradient(Vector2i(x, y));
|
||||||
|
const uint8_t* pxBase = bmp.GetPixel(Vector2i(x, y));
|
||||||
|
const auto actual_pixel_values =
|
||||||
|
std::make_tuple(
|
||||||
|
*(pxBase + 0),
|
||||||
|
*(pxBase + 1),
|
||||||
|
*(pxBase + 2),
|
||||||
|
std::get<3>(expected_pixel_values) // Since our image doesn't contain an ALPHA channel, let's copy it from the expected value
|
||||||
|
);
|
||||||
|
|
||||||
|
REQUIRE(actual_pixel_values == expected_pixel_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that reading an image works, by comparing the resulting pixel
|
||||||
|
// values with the algorithm that created them
|
||||||
|
TEST_CASE(__FILE__"/CompareRGBA", "[Read]")
|
||||||
|
{
|
||||||
|
// Read RGBA gradient image
|
||||||
|
BMP bmp("basea_gradient.bmp");
|
||||||
|
|
||||||
|
// Compare each pixel to the algorithm that has once created it
|
||||||
|
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
|
||||||
|
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
|
||||||
|
|
||||||
|
const auto expected_pixel_values = ColorGradient(Vector2i(x, y));
|
||||||
|
const uint8_t* pxBase = bmp.GetPixel(Vector2i(x, y));
|
||||||
|
const auto actual_pixel_values =
|
||||||
|
std::make_tuple(
|
||||||
|
*(pxBase + 0),
|
||||||
|
*(pxBase + 1),
|
||||||
|
*(pxBase + 2),
|
||||||
|
*(pxBase + 3)
|
||||||
|
);
|
||||||
|
|
||||||
|
REQUIRE(actual_pixel_values == expected_pixel_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#undef IMSIZE
|
2
Test/TestAssets/.gitignore
vendored
Normal file
2
Test/TestAssets/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Allow images used for tests
|
||||||
|
!*.bmp
|
BIN
Test/TestAssets/base_complex.bmp
Normal file
BIN
Test/TestAssets/base_complex.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 768 KiB |
BIN
Test/TestAssets/base_gradient.bmp
Normal file
BIN
Test/TestAssets/base_gradient.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
BIN
Test/TestAssets/basea_complex.bmp
Normal file
BIN
Test/TestAssets/basea_complex.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 MiB |
BIN
Test/TestAssets/basea_gradient.bmp
Normal file
BIN
Test/TestAssets/basea_gradient.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 MiB |
1
Test/TestAssets/readme.md
Normal file
1
Test/TestAssets/readme.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
base*.bmp is always RGB, basea*.bmp is always RGBA.
|
@ -3,6 +3,7 @@
|
|||||||
#include "Catch2.h"
|
#include "Catch2.h"
|
||||||
|
|
||||||
using namespace Leonetienne::BmpPP;
|
using namespace Leonetienne::BmpPP;
|
||||||
|
using namespace Eule;
|
||||||
|
|
||||||
// Tests that trying to interrogate any getter/Write() on an uninitialized image results in a runtime error
|
// Tests that trying to interrogate any getter/Write() on an uninitialized image results in a runtime error
|
||||||
TEST_CASE(__FILE__"/RuntimeErrorOnUninitialized", "[Uninitialized]")
|
TEST_CASE(__FILE__"/RuntimeErrorOnUninitialized", "[Uninitialized]")
|
||||||
@ -65,7 +66,7 @@ TEST_CASE(__FILE__"/UninitializedImageIsUninitialized", "[Uninitialized]")
|
|||||||
// Tests that an image constructed via dimensions is initialized
|
// Tests that an image constructed via dimensions is initialized
|
||||||
TEST_CASE(__FILE__"/ConstructedByDimensionsIsInitialized", "[Uninitialized]")
|
TEST_CASE(__FILE__"/ConstructedByDimensionsIsInitialized", "[Uninitialized]")
|
||||||
{
|
{
|
||||||
BMP bmp({800, 600});
|
BMP bmp(Vector2i(800, 600));
|
||||||
REQUIRE(bmp.IsInitialized());
|
REQUIRE(bmp.IsInitialized());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user