diff --git a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp index 01668dc037..89662c8461 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp @@ -416,15 +416,16 @@ enum class ColorTransform { }; struct JPEGLoadingContext { - JPEGLoadingContext(JPEGStream jpeg_stream) + JPEGLoadingContext(JPEGStream jpeg_stream, JPEGDecoderOptions options) : stream(move(jpeg_stream)) + , options(options) { } - static ErrorOr> create(NonnullOwnPtr stream) + static ErrorOr> create(NonnullOwnPtr stream, JPEGDecoderOptions options) { auto jpeg_stream = TRY(JPEGStream::create(move(stream))); - return make(move(jpeg_stream)); + return make(move(jpeg_stream), options); } enum State { @@ -453,6 +454,7 @@ struct JPEGLoadingContext { Array previous_dc_values {}; MacroblockMeta mblock_meta; JPEGStream stream; + JPEGDecoderOptions options; Optional color_transform {}; @@ -1640,7 +1642,8 @@ static void invert_colors_for_adobe_images(JPEGLoadingContext const& context, Ve static void cmyk_to_rgb(JPEGLoadingContext const& context, Vector& macroblocks) { - invert_colors_for_adobe_images(context, macroblocks); + if (context.options.cmyk == JPEGDecoderOptions::CMYK::Normal) + invert_colors_for_adobe_images(context, macroblocks); for (u32 vcursor = 0; vcursor < context.mblock_meta.vcount; vcursor += context.vsample_factor) { for (u32 hcursor = 0; hcursor < context.mblock_meta.hcount; hcursor += context.hsample_factor) { @@ -1944,9 +1947,14 @@ bool JPEGImageDecoderPlugin::sniff(ReadonlyBytes data) } ErrorOr> JPEGImageDecoderPlugin::create(ReadonlyBytes data) +{ + return create_with_options(data, {}); +} + +ErrorOr> JPEGImageDecoderPlugin::create_with_options(ReadonlyBytes data, JPEGDecoderOptions options) { auto stream = TRY(try_make(data)); - auto context = TRY(JPEGLoadingContext::create(move(stream))); + auto context = TRY(JPEGLoadingContext::create(move(stream), options)); auto plugin = TRY(adopt_nonnull_own_or_enomem(new (nothrow) JPEGImageDecoderPlugin(move(context)))); TRY(decode_header(*plugin->m_context)); return plugin; diff --git a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.h b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.h index b238e1c74a..f6ca410c18 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.h +++ b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.h @@ -16,10 +16,22 @@ struct JPEGLoadingContext; // For the specification, see: https://www.w3.org/Graphics/JPEG/itu-t81.pdf +struct JPEGDecoderOptions { + enum class CMYK { + // For standalone jpeg files. + Normal, + + // For jpeg data embedded in PDF files. + PDF, + }; + CMYK cmyk { CMYK::Normal }; +}; + class JPEGImageDecoderPlugin : public ImageDecoderPlugin { public: static bool sniff(ReadonlyBytes); static ErrorOr> create(ReadonlyBytes); + static ErrorOr> create_with_options(ReadonlyBytes, JPEGDecoderOptions = {}); virtual ~JPEGImageDecoderPlugin() override; virtual IntSize size() override; diff --git a/Userland/Libraries/LibPDF/Filter.cpp b/Userland/Libraries/LibPDF/Filter.cpp index 18d2eb572c..f43de7969a 100644 --- a/Userland/Libraries/LibPDF/Filter.cpp +++ b/Userland/Libraries/LibPDF/Filter.cpp @@ -271,7 +271,7 @@ 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({ 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()); }