LibGfx: Do not over-promise what type gets returned

This commit is contained in:
InvalidUsernameException 2025-11-23 13:07:39 +01:00 committed by Jelle Raaijmakers
parent 7c315ef67f
commit fa181c2be8
Notes: github-actions[bot] 2025-11-28 17:34:46 +00:00
4 changed files with 40 additions and 37 deletions

View file

@ -17,6 +17,9 @@
namespace Gfx {
// A pixel value that does not express any information about its component order
using RawPixel = u32;
enum class BitmapFormat {
Invalid,
BGRx8888,
@ -70,18 +73,18 @@ public:
[[nodiscard]] u8* scanline_u8(int physical_y);
[[nodiscard]] u8 const* scanline_u8(int physical_y) const;
[[nodiscard]] BGRA8888* scanline(int physical_y);
[[nodiscard]] BGRA8888 const* scanline(int physical_y) const;
[[nodiscard]] RawPixel* scanline(int physical_y);
[[nodiscard]] RawPixel const* scanline(int physical_y) const;
[[nodiscard]] u8* unchecked_scanline_u8(int physical_y);
[[nodiscard]] u8 const* unchecked_scanline_u8(int physical_y) const;
[[nodiscard]] BGRA8888* unchecked_scanline(int physical_y);
[[nodiscard]] BGRA8888 const* unchecked_scanline(int physical_y) const;
[[nodiscard]] RawPixel* unchecked_scanline(int physical_y);
[[nodiscard]] RawPixel const* unchecked_scanline(int physical_y) const;
[[nodiscard]] BGRA8888* begin();
[[nodiscard]] BGRA8888 const* begin() const;
[[nodiscard]] BGRA8888* end();
[[nodiscard]] BGRA8888 const* end() const;
[[nodiscard]] RawPixel* begin();
[[nodiscard]] RawPixel const* begin() const;
[[nodiscard]] RawPixel* end();
[[nodiscard]] RawPixel const* end() const;
[[nodiscard]] size_t data_size() const;
[[nodiscard]] IntRect rect() const { return { {}, m_size }; }
@ -164,14 +167,14 @@ ALWAYS_INLINE u8 const* Bitmap::unchecked_scanline_u8(int y) const
return reinterpret_cast<u8 const*>(m_data) + (y * m_pitch);
}
ALWAYS_INLINE BGRA8888* Bitmap::unchecked_scanline(int y)
ALWAYS_INLINE RawPixel* Bitmap::unchecked_scanline(int y)
{
return reinterpret_cast<BGRA8888*>(unchecked_scanline_u8(y));
return reinterpret_cast<RawPixel*>(unchecked_scanline_u8(y));
}
ALWAYS_INLINE BGRA8888 const* Bitmap::unchecked_scanline(int y) const
ALWAYS_INLINE RawPixel const* Bitmap::unchecked_scanline(int y) const
{
return reinterpret_cast<BGRA8888 const*>(unchecked_scanline_u8(y));
return reinterpret_cast<RawPixel const*>(unchecked_scanline_u8(y));
}
ALWAYS_INLINE u8* Bitmap::scanline_u8(int y)
@ -188,34 +191,34 @@ ALWAYS_INLINE u8 const* Bitmap::scanline_u8(int y) const
return unchecked_scanline_u8(y);
}
ALWAYS_INLINE BGRA8888* Bitmap::scanline(int y)
ALWAYS_INLINE RawPixel* Bitmap::scanline(int y)
{
return reinterpret_cast<BGRA8888*>(scanline_u8(y));
return reinterpret_cast<RawPixel*>(scanline_u8(y));
}
ALWAYS_INLINE BGRA8888 const* Bitmap::scanline(int y) const
ALWAYS_INLINE RawPixel const* Bitmap::scanline(int y) const
{
return reinterpret_cast<BGRA8888 const*>(scanline_u8(y));
return reinterpret_cast<RawPixel const*>(scanline_u8(y));
}
ALWAYS_INLINE BGRA8888* Bitmap::begin()
ALWAYS_INLINE RawPixel* Bitmap::begin()
{
return scanline(0);
}
ALWAYS_INLINE BGRA8888 const* Bitmap::begin() const
ALWAYS_INLINE RawPixel const* Bitmap::begin() const
{
return scanline(0);
}
ALWAYS_INLINE BGRA8888* Bitmap::end()
ALWAYS_INLINE RawPixel* Bitmap::end()
{
return reinterpret_cast<BGRA8888*>(reinterpret_cast<u8*>(m_data) + data_size());
return reinterpret_cast<RawPixel*>(reinterpret_cast<u8*>(m_data) + data_size());
}
ALWAYS_INLINE BGRA8888 const* Bitmap::end() const
ALWAYS_INLINE RawPixel const* Bitmap::end() const
{
return reinterpret_cast<BGRA8888 const*>(reinterpret_cast<u8 const*>(m_data) + data_size());
return reinterpret_cast<RawPixel const*>(reinterpret_cast<u8 const*>(m_data) + data_size());
}
ALWAYS_INLINE size_t Bitmap::data_size() const

View file

@ -32,7 +32,7 @@ public:
return ExifOrientedBitmap(move(bitmap), size, orientation);
}
template<OneOf<BGRA8888, CMYK> Value>
template<OneOf<RawPixel, CMYK> Value>
void set_pixel(u32 x, u32 y, Value color)
{
auto const new_position = oriented_position(IntPoint(x, y));

View file

@ -124,13 +124,13 @@ static void clear_rect(Bitmap& bitmap, IntRect const& rect, Color color)
if (intersection_rect.is_empty())
return;
BGRA8888* dst = bitmap.scanline(intersection_rect.top()) + intersection_rect.left();
size_t const dst_skip = bitmap.pitch() / sizeof(BGRA8888);
RawPixel* dst = bitmap.scanline(intersection_rect.top()) + intersection_rect.left();
size_t const dst_skip = bitmap.pitch() / sizeof(RawPixel);
auto const value = color.value();
auto const width = intersection_rect.width();
for (int i = intersection_rect.height() - 1; i >= 0; --i) {
for (BGRA8888* p = dst; p < (dst + width); ++p) {
for (RawPixel* p = dst; p < (dst + width); ++p) {
*p = value;
}
dst += dst_skip;

View file

@ -39,7 +39,7 @@ struct IsOpaque {
NEVER_INLINE static ErrorOr<void> write_image_data(LittleEndianOutputBitStream& bit_stream, Bitmap const& bitmap, PrefixCodeGroup const& prefix_code_group)
{
// This is currently the hot loop. Keep performance in mind when you change it.
for (BGRA8888 pixel : bitmap) {
for (RawPixel pixel : bitmap) {
u8 a = pixel >> 24;
u8 r = pixel >> 16;
u8 g = pixel >> 8;
@ -275,7 +275,7 @@ static ErrorOr<void> write_VP8L_coded_image(ImageKind image_kind, LittleEndianOu
// FIXME: Consider using a meta-prefix image and using one prefix-code-group per tile.
Array<Array<u16, 256>, 4> symbol_frequencies {};
for (BGRA8888 pixel : bitmap) {
for (RawPixel pixel : bitmap) {
static constexpr auto saturating_increment = [](u16& value) {
if (value < UINT16_MAX)
value++;
@ -322,7 +322,7 @@ static ErrorOr<void> write_VP8L_coded_image(ImageKind image_kind, LittleEndianOu
return {};
}
static BGRA8888 sub_argb32(BGRA8888 a, BGRA8888 b)
static RawPixel sub_pixel(RawPixel a, RawPixel b)
{
auto a_color = Color::from_bgra(a);
auto b_color = Color::from_bgra(b);
@ -337,10 +337,10 @@ static ErrorOr<NonnullRefPtr<Bitmap const>> maybe_write_color_indexing_transform
{
// https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification#44_color_indexing_transform
unsigned color_table_size = 0;
HashTable<BGRA8888> seen_colors;
BGRA8888 channels = 0;
BGRA8888 first_pixel = bitmap->get_pixel(0, 0).value();
for (BGRA8888 pixel : *bitmap) {
HashTable<RawPixel> seen_colors;
RawPixel channels = 0;
RawPixel first_pixel = bitmap->get_pixel(0, 0).value();
for (RawPixel pixel : *bitmap) {
auto result = seen_colors.set(pixel);
if (result == HashSetResult::InsertedNewEntry) {
++color_table_size;
@ -377,8 +377,8 @@ static ErrorOr<NonnullRefPtr<Bitmap const>> maybe_write_color_indexing_transform
TRY(bit_stream.write_bits(color_table_size - 1, 8u));
// Store color index to bit stream.
Vector<BGRA8888, 256> colors;
for (BGRA8888 color : seen_colors)
Vector<RawPixel, 256> colors;
for (RawPixel color : seen_colors)
colors.append(color);
quick_sort(colors.begin(), colors.end());
@ -387,11 +387,11 @@ static ErrorOr<NonnullRefPtr<Bitmap const>> maybe_write_color_indexing_transform
auto color_index_bitmap = TRY(Bitmap::create(BitmapFormat::BGRA8888, { static_cast<int>(color_table_size), 1 }));
color_index_bitmap->set_pixel(0, 0, Color::from_bgra(colors[0]));
for (unsigned i = 1; i < color_table_size; ++i)
color_index_bitmap->set_pixel(i, 0, Color::from_bgra(sub_argb32(colors[i], colors[i - 1])));
color_index_bitmap->set_pixel(i, 0, Color::from_bgra(sub_pixel(colors[i], colors[i - 1])));
TRY(write_VP8L_coded_image(ImageKind::EntropyCoded, bit_stream, *color_index_bitmap, is_fully_opaque));
// Return a new bitmap with the color indexing transform applied.
HashMap<BGRA8888, u8> color_index_map;
HashMap<RawPixel, u8> color_index_map;
for (unsigned i = 0; i < color_table_size; ++i)
color_index_map.set(colors[i], i);