소스 검색

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
Nico Weber 1 년 전
부모
커밋
06b9633da5
1개의 변경된 파일11개의 추가작업 그리고 3개의 파일을 삭제
  1. 11 3
      Userland/Libraries/LibPDF/Renderer.cpp

+ 11 - 3
Userland/Libraries/LibPDF/Renderer.cpp

@@ -827,7 +827,11 @@ PDFErrorOr<void> Renderer::show_text(DeprecatedString const& string)
     return {};
 }
 
-static Vector<u8> upsample_to_8_bit(ReadonlyBytes content, int bits_per_component)
+enum UpsampleMode {
+    StoreValuesUnchanged,
+    UpsampleTo8Bit,
+};
+static Vector<u8> 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<u8> upsampled_storage;
@@ -836,7 +840,10 @@ static Vector<u8> 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<NonnullRefPtr<Gfx::Bitmap>> Renderer::load_image(NonnullRefPtr<Stream
 
     Vector<u8> 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;
     }