Added implementatino of color conversion method, and added tests

This commit is contained in:
Leonetienne 2022-03-06 15:47:57 +01:00
parent 32faccf68f
commit 01b3144d6c
5 changed files with 155 additions and 0 deletions

View File

@ -3,6 +3,7 @@
#include <algorithm>
#include "BmpWriter.h"
#include "BmpReader.h"
#include <iostream>
#define CHECK_IF_INITIALIZED if (!isInitialized) throw std::runtime_error("Image not initialized!");
@ -99,6 +100,36 @@ namespace Leonetienne::BmpPP {
return pixelBuffer.data() + pixelIndex;
}
void BMP::SetPixel(const Eule::Vector2i &position,
const std::uint8_t v)
{
CHECK_IF_INITIALIZED
std::uint8_t* pixel = GetPixel(position);
pixel[0] = v;
pixel[1] = v;
pixel[2] = v;
return;
}
void BMP::SetPixel(const Eule::Vector2i &position,
const std::uint8_t r,
const std::uint8_t g,
const std::uint8_t b)
{
CHECK_IF_INITIALIZED
std::uint8_t* pixel = GetPixel(position);
pixel[0] = r;
pixel[1] = g;
pixel[2] = b;
return;
}
void BMP::SetPixel(const Eule::Vector2i &position,
const std::uint8_t r,
const std::uint8_t g,
@ -380,6 +411,61 @@ namespace Leonetienne::BmpPP {
return bmp;
}
void BMP::ConvertColormode(const Colormode &colormode) {
CHECK_IF_INITIALIZED
// Do we already have the target color mode?
if (this->colormode == colormode)
return;
// So, we actually have to do something. Darn it.
// Move the old pixel buffer into a a.. well.. buffer. We're gonna need it
const std::vector<std::uint8_t> oldPixelBuffer = std::move(pixelBuffer);
// Re-initialize our image with our new color mode
ReInitialize(size, colormode);
// What should we convert then?
switch (colormode) { // this is the PARAMETER!
// Convert RGBA to RGB.
// Just drop the alpha channel.
case Colormode::RGB: {
// Jump through the old pixel buffer, four bytes at a time
for (std::size_t i = 0; i < oldPixelBuffer.size(); i += 4) {
// Per jump, copy three bytes into the new one. These are r,g,b.
std::copy(
oldPixelBuffer.cbegin() + i,
oldPixelBuffer.cbegin() + i + 3,
pixelBuffer.begin() + i - (i/4) // Subtract one byte per pixel, because the new pixelBuffer is RGB, not RGBA.
);
}
// Done.
}
return;
// Convert RGB to RGBA.
// Just fill the new alpha channel with 0xFF.
case Colormode::RGBA: {
// Jump through the old pixel buffer, three bytes at a time
for (std::size_t i = 0; i < oldPixelBuffer.size(); i += 3) {
// Per jump, copy these three bytes into the new one. These are r,g,b.
std::copy(
oldPixelBuffer.cbegin() + i,
oldPixelBuffer.cbegin() + i + 3,
pixelBuffer.begin() + i + (i/3) // Add one byte per pixel, because the new pixelBuffer is RGBA, not RGB.
);
}
// The alpha channel should already be set to 0xFF, by ReInitialize().
// Done.
}
break;
}
return;
}
}
#undef CHECK_IF_INITIALIZED

View File

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

68
Test/ConvertColormode.cpp Normal file
View File

@ -0,0 +1,68 @@
#include <Bmp.h>
#include <stdexcept>
#include "Catch2.h"
using namespace Leonetienne::BmpPP;
using namespace Eule;
// Tests converting between color modes works
TEST_CASE(__FILE__"/Converting_between_color_modes_works", "[Conversion]")
{
SECTION("RGB to RGB") {
// Read an RGB image
BMP bmp("base_kyokucho.bmp");
// Convert it to RGB
bmp.ConvertColormode(Colormode::RGB);
// Read reference image
const BMP reference("base_kyokucho.bmp");
// Assert that they are equal
REQUIRE(bmp == reference);
}
SECTION("RGB to RGBA") {
// Read an RGB image
BMP bmp("base_kyokucho.bmp");
// Convert it to RGBA
bmp.ConvertColormode(Colormode::RGBA);
// Read reference image
const BMP reference("basea_kyokucho.bmp");
// Assert that they are equal
REQUIRE(bmp == reference);
}
SECTION("RGBA to RGB") {
// Read an RGBA image
BMP bmp("basea_kyokucho.bmp");
// Convert it to RGB
bmp.ConvertColormode(Colormode::RGB);
// Read reference image
const BMP reference("base_kyokucho.bmp");
// Assert that they are equal
REQUIRE(bmp == reference);
}
SECTION("RGBA to RGBA") {
// Read an RGBA image
BMP bmp("basea_kyokucho.bmp");
// Convert it to RGBA
bmp.ConvertColormode(Colormode::RGBA);
// Read reference image
const BMP reference("basea_kyokucho.bmp");
// Assert that they are equal
REQUIRE(bmp == reference);
}
return;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB