Rework of color spaces, some bugfixing of color spaces

This commit is contained in:
Jakub Melka
2021-01-02 18:27:22 +01:00
parent b29791b890
commit a2dc4e16a8
8 changed files with 729 additions and 9 deletions

View File

@ -20,6 +20,7 @@
#include "pdfflatarray.h"
#include "pdffunction.h"
#include "pdfutils.h"
#include <QColor>
#include <QImage>
@ -43,6 +44,7 @@ class PDFRenderErrorReporter;
using PDFColorComponent = float;
using PDFColor = PDFFlatArray<PDFColorComponent, 4>;
using PDFColorSpacePointer = QSharedPointer<PDFAbstractColorSpace>;
using PDFColorBuffer = PDFBuffer<PDFColorComponent>;
static constexpr const int COLOR_SPACE_MAX_LEVEL_OF_RECURSION = 12;
@ -209,6 +211,34 @@ public:
return result;
}
inline PDFColorComponent getValue(size_t row, size_t column) const
{
return m_values[row * Cols + column];
}
void transpose()
{
Q_ASSERT(Rows == Cols);
for (size_t row = 0; row < Rows; ++row)
{
for (size_t column = row; column < Cols; ++column)
{
const size_t index1 = row * Cols + column;
const size_t index2 = column * Cols + row;
std::swap(m_values[index1], m_values[index2]);
}
}
}
void multiplyByFactor(PDFColorComponent factor)
{
for (auto it = begin(); it != end(); ++it)
{
*it *= factor;
}
}
inline typename std::array<PDFColorComponent, Rows * Cols>::iterator begin() { return m_values.begin(); }
inline typename std::array<PDFColorComponent, Rows * Cols>::iterator end() { return m_values.end(); }
@ -226,6 +256,27 @@ public:
explicit PDFAbstractColorSpace() = default;
virtual ~PDFAbstractColorSpace() = default;
enum class ColorSpace
{
DeviceGray,
DeviceRGB,
DeviceCMYK,
CalGray,
CalRGB,
Lab,
ICCBased,
Indexed,
Separation,
DeviceN,
Pattern
};
/// Returns color space identification
virtual ColorSpace getColorSpace() const = 0;
/// Returns true, if this color space can be used for blending
bool isBlendColorSpace() const;
/// Returns default color for the color space
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const = 0;
@ -320,6 +371,23 @@ public:
/// \param ratio Mixing ratio
static PDFColor mixColors(const PDFColor& color1, const PDFColor& color2, PDFReal ratio);
/// Transforms color from source color space to target color space. Target color space
/// must be blend color space.
/// \param source Source color space
/// \param target Target color space (must be blend color space)
/// \param cms Color management system
/// \param intent Rendering intent
/// \param input Input color buffer
/// \param output Output color buffer, must match size of input color buffer
/// \param reporter Error reporter
static bool transform(const PDFAbstractColorSpace* source,
const PDFAbstractColorSpace* target,
const PDFCMS* cms,
RenderingIntent intent,
const PDFColorBuffer input,
PDFColorBuffer output,
PDFRenderErrorReporter* reporter);
protected:
/// Clips the color component to range [0, 1]
static constexpr PDFColorComponent clip01(PDFColorComponent component) { return qBound<PDFColorComponent>(0.0, component, 1.0); }
@ -426,6 +494,7 @@ public:
explicit PDFDeviceGrayColorSpace() = default;
virtual ~PDFDeviceGrayColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::DeviceGray; }
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) const override;
virtual size_t getColorComponentCount() const override;
@ -438,6 +507,7 @@ public:
explicit PDFDeviceRGBColorSpace() = default;
virtual ~PDFDeviceRGBColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::DeviceRGB; }
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) const override;
virtual size_t getColorComponentCount() const override;
@ -450,6 +520,7 @@ public:
explicit PDFDeviceCMYKColorSpace() = default;
virtual ~PDFDeviceCMYKColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::DeviceCMYK; }
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) const override;
virtual size_t getColorComponentCount() const override;
@ -461,6 +532,8 @@ class PDFXYZColorSpace : public PDFAbstractColorSpace
public:
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
const PDFColor3& getWhitePoint() const { return m_whitePoint; }
protected:
explicit PDFXYZColorSpace(PDFColor3 whitePoint);
virtual ~PDFXYZColorSpace() = default;
@ -480,10 +553,14 @@ public:
explicit PDFCalGrayColorSpace(PDFColor3 whitePoint, PDFColor3 blackPoint, PDFColorComponent gamma);
virtual ~PDFCalGrayColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::CalGray; }
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) 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;
PDFColorComponent getGamma() const { return m_gamma; }
PDFColor3 getBlackPoint() const { m_blackPoint; }
/// Creates CalGray color space from provided values.
/// \param document Document
/// \param dictionary Dictionary
@ -500,6 +577,7 @@ public:
explicit PDFCalRGBColorSpace(PDFColor3 whitePoint, PDFColor3 blackPoint, PDFColor3 gamma, PDFColorComponentMatrix_3x3 matrix);
virtual ~PDFCalRGBColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::CalRGB; }
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) 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;
@ -509,6 +587,10 @@ public:
/// \param dictionary Dictionary
static PDFColorSpacePointer createCalRGBColorSpace(const PDFDocument* document, const PDFDictionary* dictionary);
PDFColor3 getBlackPoint() const;
PDFColor3 getGamma() const;
const PDFColorComponentMatrix_3x3& getMatrix() const;
private:
PDFColor3 m_blackPoint;
PDFColor3 m_gamma;
@ -521,6 +603,7 @@ public:
explicit PDFLabColorSpace(PDFColor3 whitePoint, PDFColor3 blackPoint, PDFColorComponent aMin, PDFColorComponent aMax, PDFColorComponent bMin, PDFColorComponent bMax);
virtual ~PDFLabColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::Lab; }
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) 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;
@ -530,6 +613,13 @@ public:
/// \param dictionary Dictionary
static PDFColorSpacePointer createLabColorSpace(const PDFDocument* document, const PDFDictionary* dictionary);
PDFColorComponent getAMin() const;
PDFColorComponent getAMax() const;
PDFColorComponent getBMin() const;
PDFColorComponent getBMax() const;
PDFColor3 getBlackPoint() const;
private:
PDFColor3 m_blackPoint;
PDFColorComponent m_aMin;
@ -547,6 +637,7 @@ public:
explicit PDFICCBasedColorSpace(PDFColorSpacePointer alternateColorSpace, Ranges range, QByteArray iccProfileData, PDFObjectReference metadata);
virtual ~PDFICCBasedColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::ICCBased; }
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) const override;
virtual size_t getColorComponentCount() const override;
@ -566,6 +657,10 @@ public:
int recursion,
std::set<QByteArray>& usedNames);
const Ranges& getRange() const;
const QByteArray& getIccProfileData() const;
const QByteArray& getIccProfileDataChecksum() const;
private:
PDFColorSpacePointer m_alternateColorSpace;
Ranges m_range;
@ -580,6 +675,7 @@ public:
explicit PDFIndexedColorSpace(PDFColorSpacePointer baseColorSpace, QByteArray&& colors, int maxValue);
virtual ~PDFIndexedColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::Indexed; }
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) const override;
virtual size_t getColorComponentCount() const override;
@ -601,6 +697,9 @@ public:
int recursion,
std::set<QByteArray>& usedNames);
PDFColorSpacePointer getBaseColorSpace() const;
std::vector<PDFColorComponent> transformColorsToBaseColorSpace(const PDFColorBuffer buffer) const;
private:
static constexpr const int MIN_VALUE = 0;
static constexpr const int MAX_VALUE = 255;
@ -616,6 +715,7 @@ public:
explicit PDFSeparationColorSpace(QByteArray&& colorName, PDFColorSpacePointer alternateColorSpace, PDFFunctionPtr tintTransform);
virtual ~PDFSeparationColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::Separation; }
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) const override;
virtual size_t getColorComponentCount() const override;
@ -623,6 +723,8 @@ public:
bool isNone() const { return m_isNone; }
bool isAll() const { return m_isAll; }
std::vector<PDFColorComponent> transformColorsToBaseColorSpace(const PDFColorBuffer buffer) const;
/// Creates separation color space from provided values.
/// \param colorSpaceDictionary Color space dictionary
/// \param document Document
@ -635,6 +737,9 @@ public:
int recursion,
std::set<QByteArray>& usedNames);
PDFColorSpacePointer getAlternateColorSpace() const;
const QByteArray& getColorName() const;
private:
QByteArray m_colorName;
PDFColorSpacePointer m_alternateColorSpace;
@ -672,6 +777,7 @@ public:
std::vector<QByteArray> processColorSpaceComponents);
virtual ~PDFDeviceNColorSpace() = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::DeviceN; }
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) const override;
virtual size_t getColorComponentCount() const override;
@ -687,6 +793,8 @@ public:
const std::vector<QByteArray>& getProcessColorSpaceComponents() const { return m_processColorSpaceComponents; }
bool isNone() const { return m_isNone; }
std::vector<PDFColorComponent> transformColorsToBaseColorSpace(const PDFColorBuffer buffer) const;
/// Creates DeviceN color space from provided values.
/// \param colorSpaceDictionary Color space dictionary
/// \param document Document
@ -723,6 +831,7 @@ public:
virtual ~PDFPatternColorSpace() override = default;
virtual ColorSpace getColorSpace() const override { return ColorSpace::Pattern; }
virtual QColor getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool isRange01) const override;
virtual size_t getColorComponentCount() const override;