Add class for converting Bitmaps to monochrome bytes representation
This commit is contained in:
@@ -22,6 +22,7 @@ ptprnt_hpps = [
|
|||||||
'src/PtouchPrint.hpp',
|
'src/PtouchPrint.hpp',
|
||||||
'src/graphics/Bitmap.hpp',
|
'src/graphics/Bitmap.hpp',
|
||||||
'src/graphics/Image.hpp',
|
'src/graphics/Image.hpp',
|
||||||
|
'src/graphics/Monochrome.hpp'
|
||||||
]
|
]
|
||||||
|
|
||||||
ptprnt_srcs = [
|
ptprnt_srcs = [
|
||||||
@@ -29,6 +30,7 @@ ptprnt_srcs = [
|
|||||||
'src/P700Printer.cpp',
|
'src/P700Printer.cpp',
|
||||||
'src/graphics/Image.cpp',
|
'src/graphics/Image.cpp',
|
||||||
'src/graphics/Bitmap.cpp',
|
'src/graphics/Bitmap.cpp',
|
||||||
|
'src/graphics/Monochrome.cpp',
|
||||||
'src/libusbwrap/UsbDeviceFactory.cpp',
|
'src/libusbwrap/UsbDeviceFactory.cpp',
|
||||||
'src/libusbwrap/UsbDevice.cpp',
|
'src/libusbwrap/UsbDevice.cpp',
|
||||||
]
|
]
|
||||||
|
40
src/graphics/Monochrome.cpp
Normal file
40
src/graphics/Monochrome.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include "graphics/Monochrome.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace ptprnt::graphics {
|
||||||
|
Monochrome::Monochrome(const std::vector<uint8_t>& grayscale) : mPixels(std::move(grayscale)) {}
|
||||||
|
|
||||||
|
void Monochrome::setThreshold(uint8_t threshhold) {
|
||||||
|
mThreshhold = threshhold;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Monochrome::invert(bool shouldInvert) {
|
||||||
|
mShouldInvert = shouldInvert;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Monochrome::get() {
|
||||||
|
std::vector<uint8_t> outPixels(
|
||||||
|
(static_cast<unsigned int>((mPixels.size() / 8)) + (std::floor(mPixels.size() % 8 + 0.9))));
|
||||||
|
|
||||||
|
unsigned int outIndex = 0;
|
||||||
|
|
||||||
|
for (unsigned int byteNum = 0; byteNum < mPixels.size(); byteNum += 8) {
|
||||||
|
for (unsigned int bitNo = 0; bitNo < 8; bitNo++) {
|
||||||
|
if (mPixels[byteNum + bitNo] > mThreshhold) {
|
||||||
|
outPixels[outIndex] |= (1 << (7 - bitNo));
|
||||||
|
} else {
|
||||||
|
outPixels[outIndex] &= ~(1 << (7 - bitNo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mShouldInvert) {
|
||||||
|
outPixels[outIndex] = ~outPixels[outIndex];
|
||||||
|
}
|
||||||
|
outIndex++;
|
||||||
|
}
|
||||||
|
return outPixels;
|
||||||
|
}
|
||||||
|
} // namespace ptprnt::graphics
|
20
src/graphics/Monochrome.hpp
Normal file
20
src/graphics/Monochrome.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "graphics/Bitmap.hpp"
|
||||||
|
|
||||||
|
namespace ptprnt::graphics {
|
||||||
|
class Monochrome {
|
||||||
|
public:
|
||||||
|
Monochrome(const std::vector<uint8_t>& grayscale);
|
||||||
|
~Monochrome() = default;
|
||||||
|
|
||||||
|
void setThreshold(uint8_t);
|
||||||
|
void invert(bool shouldInvert);
|
||||||
|
std::vector<uint8_t> get();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector<uint8_t>& mPixels;
|
||||||
|
uint8_t mThreshhold = 127;
|
||||||
|
bool mShouldInvert = false;
|
||||||
|
};
|
||||||
|
} // namespace ptprnt::graphics
|
@@ -1,5 +1,6 @@
|
|||||||
tests = [['bitmap_test', 'bitmap_test_exe', ['bitmap_test/bitmap_test.cpp']],
|
tests = [['bitmap_test', 'bitmap_test_exe', ['bitmap_test/bitmap_test.cpp']],
|
||||||
['image_test', 'image_test_exe', ['image_test/image_test.cpp']]
|
['image_test', 'image_test_exe', ['image_test/image_test.cpp']],
|
||||||
|
['monochrome_test', 'monochrome_test_exe', ['monochrome_test/monochrome_test.cpp']]
|
||||||
]
|
]
|
||||||
|
|
||||||
foreach test : tests
|
foreach test : tests
|
||||||
|
49
tests/monochrome_test/monochrome_test.cpp
Normal file
49
tests/monochrome_test/monochrome_test.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include "graphics/Monochrome.hpp"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
TEST(basic_test, Monochrome_convertGrayscale_yieldsMonochrome) {
|
||||||
|
const std::vector<uint8_t> pixels({0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
|
||||||
|
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00});
|
||||||
|
|
||||||
|
const std::vector<uint8_t> expected({0b10101010, 0b10101010});
|
||||||
|
auto mono = ptprnt::graphics::Monochrome(pixels);
|
||||||
|
auto out = mono.get();
|
||||||
|
|
||||||
|
EXPECT_EQ(out, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(basic_test, Monochrome_convertInvertedGrayscale_yieldsInvertedMonochrome) {
|
||||||
|
const std::vector<uint8_t> pixels({0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
|
||||||
|
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00});
|
||||||
|
|
||||||
|
const std::vector<uint8_t> expected({0b01010101, 0b01010101});
|
||||||
|
auto mono = ptprnt::graphics::Monochrome(pixels);
|
||||||
|
mono.invert(true);
|
||||||
|
auto out = mono.get();
|
||||||
|
|
||||||
|
EXPECT_EQ(out, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(basic_test, Monochrome_convertWithCustomThreshhold_yieldsMonochromeRespectingThreshhold) {
|
||||||
|
const std::vector<uint8_t> pixels({0x0F, 0x11, 0x0F, 0x11, 0x0F, 0x11, 0x0F, 0x11, 0x0F, 0x11,
|
||||||
|
0x0F, 0x11, 0x0F, 0x11, 0x0F, 0x11});
|
||||||
|
|
||||||
|
const std::vector<uint8_t> expected({0b01010101, 0b01010101});
|
||||||
|
auto mono = ptprnt::graphics::Monochrome(pixels);
|
||||||
|
mono.setThreshold(16);
|
||||||
|
auto out = mono.get();
|
||||||
|
|
||||||
|
EXPECT_EQ(out, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(basic_test, Monochrome_convertNonAlignedPixels_spillsOverIntoNewByte) {
|
||||||
|
const std::vector<uint8_t> pixels({0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
|
||||||
|
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF});
|
||||||
|
|
||||||
|
const std::vector<uint8_t> expected({0b10101010, 0b10101010, 0b10000000});
|
||||||
|
auto mono = ptprnt::graphics::Monochrome(pixels);
|
||||||
|
auto out = mono.get();
|
||||||
|
|
||||||
|
EXPECT_EQ(out, expected);
|
||||||
|
}
|
Reference in New Issue
Block a user