1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 14:07:46 +00:00

LibGfx: Fix TGA decoder being out of boundary after calling frame method

This happened because the reader was incrementing the byte index of it
after each read of a byte from the Span, so by the end of the frame
method, we could be at the end of the mapped file, so the next call
on the same decoder will just resume from that point and will be quickly
out of boundary.
To ensure this doesn't happen we only set the bitmap to m_context member
at the end of the method, and call to that method again will just give
the already-generated bitmap.
In case of setting the bitmap as volatile, we test for that case and
re-generate a reader to read the frame again correctly.
This commit is contained in:
Liav A 2023-01-20 18:50:49 +02:00 committed by Linus Groh
parent 20033d06d8
commit 5b273f3823

View file

@ -65,6 +65,12 @@ public:
{
}
TGAReader(ReadonlyBytes data, size_t index)
: m_data(move(data))
, m_index(index)
{
}
ALWAYS_INLINE u8 read_u8()
{
u8 value = m_data[m_index];
@ -265,13 +271,25 @@ ErrorOr<ImageFrameDescriptor> TGAImageDecoderPlugin::frame(size_t index)
if (color_map > 1)
return Error::from_string_literal("TGAImageDecoderPlugin: Invalid color map type");
if (m_context->bitmap) {
return ImageFrameDescriptor { m_context->bitmap, 0 };
} else {
// NOTE: Just to be on the safe side, if m_context->bitmap is nullptr, then
// just re-construct the reader object. This will ensure that if the bitmap
// was set as volatile and therefore it is gone, we can always re-generate it
// with a new call to this method!
VERIFY(m_context->reader);
m_context->reader = make<TGAReader>(m_context->reader->data(), sizeof(TGAHeader));
}
RefPtr<Gfx::Bitmap> bitmap;
switch (bits_per_pixel) {
case 24:
m_context->bitmap = TRY(Bitmap::try_create(BitmapFormat::BGRx8888, { m_context->header.width, m_context->header.height }));
bitmap = TRY(Bitmap::try_create(BitmapFormat::BGRx8888, { m_context->header.width, m_context->header.height }));
break;
case 32:
m_context->bitmap = TRY(Bitmap::try_create(BitmapFormat::BGRA8888, { m_context->header.width, m_context->header.height }));
bitmap = TRY(Bitmap::try_create(BitmapFormat::BGRA8888, { m_context->header.width, m_context->header.height }));
break;
default:
@ -303,7 +321,7 @@ ErrorOr<ImageFrameDescriptor> TGAImageDecoderPlugin::frame(size_t index)
auto actual_col = col;
if (x_origin > width)
actual_col = width - 1 - col;
m_context->bitmap->scanline(actual_row)[actual_col] = pixel.data;
bitmap->scanline(actual_row)[actual_col] = pixel.data;
}
}
break;
@ -325,7 +343,7 @@ ErrorOr<ImageFrameDescriptor> TGAImageDecoderPlugin::frame(size_t index)
auto actual_col = col;
if (x_origin > width)
actual_col = width - 1 - col;
m_context->bitmap->scanline(actual_row)[actual_col] = pixel.data;
bitmap->scanline(actual_row)[actual_col] = pixel.data;
if (packet_type.raw && (current_pixel_index + 1) < max_pixel_index)
pixel = m_context->reader->read_pixel(bits_per_pixel);
}
@ -338,7 +356,7 @@ ErrorOr<ImageFrameDescriptor> TGAImageDecoderPlugin::frame(size_t index)
return Error::from_string_literal("TGAImageDecoderPlugin: Can currently only handle the UncompressedRGB or CompressedRGB data type");
}
VERIFY(m_context->bitmap);
m_context->bitmap = bitmap;
return ImageFrameDescriptor { m_context->bitmap, 0 };
}
}