41 lines
1,012 B
C++
41 lines
1,012 B
C++
#include <psemek/gfx/dither.hpp>
|
|
#include <psemek/util/exception.hpp>
|
|
|
|
namespace psemek::gfx
|
|
{
|
|
|
|
static std::uint8_t interleave_with_zeros(std::uint8_t input) {
|
|
std::uint8_t word = input;
|
|
word = (word ^ (word << 4 )) & 0x0f0f;
|
|
word = (word ^ (word << 2 )) & 0x3333;
|
|
word = (word ^ (word << 1 )) & 0x5555;
|
|
return word;
|
|
}
|
|
|
|
static std::uint8_t bit_interleave(std::uint8_t a, std::uint8_t b) {
|
|
return interleave_with_zeros(a) | (interleave_with_zeros(b) << 1);
|
|
}
|
|
|
|
static std::uint8_t bit_reverse(std::uint8_t b) {
|
|
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
|
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
|
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
|
return b;
|
|
}
|
|
|
|
basic_pixmap<std::uint8_t> ordered_dither(std::size_t size)
|
|
{
|
|
if (size > 16)
|
|
throw util::exception("8-bit dither map cannot be larger than 16x16");
|
|
|
|
basic_pixmap<std::uint8_t> result({size, size});
|
|
|
|
for (auto idx : result.indices())
|
|
{
|
|
result(idx) = bit_reverse(bit_interleave(idx[0] ^ idx[1], idx[0]));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|