From 06b9633da58d542c0070074ec0c541e23dbc8d49 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 6 Dec 2023 18:47:00 -0500 Subject: [PATCH] LibPDF: For indexed images with 1, 2 or 4 bpp, do not repeat bit pattern When upsampling e.g. the 4-bit value 0b1101 to 8-bit, we used to repeat the value to fill the full 8-bits, e.g. 0b11011101. This maps RGB colors to 8-bit nicely, but is the wrong thing to do for palette indices. Stop doing this for palette indices. Fixes "Indexed color space index out of range" for 11 files in the PDF/A 0000.zip test set now that we correctly handle palette indices as of the previous commit: Malformed PDF file: Indexed color space lookup table doesn't match size, in 4 files, on 8 pages, 73 times path/to/0000/0000206.pdf 2 4 (2x) 5 (3x) 6 (4x) path/to/0000/0000364.pdf 5 6 path/to/0000/0000918.pdf 5 path/to/0000/0000683.pdf 8 --- Userland/Libraries/LibPDF/Renderer.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index b65e21ae55..f4280bf30a 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -827,7 +827,11 @@ PDFErrorOr Renderer::show_text(DeprecatedString const& string) return {}; } -static Vector upsample_to_8_bit(ReadonlyBytes content, int bits_per_component) +enum UpsampleMode { + StoreValuesUnchanged, + UpsampleTo8Bit, +}; +static Vector upsample_to_8_bit(ReadonlyBytes content, int bits_per_component, UpsampleMode mode) { VERIFY(bits_per_component == 1 || bits_per_component == 2 || bits_per_component == 4); Vector upsampled_storage; @@ -836,7 +840,10 @@ static Vector upsample_to_8_bit(ReadonlyBytes content, int bits_per_componen for (auto byte : content) { for (int i = 0; i < 8; i += bits_per_component) { auto value = (byte >> (8 - bits_per_component - i)) & mask; - upsampled_storage.append(value * (255 / mask)); + if (mode == UpsampleMode::UpsampleTo8Bit) + upsampled_storage.append(value * (255 / mask)); + else + upsampled_storage.append(value); } } return upsampled_storage; @@ -895,7 +902,8 @@ PDFErrorOr> Renderer::load_image(NonnullRefPtr upsampled_storage; if (bits_per_component < 8) { - upsampled_storage = upsample_to_8_bit(content, bits_per_component); + UpsampleMode mode = color_space->family() == ColorSpaceFamily::Indexed ? UpsampleMode::StoreValuesUnchanged : UpsampleMode::UpsampleTo8Bit; + upsampled_storage = upsample_to_8_bit(content, bits_per_component, mode); content = upsampled_storage; bits_per_component = 8; }