LibGfx/WebPWriter: Let compress_VP8L_image*() return if image was opaque

We compute that as part of compression there anyways, so let's compute
it only once.

No behavior change.
This commit is contained in:
Nico Weber 2024-05-27 20:03:57 -04:00 committed by Sam Atkins
parent ab0219bb08
commit 2d80a5c6ca
Notes: sideshowbarker 2024-07-16 23:51:07 +09:00
3 changed files with 14 additions and 19 deletions

View File

@ -67,15 +67,6 @@ static ErrorOr<void> write_VP8L_header(Stream& stream, unsigned width, unsigned
return {};
}
static bool are_all_pixels_opaque(Bitmap const& bitmap)
{
for (ARGB32 pixel : bitmap) {
if ((pixel >> 24) != 0xff)
return false;
}
return true;
}
// FIXME: Consider using LibRIFF for RIFF writing details. (It currently has no writing support.)
static ErrorOr<void> align_to_two(Stream& stream, size_t number_of_bytes_written)
{
@ -190,11 +181,11 @@ static ErrorOr<void> align_to_two(AllocatingMemoryStream& stream)
ErrorOr<void> WebPWriter::encode(Stream& stream, Bitmap const& bitmap, Options const& options)
{
bool alpha_is_used_hint = !are_all_pixels_opaque(bitmap);
dbgln_if(WEBP_DEBUG, "Writing WebP of size {} with alpha hint: {}", bitmap.size(), alpha_is_used_hint);
// The chunk headers need to know their size, so we either need a SeekableStream or need to buffer the data. We're doing the latter.
auto vp8l_data_bytes = TRY(compress_VP8L_image_data(bitmap));
bool is_fully_opaque;
auto vp8l_data_bytes = TRY(compress_VP8L_image_data(bitmap, is_fully_opaque));
bool alpha_is_used_hint = !is_fully_opaque;
dbgln_if(WEBP_DEBUG, "Writing WebP of size {} with alpha hint: {}", bitmap.size(), alpha_is_used_hint);
ByteBuffer vp8x_chunk_bytes;
ByteBuffer iccp_chunk_bytes;
@ -315,7 +306,8 @@ ErrorOr<void> WebPAnimationWriter::add_frame(Bitmap& bitmap, int duration_ms, In
// 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));
bool is_fully_opaque;
auto vp8l_data_bytes = TRY(compress_VP8L_image_data(bitmap, is_fully_opaque));
ANMFChunkHeader chunk;
chunk.frame_x = static_cast<u32>(at.x());
@ -331,7 +323,7 @@ ErrorOr<void> WebPAnimationWriter::add_frame(Bitmap& bitmap, int duration_ms, In
TRY(update_size_in_header());
if (!(m_vp8x_flags & 0x10) && !are_all_pixels_opaque(bitmap))
if (!(m_vp8x_flags & 0x10) && !is_fully_opaque)
TRY(set_alpha_bit_in_header());
return {};

View File

@ -213,7 +213,7 @@ static ErrorOr<CanonicalCode> write_normal_code_lengths(LittleEndianOutputBitStr
return CanonicalCode::from_bytes(bit_lengths.span().trim(code_count));
}
static ErrorOr<void> write_VP8L_image_data(Stream& stream, Bitmap const& bitmap)
static ErrorOr<void> write_VP8L_image_data(Stream& stream, Bitmap const& bitmap, bool& is_fully_opaque)
{
LittleEndianOutputBitStream bit_stream { MaybeOwned<Stream>(stream) };
@ -291,6 +291,9 @@ static ErrorOr<void> write_VP8L_image_data(Stream& stream, Bitmap const& bitmap)
prefix_code_group[i] = TRY(write_simple_code_lengths(bit_stream, { symbols, non_zero_symbol_count }));
else
prefix_code_group[i] = TRY(write_normal_code_lengths(bit_stream, code_lengths[i], alphabet_sizes[i]));
if (i == 3)
is_fully_opaque = non_zero_symbol_count == 1 && symbols[0] == 0xff;
}
// For code #5, use a simple empty code, since we don't use this yet.
@ -306,10 +309,10 @@ static ErrorOr<void> write_VP8L_image_data(Stream& stream, Bitmap const& bitmap)
return {};
}
ErrorOr<ByteBuffer> compress_VP8L_image_data(Bitmap const& bitmap)
ErrorOr<ByteBuffer> compress_VP8L_image_data(Bitmap const& bitmap, bool& is_fully_opaque)
{
AllocatingMemoryStream vp8l_data_stream;
TRY(write_VP8L_image_data(vp8l_data_stream, bitmap));
TRY(write_VP8L_image_data(vp8l_data_stream, bitmap, is_fully_opaque));
return vp8l_data_stream.read_until_eof();
}

View File

@ -11,6 +11,6 @@
namespace Gfx {
ErrorOr<ByteBuffer> compress_VP8L_image_data(Bitmap const&);
ErrorOr<ByteBuffer> compress_VP8L_image_data(Bitmap const&, bool& is_fully_opaque);
}