diff --git a/Userland/Libraries/LibCompress/Huffman.h b/Userland/Libraries/LibCompress/Huffman.h index b18776c18d3..eae26e3909c 100644 --- a/Userland/Libraries/LibCompress/Huffman.h +++ b/Userland/Libraries/LibCompress/Huffman.h @@ -13,7 +13,7 @@ namespace Compress { template -void generate_huffman_lengths(Array& lengths, Array const& frequencies, size_t max_bit_length, u16 frequency_cap = UINT16_MAX) +void generate_huffman_lengths(Array& lengths, Array const& frequencies, size_t max_bit_length, u16 shift = 0) { VERIFY((1u << max_bit_length) >= Size); u16 heap_keys[Size]; // Used for O(n) heap construction @@ -26,9 +26,7 @@ void generate_huffman_lengths(Array& lengths, Array const& if (frequency == 0) continue; - if (frequency > frequency_cap) { - frequency = frequency_cap; - } + frequency = max(1, frequency >> shift); heap_keys[non_zero_freqs] = frequency; // sort symbols by frequency heap_values[non_zero_freqs] = Size + non_zero_freqs; // huffman_links "links" @@ -78,8 +76,8 @@ void generate_huffman_lengths(Array& lengths, Array const& } if (bit_length > max_bit_length) { - VERIFY(frequency_cap != 1); - return generate_huffman_lengths(lengths, frequencies, max_bit_length, frequency_cap / 2); + VERIFY(shift < 15); + return generate_huffman_lengths(lengths, frequencies, max_bit_length, shift + 1); } lengths[i] = bit_length; diff --git a/Userland/Libraries/LibGfx/ImageFormats/WebPWriterLossless.cpp b/Userland/Libraries/LibGfx/ImageFormats/WebPWriterLossless.cpp index b90a318e8be..cb1813969bf 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/WebPWriterLossless.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/WebPWriterLossless.cpp @@ -257,12 +257,6 @@ static ErrorOr write_VP8L_image_data(Stream& stream, Bitmap const& bitmap) // We do use huffman coding by writing a single prefix-code-group for the entire image. // FIXME: Consider using a meta-prefix image and using one prefix-code-group per tile. - // FIXME: generate_huffman_lengths() currently halves a frequency cap if the maximum bit length is reached. - // This has the effect of giving very frequent symbols a higher bit length than they would have otherwise. - // Instead, try dividing frequencies by 2 if the maximum bit length is reached. - // Then, low-frequency symbols will get a higher bit length than they would have otherwise, which might help - // compressed size. (For deflate, it doesn't matter much since their blocks are 64kiB large, but for WebP - // we currently use a single huffman tree per channel for the entire image.) Array, 4> symbol_frequencies {}; for (ARGB32 pixel : bitmap) { static constexpr auto saturating_increment = [](u16& value) {