Explorar el Código

LibGfx/ILBMLoader: Add support for EHB mode

Nicolas Ramz hace 1 año
padre
commit
7b4b5b735b
Se han modificado 1 ficheros con 37 adiciones y 4 borrados
  1. 37 4
      Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp

+ 37 - 4
Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp

@@ -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));
         }
     }