From 832a065687f0eba26b1201344c4a3c10fc204d2a Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 6 Dec 2023 18:53:19 -0500 Subject: [PATCH] LibPDF: For low-bpp images, start scanlines on byte boundaries Required per spec, and we get slanted images without it. Fixes e.g. page 1 of 0000749.pdf. --- Userland/Libraries/LibPDF/Renderer.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index f4280bf30a..152ee345c9 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -831,12 +831,14 @@ enum UpsampleMode { StoreValuesUnchanged, UpsampleTo8Bit, }; -static Vector upsample_to_8_bit(ReadonlyBytes content, int bits_per_component, UpsampleMode mode) +static Vector upsample_to_8_bit(ReadonlyBytes content, int samples_per_line, int bits_per_component, UpsampleMode mode) { VERIFY(bits_per_component == 1 || bits_per_component == 2 || bits_per_component == 4); Vector upsampled_storage; upsampled_storage.ensure_capacity(content.size() * 8 / bits_per_component); u8 const mask = (1 << bits_per_component) - 1; + + int x = 0; for (auto byte : content) { for (int i = 0; i < 8; i += bits_per_component) { auto value = (byte >> (8 - bits_per_component - i)) & mask; @@ -844,6 +846,13 @@ static Vector upsample_to_8_bit(ReadonlyBytes content, int bits_per_componen upsampled_storage.append(value * (255 / mask)); else upsampled_storage.append(value); + ++x; + + // "Byte boundaries are ignored, except that each row of sample data must begin on a byte boundary." + if (x == samples_per_line) { + x = 0; + break; + } } } return upsampled_storage; @@ -900,10 +909,12 @@ PDFErrorOr> Renderer::load_image(NonnullRefPtrbytes(); + int const n_components = color_space->number_of_components(); + Vector upsampled_storage; if (bits_per_component < 8) { UpsampleMode mode = color_space->family() == ColorSpaceFamily::Indexed ? UpsampleMode::StoreValuesUnchanged : UpsampleMode::UpsampleTo8Bit; - upsampled_storage = upsample_to_8_bit(content, bits_per_component, mode); + upsampled_storage = upsample_to_8_bit(content, width * n_components, bits_per_component, mode); content = upsampled_storage; bits_per_component = 8; } @@ -934,7 +945,6 @@ PDFErrorOr> Renderer::load_image(NonnullRefPtrnumber_of_components(); auto const bytes_per_component = bits_per_component / 8; Vector component_values; component_values.resize(n_components);