diff --git a/PdfForQtLib/sources/pdfcolorspaces.cpp b/PdfForQtLib/sources/pdfcolorspaces.cpp index 222e964..680999b 100644 --- a/PdfForQtLib/sources/pdfcolorspaces.cpp +++ b/PdfForQtLib/sources/pdfcolorspaces.cpp @@ -726,7 +726,7 @@ PDFColorSpacePointer PDFAbstractColorSpace::createDeviceColorSpaceByNameImpl(con return PDFColorSpacePointer(new PDFDeviceRGBColorSpace()); } } - else if (name == COLOR_SPACE_NAME_DEVICE_CMYK || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_CMYK) + else if (name == COLOR_SPACE_NAME_DEVICE_CMYK || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_CMYK || name == COLOR_SPACE_NAME_ABBREVIATION_CAL_CMYK) { if (colorSpaceDictionary && colorSpaceDictionary->hasKey(COLOR_SPACE_NAME_DEFAULT_CMYK) && !isNameAlreadyProcessed) { @@ -1053,10 +1053,11 @@ PDFColorSpacePointer PDFLabColorSpace::createLabColorSpace(const PDFDocument* do return PDFColorSpacePointer(new PDFLabColorSpace(whitePoint, blackPoint, minMax[0], minMax[1], minMax[2], minMax[3])); } -PDFICCBasedColorSpace::PDFICCBasedColorSpace(PDFColorSpacePointer alternateColorSpace, Ranges range, QByteArray iccProfileData) : +PDFICCBasedColorSpace::PDFICCBasedColorSpace(PDFColorSpacePointer alternateColorSpace, Ranges range, QByteArray iccProfileData, PDFObjectReference metadata) : m_alternateColorSpace(qMove(alternateColorSpace)), m_range(range), - m_iccProfileData(qMove(iccProfileData)) + m_iccProfileData(qMove(iccProfileData)), + m_metadata(metadata) { // Compute checksum m_iccProfileDataChecksum = QCryptographicHash::hash(m_iccProfileData, QCryptographicHash::Md5); @@ -1190,7 +1191,7 @@ PDFColorSpacePointer PDFICCBasedColorSpace::createICCBasedColorSpace(const PDFDi auto itEnd = std::next(itStart, rangeSize); loader.readNumberArrayFromDictionary(dictionary, ICCBASED_RANGE, itStart, itEnd); - return PDFColorSpacePointer(new PDFICCBasedColorSpace(qMove(alternateColorSpace), ranges, qMove(iccProfileData))); + return PDFColorSpacePointer(new PDFICCBasedColorSpace(qMove(alternateColorSpace), ranges, qMove(iccProfileData), loader.readReferenceFromDictionary(dictionary, "Metadata"))); } PDFIndexedColorSpace::PDFIndexedColorSpace(PDFColorSpacePointer baseColorSpace, QByteArray&& colors, int maxValue) : @@ -1391,7 +1392,9 @@ PDFColorSpacePointer PDFIndexedColorSpace::createIndexedColorSpace(const PDFDict PDFSeparationColorSpace::PDFSeparationColorSpace(QByteArray&& colorName, PDFColorSpacePointer alternateColorSpace, PDFFunctionPtr tintTransform) : m_colorName(qMove(colorName)), m_alternateColorSpace(qMove(alternateColorSpace)), - m_tintTransform(qMove(tintTransform)) + m_tintTransform(qMove(tintTransform)), + m_isNone(m_colorName == "None"), + m_isAll(m_colorName == "All") { } @@ -1406,9 +1409,25 @@ QColor PDFSeparationColorSpace::getColor(const PDFColor& color, const PDFCMS* cm // Separation color space value must have exactly one component! Q_ASSERT(color.size() == 1); + // According to the PDF 2.0 specification, separation color space, with colorant name "None" + // should not produce any visible output. + if (m_isNone) + { + return Qt::transparent; + } + // Input value double tint = color.back(); + // Jakub Melka: According to the PDF 2.0 specification, separation color space, with colorant name "All" + // should apply tint value to all output colorants, alternate color space and tint function should + // be ignored, and because QColor is aditive, we must invert the tint value. + if (m_isAll) + { + const double inversedTint = qBound(0.0, 1.0 - tint, 1.0); + return QColor::fromRgbF(inversedTint, inversedTint, inversedTint); + } + // Output values std::vector outputColor; outputColor.resize(m_alternateColorSpace->getColorComponentCount(), 0.0); @@ -1518,6 +1537,14 @@ QColor PDFDeviceNColorSpace::getDefaultColor(const PDFCMS* cms, RenderingIntent { PDFColor color; color.resize(getColorComponentCount()); + + // Jakub Melka: According to the PDF 2.0 specification, each channel should + // be initially set to 1.0. + for (size_t i = 0, colorComponentCount = color.size(); i < colorComponentCount; ++i) + { + color[i] = 1.0; + } + return getColor(color, cms, intent, reporter); } diff --git a/PdfForQtLib/sources/pdfcolorspaces.h b/PdfForQtLib/sources/pdfcolorspaces.h index c38e1f5..1e71345 100644 --- a/PdfForQtLib/sources/pdfcolorspaces.h +++ b/PdfForQtLib/sources/pdfcolorspaces.h @@ -55,6 +55,7 @@ static constexpr const char* COLOR_SPACE_NAME_DEVICE_CMYK = "DeviceCMYK"; static constexpr const char* COLOR_SPACE_NAME_ABBREVIATION_DEVICE_GRAY = "G"; static constexpr const char* COLOR_SPACE_NAME_ABBREVIATION_DEVICE_RGB = "RGB"; static constexpr const char* COLOR_SPACE_NAME_ABBREVIATION_DEVICE_CMYK = "CMYK"; +static constexpr const char* COLOR_SPACE_NAME_ABBREVIATION_CAL_CMYK = "CalCMYK"; static constexpr const char* COLOR_SPACE_NAME_DEFAULT_GRAY = "DefaultGray"; static constexpr const char* COLOR_SPACE_NAME_DEFAULT_RGB = "DefaultRGB"; @@ -542,7 +543,7 @@ public: static constexpr const size_t MAX_COLOR_COMPONENTS = 4; using Ranges = std::array; - explicit PDFICCBasedColorSpace(PDFColorSpacePointer alternateColorSpace, Ranges range, QByteArray iccProfileData); + explicit PDFICCBasedColorSpace(PDFColorSpacePointer alternateColorSpace, Ranges range, QByteArray iccProfileData, PDFObjectReference metadata); virtual ~PDFICCBasedColorSpace() = default; virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override; @@ -550,6 +551,8 @@ public: virtual size_t getColorComponentCount() const override; virtual void fillRGBBuffer(const std::vector& colors, unsigned char* outputBuffer, RenderingIntent intent, const PDFCMS* cms, PDFRenderErrorReporter* reporter) const override; + PDFObjectReference getMetadata() const { return m_metadata; } + /// Creates ICC based color space from provided values. /// \param colorSpaceDictionary Color space dictionary /// \param document Document @@ -567,6 +570,7 @@ private: Ranges m_range; QByteArray m_iccProfileData; QByteArray m_iccProfileDataChecksum; + PDFObjectReference m_metadata; }; class PDFIndexedColorSpace : public PDFAbstractColorSpace @@ -615,6 +619,9 @@ public: virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override; virtual size_t getColorComponentCount() const override; + bool isNone() const { return m_isNone; } + bool isAll() const { return m_isAll; } + /// Creates separation color space from provided values. /// \param colorSpaceDictionary Color space dictionary /// \param document Document @@ -631,6 +638,8 @@ private: QByteArray m_colorName; PDFColorSpacePointer m_alternateColorSpace; PDFFunctionPtr m_tintTransform; + bool m_isNone; + bool m_isAll; }; class PDFDeviceNColorSpace : public PDFAbstractColorSpace diff --git a/PdfForQtLib/sources/pdfimage.cpp b/PdfForQtLib/sources/pdfimage.cpp index 2e7a600..5f68a33 100644 --- a/PdfForQtLib/sources/pdfimage.cpp +++ b/PdfForQtLib/sources/pdfimage.cpp @@ -467,7 +467,7 @@ PDFImage PDFImage::createImage(const PDFDocument* document, { QByteArray iccProfileData(reinterpret_cast(jpegImage->icc_profile_buf), jpegImage->icc_profile_len); PDFICCBasedColorSpace::Ranges ranges = { 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0 }; - image.m_colorSpace.reset(new PDFICCBasedColorSpace(image.m_colorSpace, ranges, qMove(iccProfileData))); + image.m_colorSpace.reset(new PDFICCBasedColorSpace(image.m_colorSpace, ranges, qMove(iccProfileData), PDFObjectReference())); } }