mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-23 04:55:15 +00:00
LibGfx/ILBMLoader: Properly display images with a bitplane mask
Images with a display mask ("stencil" as it's called in DPaint) add an extra bitplane which acts as a mask. For now, at least skip it properly. Later we should render masked pixels as transparent, but this requires some refactoring.
This commit is contained in:
parent
45181e8eaf
commit
534eeb6c4b
Notes:
sideshowbarker
2024-07-17 20:58:35 +09:00
Author: https://github.com/warpdesign Commit: https://github.com/SerenityOS/serenity/commit/534eeb6c4b Pull-request: https://github.com/SerenityOS/serenity/pull/22808 Reviewed-by: https://github.com/LucasChollet ✅
3 changed files with 21 additions and 5 deletions
|
@ -265,6 +265,17 @@ TEST_CASE(test_small_24bit)
|
|||
EXPECT_EQ(frame.image->get_pixel(0, 4), Gfx::Color(1, 0, 1, 255));
|
||||
}
|
||||
|
||||
TEST_CASE(test_stencil_mask)
|
||||
{
|
||||
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("ilbm/test-stencil.iff"sv)));
|
||||
EXPECT(Gfx::ILBMImageDecoderPlugin::sniff(file->bytes()));
|
||||
auto plugin_decoder = TRY_OR_FAIL(Gfx::ILBMImageDecoderPlugin::create(file->bytes()));
|
||||
|
||||
auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 320, 200 }));
|
||||
|
||||
EXPECT_EQ(frame.image->get_pixel(0, 4), Gfx::Color(0, 0, 0, 255));
|
||||
}
|
||||
|
||||
TEST_CASE(test_ilbm_malformed_header)
|
||||
{
|
||||
Array test_inputs = {
|
||||
|
|
BIN
Tests/LibGfx/test-inputs/ilbm/test-stencil.iff
Normal file
BIN
Tests/LibGfx/test-inputs/ilbm/test-stencil.iff
Normal file
Binary file not shown.
|
@ -182,7 +182,8 @@ static ErrorOr<ByteBuffer> planar_to_chunky(ReadonlyBytes bitplanes, ILBMLoading
|
|||
u16 pitch = context.pitch;
|
||||
u16 width = context.bm_header.width;
|
||||
u16 height = context.bm_header.height;
|
||||
u8 planes = context.bm_header.planes;
|
||||
// mask is added as an extra plane
|
||||
u8 planes = context.bm_header.mask == MaskType::HasMask ? context.bm_header.planes + 1 : context.bm_header.planes;
|
||||
size_t buffer_size = static_cast<size_t>(width) * height;
|
||||
// If planes number is 24 we'll store R,G,B components so buffer needs to be 3 times width*height
|
||||
// otherwise we'll store a single 8bit index to the CMAP.
|
||||
|
@ -209,17 +210,17 @@ static ErrorOr<ByteBuffer> planar_to_chunky(ReadonlyBytes bitplanes, ILBMLoading
|
|||
// when enough data for current bitplane row has been read
|
||||
for (u8 b = 0; b < 8 && (i * 8) + b < width; b++) {
|
||||
u8 mask = 1 << (7 - b);
|
||||
// get current plane
|
||||
if (bit & mask) {
|
||||
// get current plane: simply skip mask plane for now
|
||||
if (bit & mask && p < context.bm_header.planes) {
|
||||
u16 x = (i * 8) + b;
|
||||
size_t offset = (scanline * pixel_size) + (x * pixel_size) + rgb_shift;
|
||||
// Only throw an error if we would actually attempt to write
|
||||
// outside of the chunky buffer. Some apps like PPaint produce
|
||||
// malformed bitplane data but files are still accepted by most readers
|
||||
// since they do not cause writing past the chunky buffer.
|
||||
if (offset >= chunky.size()) {
|
||||
if (offset >= chunky.size())
|
||||
return Error::from_string_literal("Malformed bitplane data");
|
||||
}
|
||||
|
||||
chunky[offset] |= plane_mask;
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +240,10 @@ static ErrorOr<ByteBuffer> uncompress_byte_run(ReadonlyBytes data, ILBMLoadingCo
|
|||
|
||||
size_t plane_data_size = context.pitch * context.bm_header.height * context.bm_header.planes;
|
||||
|
||||
// The mask is encoded as an extra bitplane but is not counted in the bm_header planes
|
||||
if (context.bm_header.mask == MaskType::HasMask)
|
||||
plane_data_size += context.pitch * context.bm_header.height;
|
||||
|
||||
// The maximum run length of this compression method is 127 bytes, so the uncompressed size
|
||||
// cannot be more than 127 times the size of the chunk we are decompressing.
|
||||
if (plane_data_size > NumericLimits<u32>::max() || ceil_div(plane_data_size, 127ul) > length)
|
||||
|
|
Loading…
Add table
Reference in a new issue