mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Color spaces - update according to the PDF 2.0 specification
This commit is contained in:
@ -726,7 +726,7 @@ PDFColorSpacePointer PDFAbstractColorSpace::createDeviceColorSpaceByNameImpl(con
|
|||||||
return PDFColorSpacePointer(new PDFDeviceRGBColorSpace());
|
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)
|
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]));
|
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_alternateColorSpace(qMove(alternateColorSpace)),
|
||||||
m_range(range),
|
m_range(range),
|
||||||
m_iccProfileData(qMove(iccProfileData))
|
m_iccProfileData(qMove(iccProfileData)),
|
||||||
|
m_metadata(metadata)
|
||||||
{
|
{
|
||||||
// Compute checksum
|
// Compute checksum
|
||||||
m_iccProfileDataChecksum = QCryptographicHash::hash(m_iccProfileData, QCryptographicHash::Md5);
|
m_iccProfileDataChecksum = QCryptographicHash::hash(m_iccProfileData, QCryptographicHash::Md5);
|
||||||
@ -1190,7 +1191,7 @@ PDFColorSpacePointer PDFICCBasedColorSpace::createICCBasedColorSpace(const PDFDi
|
|||||||
auto itEnd = std::next(itStart, rangeSize);
|
auto itEnd = std::next(itStart, rangeSize);
|
||||||
loader.readNumberArrayFromDictionary(dictionary, ICCBASED_RANGE, itStart, itEnd);
|
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) :
|
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) :
|
PDFSeparationColorSpace::PDFSeparationColorSpace(QByteArray&& colorName, PDFColorSpacePointer alternateColorSpace, PDFFunctionPtr tintTransform) :
|
||||||
m_colorName(qMove(colorName)),
|
m_colorName(qMove(colorName)),
|
||||||
m_alternateColorSpace(qMove(alternateColorSpace)),
|
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!
|
// Separation color space value must have exactly one component!
|
||||||
Q_ASSERT(color.size() == 1);
|
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
|
// Input value
|
||||||
double tint = color.back();
|
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
|
// Output values
|
||||||
std::vector<double> outputColor;
|
std::vector<double> outputColor;
|
||||||
outputColor.resize(m_alternateColorSpace->getColorComponentCount(), 0.0);
|
outputColor.resize(m_alternateColorSpace->getColorComponentCount(), 0.0);
|
||||||
@ -1518,6 +1537,14 @@ QColor PDFDeviceNColorSpace::getDefaultColor(const PDFCMS* cms, RenderingIntent
|
|||||||
{
|
{
|
||||||
PDFColor color;
|
PDFColor color;
|
||||||
color.resize(getColorComponentCount());
|
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);
|
return getColor(color, cms, intent, reporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_GRAY = "G";
|
||||||
static constexpr const char* COLOR_SPACE_NAME_ABBREVIATION_DEVICE_RGB = "RGB";
|
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_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_GRAY = "DefaultGray";
|
||||||
static constexpr const char* COLOR_SPACE_NAME_DEFAULT_RGB = "DefaultRGB";
|
static constexpr const char* COLOR_SPACE_NAME_DEFAULT_RGB = "DefaultRGB";
|
||||||
@ -542,7 +543,7 @@ public:
|
|||||||
static constexpr const size_t MAX_COLOR_COMPONENTS = 4;
|
static constexpr const size_t MAX_COLOR_COMPONENTS = 4;
|
||||||
using Ranges = std::array<PDFColorComponent, MAX_COLOR_COMPONENTS * 2>;
|
using Ranges = std::array<PDFColorComponent, MAX_COLOR_COMPONENTS * 2>;
|
||||||
|
|
||||||
explicit PDFICCBasedColorSpace(PDFColorSpacePointer alternateColorSpace, Ranges range, QByteArray iccProfileData);
|
explicit PDFICCBasedColorSpace(PDFColorSpacePointer alternateColorSpace, Ranges range, QByteArray iccProfileData, PDFObjectReference metadata);
|
||||||
virtual ~PDFICCBasedColorSpace() = default;
|
virtual ~PDFICCBasedColorSpace() = default;
|
||||||
|
|
||||||
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
|
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
|
||||||
@ -550,6 +551,8 @@ public:
|
|||||||
virtual size_t getColorComponentCount() const override;
|
virtual size_t getColorComponentCount() const override;
|
||||||
virtual void fillRGBBuffer(const std::vector<float>& colors, unsigned char* outputBuffer, RenderingIntent intent, const PDFCMS* cms, PDFRenderErrorReporter* reporter) const override;
|
virtual void fillRGBBuffer(const std::vector<float>& 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.
|
/// Creates ICC based color space from provided values.
|
||||||
/// \param colorSpaceDictionary Color space dictionary
|
/// \param colorSpaceDictionary Color space dictionary
|
||||||
/// \param document Document
|
/// \param document Document
|
||||||
@ -567,6 +570,7 @@ private:
|
|||||||
Ranges m_range;
|
Ranges m_range;
|
||||||
QByteArray m_iccProfileData;
|
QByteArray m_iccProfileData;
|
||||||
QByteArray m_iccProfileDataChecksum;
|
QByteArray m_iccProfileDataChecksum;
|
||||||
|
PDFObjectReference m_metadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PDFIndexedColorSpace : public PDFAbstractColorSpace
|
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 QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
|
||||||
virtual size_t getColorComponentCount() 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.
|
/// Creates separation color space from provided values.
|
||||||
/// \param colorSpaceDictionary Color space dictionary
|
/// \param colorSpaceDictionary Color space dictionary
|
||||||
/// \param document Document
|
/// \param document Document
|
||||||
@ -631,6 +638,8 @@ private:
|
|||||||
QByteArray m_colorName;
|
QByteArray m_colorName;
|
||||||
PDFColorSpacePointer m_alternateColorSpace;
|
PDFColorSpacePointer m_alternateColorSpace;
|
||||||
PDFFunctionPtr m_tintTransform;
|
PDFFunctionPtr m_tintTransform;
|
||||||
|
bool m_isNone;
|
||||||
|
bool m_isAll;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PDFDeviceNColorSpace : public PDFAbstractColorSpace
|
class PDFDeviceNColorSpace : public PDFAbstractColorSpace
|
||||||
|
@ -467,7 +467,7 @@ PDFImage PDFImage::createImage(const PDFDocument* document,
|
|||||||
{
|
{
|
||||||
QByteArray iccProfileData(reinterpret_cast<const char*>(jpegImage->icc_profile_buf), jpegImage->icc_profile_len);
|
QByteArray iccProfileData(reinterpret_cast<const char*>(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 };
|
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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user