瀏覽代碼

LibGfx/WebPWriter: Remove a copy in the animated frame writing code path

This code path now also compresses to memory once, and then writes to
the output stream.

Since the animation writer has a SeekableStream, it could compress to
the stream directly and fix up offsets later. That's more complicated
though, and keeping the animated and non-animated code paths similar
seems nice. And the drawback is just temporary higher memory use, and
the used memory is smaller than the memory needed by the input bitmap.
Nico Weber 1 年之前
父節點
當前提交
c0f67a0188
共有 1 個文件被更改,包括 5 次插入10 次删除
  1. 5 10
      Userland/Libraries/LibGfx/ImageFormats/WebPWriter.cpp

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

@@ -434,14 +434,11 @@ ErrorOr<void> WebPAnimationWriter::add_frame(Bitmap& bitmap, int duration_ms, In
     if (at.x() < 0 || at.y() < 0 || at.x() + bitmap.width() > m_dimensions.width() || at.y() + bitmap.height() > m_dimensions.height())
         return Error::from_string_literal("Frame does not fit in animation dimensions");
 
-    // FIXME: The whole writing-and-reading-into-buffer over-and-over is awkward and inefficient.
-
+    // Since we have a SeekableStream, we could write both the VP8L chunk header and the ANMF chunk header with a placeholder size,
+    // compress the frame data directly to the stream, and then go back and update the two sizes.
+    // That's pretty messy though, and the compressed image data is smaller than the uncompressed bitmap passed in. So we'll buffer it.
     auto vp8l_data_bytes = TRY(compress_VP8L_image_data(bitmap));
 
-    AllocatingMemoryStream vp8l_chunk_stream;
-    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());
-
     ANMFChunkHeader chunk;
     chunk.frame_x = static_cast<u32>(at.x());
     chunk.frame_y = static_cast<u32>(at.y());
@@ -451,10 +448,8 @@ ErrorOr<void> WebPAnimationWriter::add_frame(Bitmap& bitmap, int duration_ms, In
     chunk.blending_method = ANMFChunkHeader::BlendingMethod::DoNotBlend;
     chunk.disposal_method = ANMFChunkHeader::DisposalMethod::DoNotDispose;
 
-    TRY(write_ANMF_chunk_header(m_stream, chunk, vp8l_chunk_bytes.size()));
-
-    TRY(m_stream.write_until_depleted(vp8l_chunk_bytes));
-    VERIFY(vp8l_chunk_bytes.size() % 2 == 0);
+    TRY(write_ANMF_chunk_header(m_stream, chunk, compute_VP8L_chunk_size(vp8l_data_bytes)));
+    TRY(write_VP8L_chunk(m_stream, bitmap.width(), bitmap.height(), true, vp8l_data_bytes));
 
     TRY(update_size_in_header());