1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 07:47:37 +00:00

LibPDF+LibGfx: Don't invert CMYK channels in JPEG data in PDFs

This is a hack: Ideally we'd have a CMYK Bitmap pixel format,
and we'd convert to rgb at blit time. Then we could also apply color
profiles (which for CMYK images are CMYK-based).

Also, the colors for our CMYK->RGB conversion are off for PDFs,
and we have distinct codepaths for this in Gfx::Color (for paths)
and JPEGs. So when we fix that, we'll have to fix it in two places.

But this doesn't require a lot of code and it's a huge visual
progression, so let's go with it for now.
This commit is contained in:
Nico Weber 2023-11-15 12:58:06 -05:00 committed by Sam Atkins
parent bd7ae7f91e
commit bfe27228a3
3 changed files with 26 additions and 6 deletions

View file

@ -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<NonnullOwnPtr<JPEGLoadingContext>> create(NonnullOwnPtr<Stream> stream)
static ErrorOr<NonnullOwnPtr<JPEGLoadingContext>> create(NonnullOwnPtr<Stream> stream, JPEGDecoderOptions options)
{
auto jpeg_stream = TRY(JPEGStream::create(move(stream)));
return make<JPEGLoadingContext>(move(jpeg_stream));
return make<JPEGLoadingContext>(move(jpeg_stream), options);
}
enum State {
@ -453,6 +454,7 @@ struct JPEGLoadingContext {
Array<i16, 4> previous_dc_values {};
MacroblockMeta mblock_meta;
JPEGStream stream;
JPEGDecoderOptions options;
Optional<ColorTransform> 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<Macroblock>& 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<NonnullOwnPtr<ImageDecoderPlugin>> JPEGImageDecoderPlugin::create(ReadonlyBytes data)
{
return create_with_options(data, {});
}
ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> JPEGImageDecoderPlugin::create_with_options(ReadonlyBytes data, JPEGDecoderOptions options)
{
auto stream = TRY(try_make<FixedMemoryStream>(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;