Rendering intents for images

This commit is contained in:
Jakub Melka 2019-10-18 17:28:45 +02:00
parent a35957cb53
commit 14419980cc
5 changed files with 60 additions and 6 deletions

View File

@ -558,7 +558,18 @@ PDFImageData PDFCCITTFaxDecoder::decode()
codingLine[0] = 0; 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<PDFReal> 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() void PDFCCITTFaxDecoder::skipFill()

View File

@ -65,6 +65,10 @@ struct PDFCCITTFaxDecoderParameters
/// then 0 means black pixel and 1 white pixel. /// then 0 means black pixel and 1 white pixel.
bool hasBlackIsOne = false; bool hasBlackIsOne = false;
/// Decode
std::vector<PDFReal> decode;
/// Masking type
PDFImageData::MaskingType maskingType = PDFImageData::MaskingType::None; PDFImageData::MaskingType maskingType = PDFImageData::MaskingType::None;
}; };

View File

@ -46,10 +46,16 @@ struct PDFJPEGDCTSource
int startByte = 0; 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; PDFImage image;
image.m_colorSpace = colorSpace; image.m_colorSpace = colorSpace;
image.m_renderingIntent = renderingIntent;
const PDFDictionary* dictionary = stream->getDictionary(); const PDFDictionary* dictionary = stream->getDictionary();
QByteArray content = document->getDecodedStream(stream); 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).")); 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 // Fill Mask
if (dictionary->hasKey("Mask")) if (dictionary->hasKey("Mask"))
{ {
@ -98,7 +126,7 @@ PDFImage PDFImage::createImage(const PDFDocument* document, const PDFStream* str
else if (object.isStream()) else if (object.isStream())
{ {
// TODO: Implement Mask Image // 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; maskingType = PDFImageData::MaskingType::Image;
throw PDFRendererException(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Mask image is not implemented.")); 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()) 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; maskingType = PDFImageData::MaskingType::SoftMask;
image.m_softMask = qMove(softMaskImage.m_imageData); 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.hasEndOfBlock = loader.readBooleanFromDictionary(filterParamsDictionary, "EndOfBlock", true);
parameters.hasBlackIsOne = loader.readBooleanFromDictionary(filterParamsDictionary, "BlackIs1", false); parameters.hasBlackIsOne = loader.readBooleanFromDictionary(filterParamsDictionary, "BlackIs1", false);
parameters.damagedRowsBeforeError = loader.readIntegerFromDictionary(filterParamsDictionary, "DamagedRowsBeforeError", 0); parameters.damagedRowsBeforeError = loader.readIntegerFromDictionary(filterParamsDictionary, "DamagedRowsBeforeError", 0);
parameters.decode = !decode.empty() ? qMove(decode) : std::vector<PDFReal>({ 0.0, 1.0 });
QByteArray imageDataBuffer = document->getDecodedStream(stream); QByteArray imageDataBuffer = document->getDecodedStream(stream);
PDFCCITTFaxDecoder decoder(&imageDataBuffer, parameters); PDFCCITTFaxDecoder decoder(&imageDataBuffer, parameters);

View File

@ -39,18 +39,28 @@ public:
/// \param stream Stream with image /// \param stream Stream with image
/// \param colorSpace Color space of the image /// \param colorSpace Color space of the image
/// \param isSoftMask Is it a soft mask 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) /// \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 /// Returns image transformed from image data and color space
QImage getImage() const; QImage getImage() const;
/// Returns rendering intent of the image
RenderingIntent getRenderingIntent() const { return m_renderingIntent; }
private: private:
PDFImage() = default; PDFImage() = default;
PDFImageData m_imageData; PDFImageData m_imageData;
PDFImageData m_softMask; PDFImageData m_softMask;
PDFColorSpacePointer m_colorSpace; PDFColorSpacePointer m_colorSpace;
RenderingIntent m_renderingIntent = RenderingIntent::Perceptual;
}; };
} // namespace pdf } // namespace pdf

View File

@ -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(); QImage image = pdfImage.getImage();
if (image.format() == QImage::Format_Alpha8) if (image.format() == QImage::Format_Alpha8)