From 14419980cc8ef1511d73ae3a5f7085d69baae92c Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Fri, 18 Oct 2019 17:28:45 +0200 Subject: [PATCH] Rendering intents for images --- PdfForQtLib/sources/pdfccittfaxdecoder.cpp | 13 ++++++- PdfForQtLib/sources/pdfccittfaxdecoder.h | 4 +++ PdfForQtLib/sources/pdfimage.cpp | 35 +++++++++++++++++-- PdfForQtLib/sources/pdfimage.h | 12 ++++++- .../sources/pdfpagecontentprocessor.cpp | 2 +- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/PdfForQtLib/sources/pdfccittfaxdecoder.cpp b/PdfForQtLib/sources/pdfccittfaxdecoder.cpp index ffe45bf..81ba858 100644 --- a/PdfForQtLib/sources/pdfccittfaxdecoder.cpp +++ b/PdfForQtLib/sources/pdfccittfaxdecoder.cpp @@ -558,7 +558,18 @@ PDFImageData PDFCCITTFaxDecoder::decode() codingLine[0] = 0; } - return PDFImageData(1, 1, m_parameters.columns, row, (m_parameters.columns + 7) / 8, m_parameters.maskingType, writer.takeByteArray(), { }, { }, { }); + Q_ASSERT(m_parameters.decode.size() == 2); + std::vector decode; + if (m_parameters.hasBlackIsOne) + { + decode = { m_parameters.decode[1], m_parameters.decode[0] }; + } + else + { + decode = { m_parameters.decode[0], m_parameters.decode[1] }; + } + + return PDFImageData(1, 1, m_parameters.columns, row, (m_parameters.columns + 7) / 8, m_parameters.maskingType, writer.takeByteArray(), { }, qMove(decode), { }); } void PDFCCITTFaxDecoder::skipFill() diff --git a/PdfForQtLib/sources/pdfccittfaxdecoder.h b/PdfForQtLib/sources/pdfccittfaxdecoder.h index 601a1bc..c863fdb 100644 --- a/PdfForQtLib/sources/pdfccittfaxdecoder.h +++ b/PdfForQtLib/sources/pdfccittfaxdecoder.h @@ -65,6 +65,10 @@ struct PDFCCITTFaxDecoderParameters /// then 0 means black pixel and 1 white pixel. bool hasBlackIsOne = false; + /// Decode + std::vector decode; + + /// Masking type PDFImageData::MaskingType maskingType = PDFImageData::MaskingType::None; }; diff --git a/PdfForQtLib/sources/pdfimage.cpp b/PdfForQtLib/sources/pdfimage.cpp index d69be33..81f577f 100644 --- a/PdfForQtLib/sources/pdfimage.cpp +++ b/PdfForQtLib/sources/pdfimage.cpp @@ -46,10 +46,16 @@ struct PDFJPEGDCTSource int startByte = 0; }; -PDFImage PDFImage::createImage(const PDFDocument* document, const PDFStream* stream, PDFColorSpacePointer colorSpace, bool isSoftMask, PDFRenderErrorReporter* errorReporter) +PDFImage PDFImage::createImage(const PDFDocument* document, + const PDFStream* stream, + PDFColorSpacePointer colorSpace, + bool isSoftMask, + RenderingIntent renderingIntent, + PDFRenderErrorReporter* errorReporter) { PDFImage image; image.m_colorSpace = colorSpace; + image.m_renderingIntent = renderingIntent; const PDFDictionary* dictionary = stream->getDictionary(); QByteArray content = document->getDecodedStream(stream); @@ -86,6 +92,28 @@ PDFImage PDFImage::createImage(const PDFDocument* document, const PDFStream* str throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Regular image can't have Matte entry (used for soft masks).")); } + // Set rendering intent + if (dictionary->hasKey("Intent")) + { + QByteArray renderingIntentName = loader.readNameFromDictionary(dictionary, "Intent"); + if (renderingIntentName == "Perceptual") + { + image.m_renderingIntent = RenderingIntent::Perceptual; + } + else if (renderingIntentName == "AbsoluteColorimetric") + { + image.m_renderingIntent = RenderingIntent::AbsoluteColorimetric; + } + else if (renderingIntentName == "RelativeColorimetric") + { + image.m_renderingIntent = RenderingIntent::RelativeColorimetric; + } + else if (renderingIntentName == "Saturation") + { + image.m_renderingIntent = RenderingIntent::Saturation; + } + } + // Fill Mask if (dictionary->hasKey("Mask")) { @@ -98,7 +126,7 @@ PDFImage PDFImage::createImage(const PDFDocument* document, const PDFStream* str else if (object.isStream()) { // TODO: Implement Mask Image - PDFImage maskImage = createImage(document, object.getStream(), colorSpace, false, errorReporter); + PDFImage maskImage = createImage(document, object.getStream(), colorSpace, false, renderingIntent, errorReporter); maskingType = PDFImageData::MaskingType::Image; throw PDFRendererException(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Mask image is not implemented.")); } @@ -110,7 +138,7 @@ PDFImage PDFImage::createImage(const PDFDocument* document, const PDFStream* str if (softMaskObject.isStream()) { - PDFImage softMaskImage = createImage(document, softMaskObject.getStream(), PDFColorSpacePointer(new PDFDeviceGrayColorSpace()), true, errorReporter); + PDFImage softMaskImage = createImage(document, softMaskObject.getStream(), PDFColorSpacePointer(new PDFDeviceGrayColorSpace()), true, renderingIntent, errorReporter); maskingType = PDFImageData::MaskingType::SoftMask; image.m_softMask = qMove(softMaskImage.m_imageData); } @@ -530,6 +558,7 @@ PDFImage PDFImage::createImage(const PDFDocument* document, const PDFStream* str parameters.hasEndOfBlock = loader.readBooleanFromDictionary(filterParamsDictionary, "EndOfBlock", true); parameters.hasBlackIsOne = loader.readBooleanFromDictionary(filterParamsDictionary, "BlackIs1", false); parameters.damagedRowsBeforeError = loader.readIntegerFromDictionary(filterParamsDictionary, "DamagedRowsBeforeError", 0); + parameters.decode = !decode.empty() ? qMove(decode) : std::vector({ 0.0, 1.0 }); QByteArray imageDataBuffer = document->getDecodedStream(stream); PDFCCITTFaxDecoder decoder(&imageDataBuffer, parameters); diff --git a/PdfForQtLib/sources/pdfimage.h b/PdfForQtLib/sources/pdfimage.h index 4650f64..4f22fd6 100644 --- a/PdfForQtLib/sources/pdfimage.h +++ b/PdfForQtLib/sources/pdfimage.h @@ -39,18 +39,28 @@ public: /// \param stream Stream with image /// \param colorSpace Color space of the image /// \param isSoftMask Is it a soft mask image? + /// \param renderingIntent Default rendering intent of the image /// \param errorReporter Error reporter for reporting errors (or warnings) - static PDFImage createImage(const PDFDocument* document, const PDFStream* stream, PDFColorSpacePointer colorSpace, bool isSoftMask, PDFRenderErrorReporter* errorReporter); + static PDFImage createImage(const PDFDocument* document, + const PDFStream* stream, + PDFColorSpacePointer colorSpace, + bool isSoftMask, + RenderingIntent renderingIntent, + PDFRenderErrorReporter* errorReporter); /// Returns image transformed from image data and color space QImage getImage() const; + /// Returns rendering intent of the image + RenderingIntent getRenderingIntent() const { return m_renderingIntent; } + private: PDFImage() = default; PDFImageData m_imageData; PDFImageData m_softMask; PDFColorSpacePointer m_colorSpace; + RenderingIntent m_renderingIntent = RenderingIntent::Perceptual; }; } // namespace pdf diff --git a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp index 12e0111..d872de3 100644 --- a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp +++ b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp @@ -2663,7 +2663,7 @@ void PDFPageContentProcessor::paintXObjectImage(const PDFStream* stream) } } - PDFImage pdfImage = PDFImage::createImage(m_document, stream, qMove(colorSpace), false, this); + PDFImage pdfImage = PDFImage::createImage(m_document, stream, qMove(colorSpace), false, m_graphicState.getRenderingIntent(), this); QImage image = pdfImage.getImage(); if (image.format() == QImage::Format_Alpha8)