mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-01-30 17:14:50 +01:00
Color spaces and images - bugfixing, compliance to PDF 2.0 specification
This commit is contained in:
parent
8eedb45576
commit
7129793109
@ -1401,7 +1401,7 @@ PDFSeparationColorSpace::PDFSeparationColorSpace(QByteArray&& colorName, PDFColo
|
|||||||
|
|
||||||
QColor PDFSeparationColorSpace::getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
QColor PDFSeparationColorSpace::getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||||
{
|
{
|
||||||
return getColor(PDFColor(0.0f), cms, intent, reporter);
|
return getColor(PDFColor(1.0f), cms, intent, reporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor PDFSeparationColorSpace::getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
QColor PDFSeparationColorSpace::getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||||
@ -1528,9 +1528,10 @@ PDFDeviceNColorSpace::PDFDeviceNColorSpace(PDFDeviceNColorSpace::Type type,
|
|||||||
m_processColorSpace(qMove(processColorSpace)),
|
m_processColorSpace(qMove(processColorSpace)),
|
||||||
m_tintTransform(qMove(tintTransform)),
|
m_tintTransform(qMove(tintTransform)),
|
||||||
m_colorantsPrintingOrder(qMove(colorantsPrintingOrder)),
|
m_colorantsPrintingOrder(qMove(colorantsPrintingOrder)),
|
||||||
m_processColorSpaceComponents(qMove(processColorSpaceComponents))
|
m_processColorSpaceComponents(qMove(processColorSpaceComponents)),
|
||||||
|
m_isNone(false)
|
||||||
{
|
{
|
||||||
|
m_isNone = std::all_of(m_colorants.cbegin(), m_colorants.cend(), [](const auto& colorant) { return colorant.name == "None"; });
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor PDFDeviceNColorSpace::getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
QColor PDFDeviceNColorSpace::getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||||
@ -1550,6 +1551,13 @@ QColor PDFDeviceNColorSpace::getDefaultColor(const PDFCMS* cms, RenderingIntent
|
|||||||
|
|
||||||
QColor PDFDeviceNColorSpace::getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
QColor PDFDeviceNColorSpace::getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||||
{
|
{
|
||||||
|
// According to the PDF 2.0 specification, DeviceN color space, with all colorant name "None"
|
||||||
|
// should not produce any visible output.
|
||||||
|
if (m_isNone)
|
||||||
|
{
|
||||||
|
return Qt::transparent;
|
||||||
|
}
|
||||||
|
|
||||||
// Input values
|
// Input values
|
||||||
std::vector<double> inputColor(color.size(), 0.0);
|
std::vector<double> inputColor(color.size(), 0.0);
|
||||||
for (size_t i = 0, count = inputColor.size(); i < count; ++i)
|
for (size_t i = 0, count = inputColor.size(); i < count; ++i)
|
||||||
|
@ -678,6 +678,14 @@ public:
|
|||||||
/// Returns type of DeviceN color space
|
/// Returns type of DeviceN color space
|
||||||
Type getType() const { return m_type; }
|
Type getType() const { return m_type; }
|
||||||
|
|
||||||
|
const Colorants& getColorants() const { return m_colorants; }
|
||||||
|
const PDFColorSpacePointer& getAlternateColorSpace() const { return m_alternateColorSpace; }
|
||||||
|
const PDFColorSpacePointer& getProcessColorSpace() const { return m_processColorSpace; }
|
||||||
|
const PDFFunctionPtr& getTintTransform() const { return m_tintTransform; }
|
||||||
|
const std::vector<QByteArray>& getPrintingOrder() const { return m_colorantsPrintingOrder; }
|
||||||
|
const std::vector<QByteArray>& getProcessColorSpaceComponents() const { return m_processColorSpaceComponents; }
|
||||||
|
bool isNone() const { return m_isNone; }
|
||||||
|
|
||||||
/// Creates DeviceN color space from provided values.
|
/// Creates DeviceN color space from provided values.
|
||||||
/// \param colorSpaceDictionary Color space dictionary
|
/// \param colorSpaceDictionary Color space dictionary
|
||||||
/// \param document Document
|
/// \param document Document
|
||||||
@ -698,6 +706,7 @@ private:
|
|||||||
PDFFunctionPtr m_tintTransform;
|
PDFFunctionPtr m_tintTransform;
|
||||||
std::vector<QByteArray> m_colorantsPrintingOrder;
|
std::vector<QByteArray> m_colorantsPrintingOrder;
|
||||||
std::vector<QByteArray> m_processColorSpaceComponents;
|
std::vector<QByteArray> m_processColorSpaceComponents;
|
||||||
|
bool m_isNone;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PDFPatternColorSpace : public PDFAbstractColorSpace
|
class PDFPatternColorSpace : public PDFAbstractColorSpace
|
||||||
|
@ -73,6 +73,17 @@ PDFImage PDFImage::createImage(const PDFDocument* document,
|
|||||||
bool imageMask = loader.readBooleanFromDictionary(dictionary, "ImageMask", false);
|
bool imageMask = loader.readBooleanFromDictionary(dictionary, "ImageMask", false);
|
||||||
std::vector<PDFReal> matte = loader.readNumberArrayFromDictionary(dictionary, "Matte");
|
std::vector<PDFReal> matte = loader.readNumberArrayFromDictionary(dictionary, "Matte");
|
||||||
PDFInteger sMaskInData = loader.readIntegerFromDictionary(dictionary, "SMaskInData", 0);
|
PDFInteger sMaskInData = loader.readIntegerFromDictionary(dictionary, "SMaskInData", 0);
|
||||||
|
image.m_interpolate = loader.readBooleanFromDictionary(dictionary, "Interpolate", false);
|
||||||
|
image.m_alternates = loader.readObjectList<PDFAlternateImage>(dictionary->get("Alternates"));
|
||||||
|
image.m_name = loader.readNameFromDictionary(dictionary, "Name");
|
||||||
|
image.m_structuralParent = loader.readIntegerFromDictionary(dictionary, "StructParent", 0);
|
||||||
|
image.m_webCaptureContentSetId = loader.readStringFromDictionary(dictionary, "ID");
|
||||||
|
image.m_OPI = dictionary->get("OPI");
|
||||||
|
image.m_OC = dictionary->get("OC");
|
||||||
|
image.m_metadata = dictionary->get("Metadata");
|
||||||
|
image.m_associatedFiles = dictionary->get("AF");
|
||||||
|
image.m_measure = dictionary->get("Measure");
|
||||||
|
image.m_pointData = dictionary->get("PtData");
|
||||||
|
|
||||||
if (isSoftMask && (imageMask || dictionary->hasKey("Mask") || dictionary->hasKey("SMask")))
|
if (isSoftMask && (imageMask || dictionary->hasKey("Mask") || dictionary->hasKey("SMask")))
|
||||||
{
|
{
|
||||||
@ -706,9 +717,9 @@ PDFImage PDFImage::createImage(const PDFDocument* document,
|
|||||||
}
|
}
|
||||||
else if (imageMask)
|
else if (imageMask)
|
||||||
{
|
{
|
||||||
// We intentionally have 8 bits in the following code, because if ImageMask is set to true, then "BitsPerComponent"
|
// If ImageMask is set to true, then "BitsPerComponent" should have always value of 1.
|
||||||
// should have always value of 1.
|
// If this entry is not specified, then the value should be implicitly 1.
|
||||||
const unsigned int bitsPerComponent = static_cast<unsigned int>(loader.readIntegerFromDictionary(dictionary, "BitsPerComponent", 8));
|
const unsigned int bitsPerComponent = static_cast<unsigned int>(loader.readIntegerFromDictionary(dictionary, "BitsPerComponent", 1));
|
||||||
|
|
||||||
if (bitsPerComponent != 1)
|
if (bitsPerComponent != 1)
|
||||||
{
|
{
|
||||||
@ -840,6 +851,19 @@ OPJ_OFF_T PDFJPEG2000ImageData::skip(OPJ_OFF_T p_nb_bytes, void* p_user_data)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement image rendering intent
|
PDFAlternateImage PDFAlternateImage::parse(const PDFObjectStorage* storage, PDFObject object)
|
||||||
|
{
|
||||||
|
PDFAlternateImage result;
|
||||||
|
|
||||||
|
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||||
|
{
|
||||||
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
|
result.m_image = loader.readReferenceFromDictionary(dictionary, "Image");
|
||||||
|
result.m_oc = loader.readReferenceFromDictionary(dictionary, "OC");
|
||||||
|
result.m_defaultForPrinting = loader.readBooleanFromDictionary(dictionary, "DefaultForPrinting", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#ifndef PDFIMAGE_H
|
#ifndef PDFIMAGE_H
|
||||||
#define PDFIMAGE_H
|
#define PDFIMAGE_H
|
||||||
|
|
||||||
|
#include "pdfobject.h"
|
||||||
#include "pdfcolorspaces.h"
|
#include "pdfcolorspaces.h"
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
@ -28,8 +29,31 @@ namespace pdf
|
|||||||
{
|
{
|
||||||
class PDFStream;
|
class PDFStream;
|
||||||
class PDFDocument;
|
class PDFDocument;
|
||||||
|
class PDFObjectStorage;
|
||||||
class PDFRenderErrorReporter;
|
class PDFRenderErrorReporter;
|
||||||
|
|
||||||
|
/// Alternate image object. Defines alternate image, which
|
||||||
|
/// can be shown in some circumstances instead of main image.
|
||||||
|
class PDFAlternateImage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit inline PDFAlternateImage() = default;
|
||||||
|
|
||||||
|
/// Parses alternate image dictionary object.
|
||||||
|
/// \param storage Object storage
|
||||||
|
/// \param object Alternate image object
|
||||||
|
static PDFAlternateImage parse(const PDFObjectStorage* storage, PDFObject object);
|
||||||
|
|
||||||
|
PDFObjectReference getImage() const { return m_image; }
|
||||||
|
PDFObjectReference getOc() const { return m_oc; }
|
||||||
|
bool isDefaultForPrinting() const { return m_defaultForPrinting; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
PDFObjectReference m_image;
|
||||||
|
PDFObjectReference m_oc;
|
||||||
|
bool m_defaultForPrinting = false;
|
||||||
|
};
|
||||||
|
|
||||||
class PDFImage
|
class PDFImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -54,6 +78,33 @@ public:
|
|||||||
/// Returns rendering intent of the image
|
/// Returns rendering intent of the image
|
||||||
RenderingIntent getRenderingIntent() const { return m_renderingIntent; }
|
RenderingIntent getRenderingIntent() const { return m_renderingIntent; }
|
||||||
|
|
||||||
|
/// Color space of image samples
|
||||||
|
const PDFColorSpacePointer& getColorSpace() const { return m_colorSpace; }
|
||||||
|
|
||||||
|
/// Should PDF processor perform interpolation on this image?
|
||||||
|
bool isInterpolated() const { return m_interpolate; }
|
||||||
|
|
||||||
|
/// Array of alternate images
|
||||||
|
const std::vector<PDFAlternateImage>& getAlternates() const { return m_alternates; }
|
||||||
|
|
||||||
|
/// Returns name of image, under which is referenced in resources dictionary.
|
||||||
|
/// It was mandatory in PDF 1.0, otherwise it is optional and now it is deprecated
|
||||||
|
/// in PDF 2.0 specification.
|
||||||
|
const QByteArray& getName() const { return m_name; }
|
||||||
|
|
||||||
|
/// Returns idenfitier to structural parent in structure tree
|
||||||
|
PDFInteger getStructuralParent() const { return m_structuralParent; }
|
||||||
|
|
||||||
|
/// Web capture content set identifier
|
||||||
|
const QByteArray& getWebCaptureContentSetID() const { return m_webCaptureContentSetId; }
|
||||||
|
|
||||||
|
const PDFObject& getOPI() const { return m_OPI; }
|
||||||
|
const PDFObject& getOC() const { return m_OC; }
|
||||||
|
const PDFObject& getMetadata() const { return m_metadata; }
|
||||||
|
const PDFObject& getAssociatedFiles() const { return m_associatedFiles; }
|
||||||
|
const PDFObject& getMeasure() const { return m_measure; }
|
||||||
|
const PDFObject& getPointData() const { return m_pointData; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PDFImage() = default;
|
PDFImage() = default;
|
||||||
|
|
||||||
@ -61,6 +112,17 @@ private:
|
|||||||
PDFImageData m_softMask;
|
PDFImageData m_softMask;
|
||||||
PDFColorSpacePointer m_colorSpace;
|
PDFColorSpacePointer m_colorSpace;
|
||||||
RenderingIntent m_renderingIntent = RenderingIntent::Perceptual;
|
RenderingIntent m_renderingIntent = RenderingIntent::Perceptual;
|
||||||
|
bool m_interpolate = false;
|
||||||
|
std::vector<PDFAlternateImage> m_alternates;
|
||||||
|
QByteArray m_name;
|
||||||
|
QByteArray m_webCaptureContentSetId;
|
||||||
|
PDFInteger m_structuralParent = 0;
|
||||||
|
PDFObject m_OPI;
|
||||||
|
PDFObject m_OC;
|
||||||
|
PDFObject m_metadata;
|
||||||
|
PDFObject m_associatedFiles;
|
||||||
|
PDFObject m_measure;
|
||||||
|
PDFObject m_pointData;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -500,7 +500,11 @@ void PDFPageContentProcessor::processContent(const QByteArray& content)
|
|||||||
{ "H", "Height" },
|
{ "H", "Height" },
|
||||||
{ "IM", "ImageMask" },
|
{ "IM", "ImageMask" },
|
||||||
{ "I", "Interpolate" },
|
{ "I", "Interpolate" },
|
||||||
{ "W", "Width" }
|
{ "W", "Width" },
|
||||||
|
{ "L", "Length" },
|
||||||
|
{ "G", "DeviceGray" },
|
||||||
|
{ "RGB", "DeviceRGB" },
|
||||||
|
{ "CMYK", "DeviceCMYK" }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<PDFDictionary> dictionarySharedPointer = std::make_shared<PDFDictionary>();
|
std::shared_ptr<PDFDictionary> dictionarySharedPointer = std::make_shared<PDFDictionary>();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user