ladybird/Userland/Libraries/LibGfx/ImageFormats/WebPSharedLossless.cpp
Nico Weber 7aa61ca49b LibGfx/WebP: Add CanonicalCode::write_symbol(), use it in writer
We still construct the code length codes manually, and now we also
construct a PrefixCodeGroup manually that assigns 8 bits to all
symbols (except for fully-opaque alpha channels, and for the
unused distance codes, like before). But now we use the CanonicalCodes
from that PrefixCodeGroup for writing.

No behavior change at all, the output is bit-for-bit identical to
before. But this is a step towards actually huffman-coding symbols.

This is however a pretty big perf regression. For
`image -o test.webp test.bmp` (where test.bmp is retro-sunset.png
re-encoded as bmp), time goes from 23.7 ms to 33.2 ms.

`animation -o wow.webp giphy.gif` goes from 85.5 ms to 127.7 ms.

`animation -o wow.webp 7z7c.gif` goes from 12.6 ms to 16.5 ms.
2024-05-20 13:17:34 -04:00

43 lines
1.3 KiB
C++

/*
* Copyright (c) 2024, Nico Weber <thakis@chromium.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/ImageFormats/WebPSharedLossless.h>
namespace Gfx {
ErrorOr<CanonicalCode> CanonicalCode::from_bytes(ReadonlyBytes bytes)
{
auto non_zero_symbol_count = 0;
auto last_non_zero_symbol = -1;
for (size_t i = 0; i < bytes.size(); i++) {
if (bytes[i] != 0) {
non_zero_symbol_count++;
last_non_zero_symbol = i;
}
}
if (non_zero_symbol_count == 1)
return CanonicalCode(last_non_zero_symbol);
return CanonicalCode(TRY(Compress::CanonicalCode::from_bytes(bytes)));
}
ErrorOr<u32> CanonicalCode::read_symbol(LittleEndianInputBitStream& bit_stream) const
{
return TRY(m_code.visit(
[](u32 single_code) -> ErrorOr<u32> { return single_code; },
[&bit_stream](Compress::CanonicalCode const& code) { return code.read_symbol(bit_stream); }));
}
ErrorOr<void> CanonicalCode::write_symbol(LittleEndianOutputBitStream& bit_stream, u32 symbol) const
{
TRY(m_code.visit(
[&](u32 single_code) -> ErrorOr<void> { VERIFY(symbol == single_code); return {};},
[&](Compress::CanonicalCode const& code) { return code.write_symbol(bit_stream, symbol); }));
return {};
}
}