From e770cf06b0d8cf1ea630d99353f6e63453094616 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sun, 7 Jan 2024 22:12:20 -0500 Subject: [PATCH] LibPDF: Send jpeg data down the same path as all other data JPEG images now honor decode arrays and color spaces. --- Userland/Libraries/LibPDF/Filter.cpp | 36 ++++++++++++++++++++++---- Userland/Libraries/LibPDF/Renderer.cpp | 5 ---- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Userland/Libraries/LibPDF/Filter.cpp b/Userland/Libraries/LibPDF/Filter.cpp index 00f4dfe5891..2fd170391f9 100644 --- a/Userland/Libraries/LibPDF/Filter.cpp +++ b/Userland/Libraries/LibPDF/Filter.cpp @@ -226,12 +226,38 @@ PDFErrorOr Filter::decode_jbig2(ReadonlyBytes) PDFErrorOr Filter::decode_dct(ReadonlyBytes bytes) { - if (Gfx::JPEGImageDecoderPlugin::sniff({ bytes.data(), bytes.size() })) { - auto decoder = TRY(Gfx::JPEGImageDecoderPlugin::create_with_options({ bytes.data(), bytes.size() }, { .cmyk = Gfx::JPEGDecoderOptions::CMYK::PDF })); - auto frame = TRY(decoder->frame(0)); - return TRY(frame.image->serialize_to_byte_buffer()); + if (!Gfx::JPEGImageDecoderPlugin::sniff({ bytes.data(), bytes.size() })) + return AK::Error::from_string_literal("Not a JPEG image!"); + + auto decoder = TRY(Gfx::JPEGImageDecoderPlugin::create_with_options({ bytes.data(), bytes.size() }, { .cmyk = Gfx::JPEGDecoderOptions::CMYK::PDF })); + auto internal_format = decoder->natural_frame_format(); + + if (internal_format == Gfx::NaturalFrameFormat::CMYK) { + auto bitmap = TRY(decoder->cmyk_frame()); + // FIXME: Could give CMYKBitmap a method to steal its internal ByteBuffer. + auto size = bitmap->size().width() * bitmap->size().height() * 4; + auto buffer = TRY(ByteBuffer::create_uninitialized(size)); + buffer.overwrite(0, bitmap->scanline(0), size); + return buffer; } - return AK::Error::from_string_literal("Not a JPEG image!"); + + auto bitmap = TRY(decoder->frame(0)).image; + auto size = bitmap->size().width() * bitmap->size().height() * (internal_format == Gfx::NaturalFrameFormat::Grayscale ? 1 : 3); + ByteBuffer buffer; + TRY(buffer.try_ensure_capacity(size)); + + for (auto& pixel : *bitmap) { + Color color = Color::from_argb(pixel); + if (internal_format == Gfx::NaturalFrameFormat::Grayscale) { + // Either channel is fine, they're all the same. + buffer.append(color.red()); + } else { + buffer.append(color.red()); + buffer.append(color.green()); + buffer.append(color.blue()); + } + } + return buffer; } PDFErrorOr Filter::decode_jpx(ReadonlyBytes) diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index 508088285b1..87d166b52dd 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -1124,11 +1124,6 @@ PDFErrorOr Renderer::load_image(NonnullRefPtr to avoid serialisation/deserialisation here - return LoadedImage { TRY(Gfx::Bitmap::create_from_serialized_bytes(image->bytes())), is_image_mask }; - } - auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { width, height })); int x = 0; int y = 0;