LibGfx/ILBMLoader: Add support for EHB mode

This commit is contained in:
Nicolas Ramz 2023-09-13 10:01:40 +02:00 committed by Andrew Kaster
parent 398d271a46
commit 7b4b5b735b

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ByteReader.h>
#include <AK/Debug.h>
#include <AK/Endian.h>
#include <AK/FixedArray.h>
@ -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<u32> chunk_size;
@ -74,7 +82,9 @@ struct ILBMLoadingContext {
// max number of bytes per plane row
u16 pitch;
FixedArray<Color> color_table;
ViewportMode viewport_mode;
Vector<Color> color_table;
RefPtr<Gfx::Bitmap> bitmap;
@ -96,13 +106,14 @@ static ErrorOr<void> decode_iff_ilbm_header(ILBMLoadingContext& context)
return {};
}
static ErrorOr<FixedArray<Color>> decode_cmap_chunk(Chunk cmap_chunk)
static ErrorOr<Vector<Color>> decode_cmap_chunk(Chunk cmap_chunk)
{
size_t const size = cmap_chunk.data.size() / 3;
FixedArray<Color> color_table = TRY(FixedArray<Color>::create(size));
Vector<Color> 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<ByteBuffer> uncompress_byte_run(ReadonlyBytes data, ILBMLoadingCo
return plane_data;
}
static ErrorOr<void> 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<void> 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<void> 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<void> 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<ViewportMode>(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));
}
}