diff --git a/Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp index a448be0500..50511cb253 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -36,6 +37,13 @@ enum class MaskType : u8 { HasLasso = 3 }; +enum class ViewportMode : u32 { + EHB = 0x80, + HAM = 0x800 +}; + +AK_ENUM_BITWISE_OPERATORS(ViewportMode); + struct ChunkHeader { FourCC chunk_type; BigEndian chunk_size; @@ -74,7 +82,9 @@ struct ILBMLoadingContext { // max number of bytes per plane row u16 pitch; - FixedArray color_table; + ViewportMode viewport_mode; + + Vector color_table; RefPtr bitmap; @@ -96,13 +106,14 @@ static ErrorOr decode_iff_ilbm_header(ILBMLoadingContext& context) return {}; } -static ErrorOr> decode_cmap_chunk(Chunk cmap_chunk) +static ErrorOr> decode_cmap_chunk(Chunk cmap_chunk) { size_t const size = cmap_chunk.data.size() / 3; - FixedArray color_table = TRY(FixedArray::create(size)); + Vector color_table; + TRY(color_table.try_ensure_capacity(size)); for (size_t i = 0; i < size; ++i) { - color_table[i] = Color(cmap_chunk.data[i * 3], cmap_chunk.data[(i * 3) + 1], cmap_chunk.data[(i * 3) + 2]); + color_table.unchecked_append(Color(cmap_chunk.data[i * 3], cmap_chunk.data[(i * 3) + 1], cmap_chunk.data[(i * 3) + 2])); } return color_table; @@ -189,6 +200,17 @@ static ErrorOr uncompress_byte_run(ReadonlyBytes data, ILBMLoadingCo return plane_data; } +static ErrorOr extend_ehb_palette(ILBMLoadingContext& context) +{ + dbgln_if(ILBM_DEBUG, "need to extend palette"); + for (size_t i = 0; i < 32; ++i) { + auto const color = context.color_table[i]; + TRY(context.color_table.try_append(color.darkened())); + } + + return {}; +} + static ErrorOr decode_body_chunk(Chunk body_chunk, ILBMLoadingContext& context) { dbgln_if(ILBM_DEBUG, "decode_body_chunk {}", body_chunk.data.size()); @@ -202,6 +224,14 @@ static ErrorOr decode_body_chunk(Chunk body_chunk, ILBMLoadingContext& con pixel_data = TRY(planar_to_chunky(body_chunk.data, context)); } + // Some files already have 64 colours defined in the palette, + // maybe for upward compatibility with 256 colours software/hardware. + // DPaint 4 & previous files only have 32 colours so the + // palette needs to be extended only for these files. + if (has_flag(context.viewport_mode, ViewportMode::EHB) && context.color_table.size() < 64) { + TRY(extend_ehb_palette(context)); + } + context.bitmap = TRY(chunky_to_bitmap(context, pixel_data)); return {}; @@ -253,6 +283,9 @@ static ErrorOr decode_iff_chunks(ILBMLoadingContext& context) context.state = ILBMLoadingContext::State::BitmapDecoded; } else if (chunk.type == FourCC("CRNG")) { dbgln_if(ILBM_DEBUG, "Chunk:CRNG"); + } else if (chunk.type == FourCC("CAMG")) { + context.viewport_mode = static_cast(AK::convert_between_host_and_big_endian(ByteReader::load32(chunk.data.data()))); + dbgln_if(ILBM_DEBUG, "Chunk:CAMG, Viewport={}, EHB={}, HAM={}", (u32)context.viewport_mode, has_flag(context.viewport_mode, ViewportMode::EHB), has_flag(context.viewport_mode, ViewportMode::HAM)); } }