Add ordered dither mask generation to gfx
This commit is contained in:
parent
302e5e888f
commit
0bddeaf865
2 changed files with 50 additions and 0 deletions
10
libs/gfx/include/psemek/gfx/dither.hpp
Normal file
10
libs/gfx/include/psemek/gfx/dither.hpp
Normal 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);
|
||||
|
||||
}
|
||||
40
libs/gfx/source/dither.cpp
Normal file
40
libs/gfx/source/dither.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue