Ver Fonte

LibGfx/WebP: Split out ANMFChunk header data into ANMFChunkHeader

No behavior change.
Nico Weber há 1 ano atrás
pai
commit
768a7ea1e5

+ 12 - 11
Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp

@@ -311,10 +311,8 @@ static ErrorOr<ANMFChunk> decode_webp_chunk_ANMF(WebPLoadingContext& context, RI
     u32 frame_duration = (u32)anmf_chunk[12] | ((u32)anmf_chunk[13] << 8) | ((u32)anmf_chunk[14] << 16);
 
     u8 flags = anmf_chunk[15];
-    auto blending_method = static_cast<ANMFChunk::BlendingMethod>((flags >> 1) & 1);
-    auto disposal_method = static_cast<ANMFChunk::DisposalMethod>(flags & 1);
-
-    ReadonlyBytes frame_data = anmf_chunk.data().slice(16);
+    auto blending_method = static_cast<ANMFChunkHeader::BlendingMethod>((flags >> 1) & 1);
+    auto disposal_method = static_cast<ANMFChunkHeader::DisposalMethod>(flags & 1);
 
     dbgln_if(WEBP_DEBUG, "frame_x {} frame_y {} frame_width {} frame_height {} frame_duration {} blending_method {} disposal_method {}",
         frame_x, frame_y, frame_width, frame_height, frame_duration, (int)blending_method, (int)disposal_method);
@@ -326,7 +324,9 @@ static ErrorOr<ANMFChunk> decode_webp_chunk_ANMF(WebPLoadingContext& context, RI
     if (frame_x + frame_width > context.vp8x_header.width || frame_y + frame_height > context.vp8x_header.height)
         return Error::from_string_literal("WebPImageDecoderPlugin: ANMF dimensions out of bounds");
 
-    return ANMFChunk { frame_x, frame_y, frame_width, frame_height, frame_duration, blending_method, disposal_method, frame_data };
+    auto header = ANMFChunkHeader { frame_x, frame_y, frame_width, frame_height, frame_duration, blending_method, disposal_method };
+    ReadonlyBytes frame_data = anmf_chunk.data().slice(16);
+    return ANMFChunk { header, frame_data };
 }
 
 static ErrorOr<ImageData> decode_webp_set_image_data(Optional<RIFF::Chunk> alpha, Optional<RIFF::Chunk> image_data)
@@ -561,28 +561,29 @@ static ErrorOr<ImageFrameDescriptor> decode_webp_animation_frame(WebPLoadingCont
     for (size_t i = start_frame; i <= frame_index; ++i) {
         dbgln_if(WEBP_DEBUG, "drawing frame {} to produce frame {}", i, frame_index);
 
-        auto const& frame_description = context.animation_frame_chunks_data.value()[i];
+        auto const& frame = context.animation_frame_chunks_data.value()[i];
+        auto const& frame_description = frame.header;
 
         if (i > 0) {
-            auto const& previous_frame = context.animation_frame_chunks_data.value()[i - 1];
-            if (previous_frame.disposal_method == ANMFChunk::DisposalMethod::DisposeToBackgroundColor)
+            auto const& previous_frame = context.animation_frame_chunks_data.value()[i - 1].header;
+            if (previous_frame.disposal_method == ANMFChunkHeader::DisposalMethod::DisposeToBackgroundColor)
                 painter.clear_rect({ previous_frame.frame_x, previous_frame.frame_y, previous_frame.frame_width, previous_frame.frame_height }, clear_color);
         }
 
-        auto frame_image_data = TRY(decode_webp_animation_frame_image_data(frame_description));
+        auto frame_image_data = TRY(decode_webp_animation_frame_image_data(frame));
         auto frame_bitmap = TRY(decode_webp_image_data(context, frame_image_data));
         if (static_cast<u32>(frame_bitmap->width()) != frame_description.frame_width || static_cast<u32>(frame_bitmap->height()) != frame_description.frame_height)
             return Error::from_string_literal("WebPImageDecoderPlugin: decoded frame bitmap size doesn't match frame description size");
 
         // FIXME: "Alpha-blending SHOULD be done in linear color space..."
-        bool apply_alpha = frame_description.blending_method == ANMFChunk::BlendingMethod::UseAlphaBlending;
+        bool apply_alpha = frame_description.blending_method == ANMFChunkHeader::BlendingMethod::UseAlphaBlending;
         painter.blit({ frame_description.frame_x, frame_description.frame_y }, *frame_bitmap, { {}, frame_bitmap->size() }, /*opacity=*/1.0, apply_alpha);
 
         context.current_frame = i;
         context.state = WebPLoadingContext::State::BitmapDecoded;
     }
 
-    return ImageFrameDescriptor { context.bitmap, static_cast<int>(context.animation_frame_chunks_data.value()[frame_index].frame_duration_in_milliseconds) };
+    return ImageFrameDescriptor { context.bitmap, static_cast<int>(context.animation_frame_chunks_data.value()[frame_index].header.frame_duration_in_milliseconds) };
 }
 
 WebPImageDecoderPlugin::WebPImageDecoderPlugin(ReadonlyBytes data, OwnPtr<WebPLoadingContext> context)

+ 4 - 1
Userland/Libraries/LibGfx/ImageFormats/WebPShared.h

@@ -26,7 +26,7 @@ struct ANIMChunk {
     u16 loop_count { 0 };
 };
 
-struct ANMFChunk {
+struct ANMFChunkHeader {
     u32 frame_x { 0 };
     u32 frame_y { 0 };
     u32 frame_width { 0 };
@@ -44,7 +44,10 @@ struct ANMFChunk {
         DisposeToBackgroundColor = 1,
     };
     DisposalMethod disposal_method { DisposalMethod::DoNotDispose };
+};
 
+struct ANMFChunk {
+    ANMFChunkHeader header;
     ReadonlyBytes frame_data;
 };
 

+ 10 - 11
Userland/Libraries/LibGfx/ImageFormats/WebPWriter.cpp

@@ -370,7 +370,7 @@ static ErrorOr<void> align_to_two(SeekableStream& stream)
     return align_to_two(stream, TRY(stream.tell()));
 }
 
-static ErrorOr<void> write_ANMF_chunk(Stream& stream, ANMFChunk const& chunk)
+static ErrorOr<void> write_ANMF_chunk(Stream& stream, ANMFChunkHeader const& chunk, ReadonlyBytes frame_data)
 {
     if (chunk.frame_width > (1 << 24) || chunk.frame_height > (1 << 24))
         return Error::from_string_literal("WebP dimensions too large for ANMF chunk");
@@ -384,7 +384,7 @@ static ErrorOr<void> write_ANMF_chunk(Stream& stream, ANMFChunk const& chunk)
     dbgln_if(WEBP_DEBUG, "writing ANMF frame_x {} frame_y {} frame_width {} frame_height {} frame_duration {} blending_method {} disposal_method {}",
         chunk.frame_x, chunk.frame_y, chunk.frame_width, chunk.frame_height, chunk.frame_duration_in_milliseconds, (int)chunk.blending_method, (int)chunk.disposal_method);
 
-    TRY(write_chunk_header(stream, "ANMF"sv, 16 + chunk.frame_data.size()));
+    TRY(write_chunk_header(stream, "ANMF"sv, 16 + frame_data.size()));
 
     LittleEndianOutputBitStream bit_stream { MaybeOwned<Stream>(stream) };
 
@@ -414,11 +414,11 @@ static ErrorOr<void> write_ANMF_chunk(Stream& stream, ANMFChunk const& chunk)
     //  MUST be 0. Readers MUST ignore this field."
 
     // "Blending method (B): 1 bit"
-    if (chunk.blending_method == ANMFChunk::BlendingMethod::DoNotBlend)
+    if (chunk.blending_method == ANMFChunkHeader::BlendingMethod::DoNotBlend)
         flags |= 0x2;
 
     // "Disposal method (D): 1 bit"
-    if (chunk.disposal_method == ANMFChunk::DisposalMethod::DisposeToBackgroundColor)
+    if (chunk.disposal_method == ANMFChunkHeader::DisposalMethod::DisposeToBackgroundColor)
         flags |= 0x1;
 
     TRY(bit_stream.write_bits(flags, 8u));
@@ -426,9 +426,9 @@ static ErrorOr<void> write_ANMF_chunk(Stream& stream, ANMFChunk const& chunk)
     // FIXME: Make ~LittleEndianOutputBitStream do this, or make it VERIFY() that it has happened at least.
     TRY(bit_stream.flush_buffer_to_stream());
 
-    TRY(stream.write_until_depleted(chunk.frame_data));
+    TRY(stream.write_until_depleted(frame_data));
 
-    if (chunk.frame_data.size() % 2 != 0)
+    if (frame_data.size() % 2 != 0)
         TRY(stream.write_value<u8>(0));
 
     return {};
@@ -447,17 +447,16 @@ ErrorOr<void> WebPAnimationWriter::add_frame(Bitmap& bitmap, int duration_ms, In
     TRY(write_VP8L_chunk(vp8l_chunk_stream, bitmap.width(), bitmap.height(), true, vp8l_data_bytes));
     auto vp8l_chunk_bytes = TRY(vp8l_chunk_stream.read_until_eof());
 
-    ANMFChunk chunk;
+    ANMFChunkHeader chunk;
     chunk.frame_x = static_cast<u32>(at.x());
     chunk.frame_y = static_cast<u32>(at.y());
     chunk.frame_width = static_cast<u32>(bitmap.width());
     chunk.frame_height = static_cast<u32>(bitmap.height());
     chunk.frame_duration_in_milliseconds = static_cast<u32>(duration_ms);
-    chunk.blending_method = ANMFChunk::BlendingMethod::DoNotBlend;
-    chunk.disposal_method = ANMFChunk::DisposalMethod::DoNotDispose;
-    chunk.frame_data = vp8l_chunk_bytes;
+    chunk.blending_method = ANMFChunkHeader::BlendingMethod::DoNotBlend;
+    chunk.disposal_method = ANMFChunkHeader::DisposalMethod::DoNotDispose;
 
-    TRY(write_ANMF_chunk(m_stream, chunk));
+    TRY(write_ANMF_chunk(m_stream, chunk, vp8l_chunk_bytes));
 
     TRY(update_size_in_header());