GraphicsBitmap: Add a new "Indexed8" format that uses a 256-entry palette.

These bitmaps should only be used as a source bitmap, we won't support
painting into them using Painter. You can however manipulate the raw
pixel data. :^)
This commit is contained in:
Andreas Kling 2019-05-06 19:32:56 +02:00
parent cec16105cc
commit 61e3ecec79
Notes: sideshowbarker 2024-07-19 14:13:19 +09:00
3 changed files with 56 additions and 8 deletions

View file

@ -17,6 +17,8 @@ GraphicsBitmap::GraphicsBitmap(Format format, const Size& size)
, m_pitch(round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16))
, m_format(format)
{
if (format == Format::Indexed8)
m_palette = new RGBA32[256];
m_data = (RGBA32*)mmap(nullptr, size_in_bytes(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
ASSERT(m_data && m_data != (void*)-1);
m_needs_munmap = true;
@ -47,6 +49,7 @@ GraphicsBitmap::GraphicsBitmap(Format format, const Size& size, RGBA32* data)
, m_pitch(round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16))
, m_format(format)
{
ASSERT(format != Format::Indexed8);
}
GraphicsBitmap::GraphicsBitmap(Format format, const Size& size, MappedFile&& mapped_file)
@ -56,6 +59,7 @@ GraphicsBitmap::GraphicsBitmap(Format format, const Size& size, MappedFile&& map
, m_format(format)
, m_mapped_file(move(mapped_file))
{
ASSERT(format != Format::Indexed8);
}
Retained<GraphicsBitmap> GraphicsBitmap::create_with_shared_buffer(Format format, Retained<SharedBuffer>&& shared_buffer, const Size& size)
@ -70,6 +74,7 @@ GraphicsBitmap::GraphicsBitmap(Format format, Retained<SharedBuffer>&& shared_bu
, m_format(format)
, m_shared_buffer(move(shared_buffer))
{
ASSERT(format != Format::Indexed8);
}
GraphicsBitmap::~GraphicsBitmap()
@ -79,6 +84,7 @@ GraphicsBitmap::~GraphicsBitmap()
ASSERT(rc == 0);
}
m_data = nullptr;
delete [] m_palette;
}
void GraphicsBitmap::set_mmap_name(const String& name)

View file

@ -11,7 +11,7 @@
class GraphicsBitmap : public Retainable<GraphicsBitmap> {
public:
enum class Format { Invalid, RGB32, RGBA32 };
enum class Format { Invalid, RGB32, RGBA32, Indexed8 };
static Retained<GraphicsBitmap> create(Format, const Size&);
static Retained<GraphicsBitmap> create_wrapper(Format, const Size&, RGBA32*);
@ -23,6 +23,8 @@ public:
RGBA32* scanline(int y);
const RGBA32* scanline(int y) const;
const byte* bits(int y) const;
Rect rect() const { return { {}, m_size }; }
Size size() const { return m_size; }
int width() const { return m_size.width(); }
@ -37,6 +39,23 @@ public:
size_t size_in_bytes() const { return m_pitch * m_size.height() * sizeof(RGBA32); }
Color palette_color(byte index) const { return Color::from_rgba(m_palette[index]); }
void set_palette_color(byte index, Color color) { m_palette[index] = color.value(); }
Color get_pixel(int x, int y) const
{
switch (m_format) {
case Format::RGB32:
return Color::from_rgb(scanline(y)[x]);
case Format::RGBA32:
return Color::from_rgba(scanline(y)[x]);
case Format::Indexed8:
return Color::from_rgba(m_palette[bits(y)[x]]);
default:
ASSERT_NOT_REACHED();
}
}
private:
GraphicsBitmap(Format, const Size&);
GraphicsBitmap(Format, const Size&, RGBA32*);
@ -45,6 +64,7 @@ private:
Size m_size;
RGBA32* m_data { nullptr };
RGBA32* m_palette { nullptr };
size_t m_pitch { 0 };
Format m_format { Format::Invalid };
bool m_needs_munmap { false };
@ -61,3 +81,8 @@ inline const RGBA32* GraphicsBitmap::scanline(int y) const
{
return reinterpret_cast<const RGBA32*>((((const byte*)m_data) + (y * m_pitch)));
}
inline const byte* GraphicsBitmap::bits(int y) const
{
return reinterpret_cast<const byte*>(scanline(y));
}

View file

@ -308,15 +308,32 @@ void Painter::blit(const Point& position, const GraphicsBitmap& source, const Re
const int last_row = clipped_rect.bottom() - dst_rect.top();
const int first_column = clipped_rect.left() - dst_rect.left();
RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x();
const RGBA32* src = source.scanline(src_rect.top() + first_row) + src_rect.left() + first_column;
const size_t dst_skip = m_target->pitch() / sizeof(RGBA32);
const size_t src_skip = source.pitch() / sizeof(RGBA32);
for (int row = first_row; row <= last_row; ++row) {
fast_dword_copy(dst, src, clipped_rect.width());
dst += dst_skip;
src += src_skip;
if (source.format() == GraphicsBitmap::Format::RGB32 || source.format() == GraphicsBitmap::Format::RGBA32) {
const RGBA32* src = source.scanline(src_rect.top() + first_row) + src_rect.left() + first_column;
const size_t src_skip = source.pitch() / sizeof(RGBA32);
for (int row = first_row; row <= last_row; ++row) {
fast_dword_copy(dst, src, clipped_rect.width());
dst += dst_skip;
src += src_skip;
}
return;
}
if (source.format() == GraphicsBitmap::Format::Indexed8) {
const byte* src = source.bits(src_rect.top() + first_row) + src_rect.left() + first_column;
const size_t src_skip = source.pitch();
for (int row = first_row; row <= last_row; ++row) {
for (int i = 0; i < clipped_rect.width(); ++i)
dst[i] = source.palette_color(src[i]).value();
dst += dst_skip;
src += src_skip;
}
return;
}
ASSERT_NOT_REACHED();
}
void Painter::draw_scaled_bitmap(const Rect& a_dst_rect, const GraphicsBitmap& source, const Rect& src_rect)
@ -345,7 +362,7 @@ void Painter::draw_scaled_bitmap(const Rect& a_dst_rect, const GraphicsBitmap& s
auto scaled_x = (float)(x - dst_rect.x()) * hscale;
auto scaled_y = (float)(y - dst_rect.y()) * vscale;
auto src_pixel = Color::from_rgba(source.scanline((int)scaled_y)[(int)scaled_x]);
auto src_pixel = source.get_pixel(scaled_x, scaled_y);
if (!src_pixel.alpha())
continue;