Add ordered dither mask generation to gfx

This commit is contained in:
Nikita Lisitsa 2022-06-18 17:35:50 +03:00
parent 302e5e888f
commit 0bddeaf865
2 changed files with 50 additions and 0 deletions

View file

@ -0,0 +1,10 @@
#pragma once
#include <psemek/gfx/pixmap.hpp>
namespace psemek::gfx
{
basic_pixmap<std::uint8_t> ordered_dither(std::size_t size);
}

View file

@ -0,0 +1,40 @@
#include <psemek/gfx/dither.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 std::runtime_error("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;
}
}