Added implementation of Rotation methods, and tests

This commit is contained in:
Leonetienne 2022-03-06 14:51:01 +01:00
parent 046a694dc4
commit 316ddc4a24
7 changed files with 142 additions and 0 deletions

View File

@ -293,6 +293,93 @@ namespace Leonetienne::BmpPP {
return bmp;
}
BMP BMP::Rotate90degClockwise() const {
CHECK_IF_INITIALIZED
// Create a new image matching this ones metadata, but with width and height flipped
BMP bmp(Eule::Vector2i(size.y, size.x), colormode);
// Now copy over the pixels, rotating it by 90 deg
const std::size_t numChannels = GetNumChannels();
for (std::size_t y = 0; y < size.y; y++) {
for (std::size_t x = 0; x < size.x; x++) {
const std::size_t pixelIndex = (y * size.x + x) * numChannels;
const std::size_t rotatedPixelIndex = (x * size.y + (size.y - 1 - y)) * numChannels;
// Copy over the whole pixel
std::copy(
pixelBuffer.cbegin() + pixelIndex,
pixelBuffer.cbegin() + pixelIndex + numChannels,
bmp.pixelBuffer.begin() + rotatedPixelIndex
);
}
}
// return it
return bmp;
}
BMP BMP::Rotate90degCounterclockwise() const {
CHECK_IF_INITIALIZED
// Create a new image matching this ones metadata, but with width and height flipped
BMP bmp(Eule::Vector2i(size.y, size.x), colormode);
// Now copy over the pixels, rotating it by -90 deg
const std::size_t numChannels = GetNumChannels();
for (std::size_t y = 0; y < size.y; y++) {
for (std::size_t x = 0; x < size.x; x++) {
const std::size_t pixelIndex = (y * size.x + x) * numChannels;
const std::size_t rotatedPixelIndex = ((size.x - 1 - x) * size.y + y) * numChannels;
// Copy over the whole pixel
std::copy(
pixelBuffer.cbegin() + pixelIndex,
pixelBuffer.cbegin() + pixelIndex + numChannels,
bmp.pixelBuffer.begin() + rotatedPixelIndex
);
}
}
// return it
return bmp;
}
BMP BMP::Rotate180deg() const {
CHECK_IF_INITIALIZED
// Basically, what we're doing here, is mirroring
// the image horizontally and vertically at the same time
// Create a new image matching this's metadata
BMP bmp(size, colormode);
// Now copy over the pixels, mirroring it horizontally and vertically
const std::size_t numChannels = GetNumChannels();
const std::size_t rowLength = size.x * numChannels;
for (std::size_t y = 0; y < size.y; y++) {
const std::size_t rowIndex = y * rowLength;
const std::size_t flippedRowIndex = (size.y - 1 - y) * rowLength;
for (std::size_t x = 0; x < size.x; x++) {
const std::size_t pixelIndex = rowIndex + x * numChannels;
const std::size_t rotatedPixelIndex = flippedRowIndex + (size.x - 1 - x) * numChannels;
// Copy over the whole pixel
std::copy(
pixelBuffer.cbegin() + pixelIndex,
pixelBuffer.cbegin() + pixelIndex + numChannels,
bmp.pixelBuffer.begin() + rotatedPixelIndex
);
}
}
// return it
return bmp;
}
}
#undef CHECK_IF_INITIALIZED

View File

@ -28,6 +28,7 @@ add_executable(Test
MirrorHorizontally.cpp
MirrorVertically.cpp
SwapChannels.cpp
Rotate.cpp
)
# Move test images to build dir

54
Test/Rotate.cpp Normal file
View File

@ -0,0 +1,54 @@
#include <Bmp.h>
#include <stdexcept>
#include "Catch2.h"
using namespace Leonetienne::BmpPP;
using namespace Eule;
// Tests that rotating works
TEST_CASE(__FILE__"/Mirroring produces the correct results", "[Rotate]")
{
SECTION("90deg clockwise") {
// Read an image
BMP bmp("base_mateya.bmp");
// Rotate it
bmp = bmp.Rotate90degClockwise();
// Read reference image
const BMP reference("base_mateya_rot_90deg.bmp");
// Assert that they are equal
REQUIRE(bmp == reference);
}
SECTION("90deg counterclockwise") {
// Read an image
BMP bmp("base_mateya.bmp");
// Rotate it
bmp = bmp.Rotate90degCounterclockwise();
// Read reference image
const BMP reference("base_mateya_rot_270deg.bmp");
// Assert that they are equal
REQUIRE(bmp == reference);
}
SECTION("180deg") {
// Read an image
BMP bmp("base_mateya.bmp");
// Rotate it
bmp = bmp.Rotate180deg();
// Read reference image
const BMP reference("base_mateya_rot_180deg.bmp");
// Assert that they are equal
REQUIRE(bmp == reference);
}
return;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB