mirror of https://github.com/JakubMelka/PDF4QT.git
Performance boost for images
This commit is contained in:
parent
afbf37d068
commit
c803317b6b
|
@ -43,6 +43,11 @@ public:
|
|||
virtual QColor getColorFromDeviceCMYK(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual QColor getColorFromXYZ(const PDFColor3& whitePoint, const PDFColor3& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual QColor getColorFromICC(const PDFColor& color, RenderingIntent renderingIntent, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromDeviceGray(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromDeviceRGB(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromDeviceCMYK(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromXYZ(const PDFColor3& whitePoint, const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromICC(const std::vector<float>& colors, RenderingIntent renderingIntent, unsigned char* outputBuffer, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
@ -66,7 +71,15 @@ private:
|
|||
/// Gets transform from cache. If transform doesn't exist, then it is created.
|
||||
/// \param profile Color profile
|
||||
/// \param intent Rendering intent
|
||||
cmsHTRANSFORM getTransform(Profile profile, RenderingIntent intent) const;
|
||||
/// \param isRGB888Buffer If true, 8-bit RGB output buffer is used, otherwise FLOAT RGB output buffer is used
|
||||
cmsHTRANSFORM getTransform(Profile profile, RenderingIntent intent, bool isRGB888Buffer) const;
|
||||
|
||||
/// Gets transform for ICC profile from cache. If transform doesn't exist, then it is created.
|
||||
/// \param iccData Data of icc profile
|
||||
/// \param iccID Icc profile id
|
||||
/// \param renderingIntent Rendering intent
|
||||
/// \param isRGB888Buffer If true, 8-bit RGB output buffer is used, otherwise FLOAT RGB output buffer is used
|
||||
cmsHTRANSFORM getTransformFromICCProfile(const QByteArray& iccData, const QByteArray& iccID, RenderingIntent renderingIntent, bool isRGB888Buffer) const;
|
||||
|
||||
/// Returns transformation flags accordint to the current settings
|
||||
cmsUInt32Number getTransformationFlags() const;
|
||||
|
@ -78,7 +91,8 @@ private:
|
|||
/// Gets transform from cache key.
|
||||
/// \param profile Color profile
|
||||
/// \param intent Rendering intent
|
||||
static constexpr int getCacheKey(Profile profile, RenderingIntent intent) { return int(intent) * ProfileCount + profile; }
|
||||
/// \param isRGB888Buffer If true, 8-bit RGB output buffer is used, otherwise FLOAT RGB output buffer is used
|
||||
static constexpr int getCacheKey(Profile profile, RenderingIntent intent, bool isRGB888Buffer) { return ((int(intent) * ProfileCount + profile) << 1) + (isRGB888Buffer ? 1 : 0); }
|
||||
|
||||
/// Returns little CMS rendering intent
|
||||
/// \param intent Rendering intent
|
||||
|
@ -104,6 +118,163 @@ private:
|
|||
mutable std::map<std::pair<QByteArray, RenderingIntent>, cmsHTRANSFORM> m_customIccProfileCache;
|
||||
};
|
||||
|
||||
bool PDFLittleCMS::fillRGBBufferFromDeviceGray(const std::vector<float>& colors,
|
||||
RenderingIntent intent,
|
||||
unsigned char* outputBuffer,
|
||||
PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransform(Gray, getEffectiveRenderingIntent(intent), true);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from gray to output device using CMS failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cmsGetTransformInputFormat(transform) == TYPE_GRAY_FLT)
|
||||
{
|
||||
Q_ASSERT(cmsGetTransformOutputFormat(transform) == TYPE_RGB_8);
|
||||
cmsDoTransform(transform, colors.data(), outputBuffer, static_cast<cmsUInt32Number>(colors.size()));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from gray to output device using CMS failed - invalid data format."));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PDFLittleCMS::fillRGBBufferFromDeviceRGB(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransform(RGB, getEffectiveRenderingIntent(intent), true);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from RGB to output device using CMS failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
const cmsUInt32Number inputFormat = cmsGetTransformInputFormat(transform);
|
||||
if (inputFormat == TYPE_RGB_FLT && (colors.size()) % T_CHANNELS(inputFormat) == 0)
|
||||
{
|
||||
Q_ASSERT(cmsGetTransformOutputFormat(transform) == TYPE_RGB_8);
|
||||
cmsDoTransform(transform, colors.data(), outputBuffer, static_cast<cmsUInt32Number>(colors.size()) / T_CHANNELS(inputFormat));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from RGB to output device using CMS failed - invalid data format."));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PDFLittleCMS::fillRGBBufferFromDeviceCMYK(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransform(CMYK, getEffectiveRenderingIntent(intent), true);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from CMYK to output device using CMS failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
const cmsUInt32Number inputFormat = cmsGetTransformInputFormat(transform);
|
||||
if (inputFormat == TYPE_CMYK_FLT && (colors.size()) % T_CHANNELS(inputFormat) == 0)
|
||||
{
|
||||
Q_ASSERT(cmsGetTransformOutputFormat(transform) == TYPE_RGB_8);
|
||||
std::vector<float> fixedColors = colors;
|
||||
for (size_t i = 0, count = fixedColors.size(); i < count; ++i)
|
||||
{
|
||||
fixedColors[i] = fixedColors[i] * 100.0f;
|
||||
}
|
||||
cmsDoTransform(transform, fixedColors.data(), outputBuffer, static_cast<cmsUInt32Number>(colors.size()) / T_CHANNELS(inputFormat));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from CMYK to output device using CMS failed - invalid data format."));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PDFLittleCMS::fillRGBBufferFromXYZ(const PDFColor3& whitePoint, const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransform(XYZ, getEffectiveRenderingIntent(intent), true);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from XYZ to output device using CMS failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
const cmsUInt32Number inputFormat = cmsGetTransformInputFormat(transform);
|
||||
if (inputFormat == TYPE_XYZ_FLT && (colors.size()) % T_CHANNELS(inputFormat) == 0)
|
||||
{
|
||||
Q_ASSERT(cmsGetTransformOutputFormat(transform) == TYPE_RGB_8);
|
||||
|
||||
const cmsCIEXYZ* d50WhitePoint = cmsD50_XYZ();
|
||||
std::array<float, 3> correctionCoefficients = { float(d50WhitePoint->X) / whitePoint[0], float(d50WhitePoint->Y) / whitePoint[1], float(d50WhitePoint->Z) / whitePoint[2] };
|
||||
std::vector<float> fixedColors = colors;
|
||||
for (size_t i = 0, count = fixedColors.size(); i < count; ++i)
|
||||
{
|
||||
fixedColors[i] = fixedColors[i] * correctionCoefficients[i % correctionCoefficients.size()];
|
||||
}
|
||||
|
||||
cmsDoTransform(transform, fixedColors.data(), outputBuffer, static_cast<cmsUInt32Number>(colors.size()) / T_CHANNELS(inputFormat));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from XYZ to output device using CMS failed - invalid data format."));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PDFLittleCMS::fillRGBBufferFromICC(const std::vector<float>& colors, RenderingIntent renderingIntent, unsigned char* outputBuffer, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransformFromICCProfile(iccData, iccID, renderingIntent, true);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from icc profile space to output device using CMS failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
const cmsUInt32Number format = cmsGetTransformInputFormat(transform);
|
||||
const cmsUInt32Number channels = T_CHANNELS(format);
|
||||
const cmsUInt32Number colorSpace = T_COLORSPACE(format);
|
||||
const bool isCMYK = colorSpace == PT_CMYK;
|
||||
const float* inputColors = colors.data();
|
||||
std::vector<float> cmykColors;
|
||||
|
||||
if (isCMYK)
|
||||
{
|
||||
cmykColors = colors;
|
||||
for (size_t i = 0; i < cmykColors.size(); ++i)
|
||||
{
|
||||
cmykColors[i] = cmykColors[i] * 100.0;
|
||||
}
|
||||
inputColors = cmykColors.data();
|
||||
}
|
||||
|
||||
if ((colors.size()) % T_CHANNELS(format) == 0)
|
||||
{
|
||||
const cmsUInt32Number pixels = static_cast<cmsUInt32Number>(colors.size()) / channels;
|
||||
cmsDoTransform(transform, inputColors, outputBuffer, pixels);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter->reportRenderErrorOnce(RenderErrorType::Error, PDFTranslationContext::tr("Conversion from icc profile space to output device using CMS failed - invalid data format."));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PDFLittleCMS::PDFLittleCMS(const PDFCMSManager* manager, const PDFCMSSettings& settings) :
|
||||
m_manager(manager),
|
||||
m_settings(settings),
|
||||
|
@ -154,7 +325,7 @@ QColor PDFLittleCMS::getPaperColor() const
|
|||
|
||||
QColor PDFLittleCMS::getColorFromDeviceGray(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransform(Gray, getEffectiveRenderingIntent(intent));
|
||||
cmsHTRANSFORM transform = getTransform(Gray, getEffectiveRenderingIntent(intent), false);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
|
@ -181,7 +352,7 @@ QColor PDFLittleCMS::getColorFromDeviceGray(const PDFColor& color, RenderingInte
|
|||
|
||||
QColor PDFLittleCMS::getColorFromDeviceRGB(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransform(RGB, getEffectiveRenderingIntent(intent));
|
||||
cmsHTRANSFORM transform = getTransform(RGB, getEffectiveRenderingIntent(intent), false);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
|
@ -208,7 +379,7 @@ QColor PDFLittleCMS::getColorFromDeviceRGB(const PDFColor& color, RenderingInten
|
|||
|
||||
QColor PDFLittleCMS::getColorFromDeviceCMYK(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransform(CMYK, getEffectiveRenderingIntent(intent));
|
||||
cmsHTRANSFORM transform = getTransform(CMYK, getEffectiveRenderingIntent(intent), false);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
|
@ -235,7 +406,7 @@ QColor PDFLittleCMS::getColorFromDeviceCMYK(const PDFColor& color, RenderingInte
|
|||
|
||||
QColor PDFLittleCMS::getColorFromXYZ(const PDFColor3& whitePoint, const PDFColor3& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransform(XYZ, getEffectiveRenderingIntent(intent));
|
||||
cmsHTRANSFORM transform = getTransform(XYZ, getEffectiveRenderingIntent(intent), false);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
|
@ -261,46 +432,50 @@ QColor PDFLittleCMS::getColorFromXYZ(const PDFColor3& whitePoint, const PDFColor
|
|||
return QColor();
|
||||
}
|
||||
|
||||
QColor PDFLittleCMS::getColorFromICC(const PDFColor& color, RenderingIntent renderingIntent, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const
|
||||
cmsHTRANSFORM PDFLittleCMS::getTransformFromICCProfile(const QByteArray& iccData, const QByteArray& iccID, RenderingIntent renderingIntent, bool isRGB888Buffer) const
|
||||
{
|
||||
cmsHTRANSFORM transform = cmsHTRANSFORM();
|
||||
|
||||
RenderingIntent effectiveRenderingIntent = getEffectiveRenderingIntent(renderingIntent);
|
||||
const auto key = std::make_pair(iccID + (isRGB888Buffer ? "RGB_888" : "FLT"), effectiveRenderingIntent);
|
||||
QReadLocker lock(&m_customIccProfileCacheLock);
|
||||
auto it = m_customIccProfileCache.find(key);
|
||||
if (it == m_customIccProfileCache.cend())
|
||||
{
|
||||
RenderingIntent effectiveRenderingIntent = getEffectiveRenderingIntent(renderingIntent);
|
||||
const auto key = std::make_pair(iccID, effectiveRenderingIntent);
|
||||
QReadLocker lock(&m_customIccProfileCacheLock);
|
||||
auto it = m_customIccProfileCache.find(key);
|
||||
lock.unlock();
|
||||
QWriteLocker writeLock(&m_customIccProfileCacheLock);
|
||||
|
||||
// Now, we have locked cache for writing. We must find out,
|
||||
// if some other thread doesn't created the transformation already.
|
||||
it = m_customIccProfileCache.find(key);
|
||||
if (it == m_customIccProfileCache.cend())
|
||||
{
|
||||
lock.unlock();
|
||||
QWriteLocker writeLock(&m_customIccProfileCacheLock);
|
||||
|
||||
// Now, we have locked cache for writing. We must find out,
|
||||
// if some other thread doesn't created the transformation already.
|
||||
it = m_customIccProfileCache.find(key);
|
||||
if (it == m_customIccProfileCache.cend())
|
||||
cmsHTRANSFORM transform = cmsHTRANSFORM();
|
||||
cmsHPROFILE profile = cmsOpenProfileFromMem(iccData.data(), iccData.size());
|
||||
if (profile)
|
||||
{
|
||||
cmsHPROFILE profile = cmsOpenProfileFromMem(iccData.data(), iccData.size());
|
||||
if (profile)
|
||||
if (const cmsUInt32Number inputDataFormat = getProfileDataFormat(profile))
|
||||
{
|
||||
if (const cmsUInt32Number inputDataFormat = getProfileDataFormat(profile))
|
||||
{
|
||||
cmsUInt32Number lcmsIntent = getLittleCMSRenderingIntent(effectiveRenderingIntent);
|
||||
transform = cmsCreateTransform(profile, inputDataFormat, m_profiles[Output], TYPE_RGB_FLT, lcmsIntent, getTransformationFlags());
|
||||
}
|
||||
cmsCloseProfile(profile);
|
||||
cmsUInt32Number lcmsIntent = getLittleCMSRenderingIntent(effectiveRenderingIntent);
|
||||
transform = cmsCreateTransform(profile, inputDataFormat, m_profiles[Output], isRGB888Buffer ? TYPE_RGB_8 : TYPE_RGB_FLT, lcmsIntent, getTransformationFlags());
|
||||
}
|
||||
|
||||
it = m_customIccProfileCache.insert(std::make_pair(key, transform)).first;
|
||||
cmsCloseProfile(profile);
|
||||
}
|
||||
|
||||
transform = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform = it->second;
|
||||
it = m_customIccProfileCache.insert(std::make_pair(key, transform)).first;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return cmsHTRANSFORM();
|
||||
}
|
||||
|
||||
QColor PDFLittleCMS::getColorFromICC(const PDFColor& color, RenderingIntent renderingIntent, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
cmsHTRANSFORM transform = getTransformFromICCProfile(iccData, iccID, renderingIntent, false);
|
||||
|
||||
if (!transform)
|
||||
{
|
||||
|
@ -424,9 +599,9 @@ cmsHPROFILE PDFLittleCMS::createProfile(const QString& id, const PDFColorProfile
|
|||
return cmsHPROFILE();
|
||||
}
|
||||
|
||||
cmsHTRANSFORM PDFLittleCMS::getTransform(Profile profile, RenderingIntent intent) const
|
||||
cmsHTRANSFORM PDFLittleCMS::getTransform(Profile profile, RenderingIntent intent, bool isRGB888Buffer) const
|
||||
{
|
||||
const int key = getCacheKey(profile, intent);
|
||||
const int key = getCacheKey(profile, intent, isRGB888Buffer);
|
||||
|
||||
QReadLocker lock(&m_transformationCacheLock);
|
||||
auto it = m_transformationCache.find(key);
|
||||
|
@ -446,7 +621,7 @@ cmsHTRANSFORM PDFLittleCMS::getTransform(Profile profile, RenderingIntent intent
|
|||
|
||||
if (input && output)
|
||||
{
|
||||
transform = cmsCreateTransform(input, getProfileDataFormat(input), output, TYPE_RGB_FLT, getLittleCMSRenderingIntent(intent), getTransformationFlags());
|
||||
transform = cmsCreateTransform(input, getProfileDataFormat(input), output, isRGB888Buffer ? TYPE_RGB_8 : TYPE_RGB_FLT, getLittleCMSRenderingIntent(intent), getTransformationFlags());
|
||||
}
|
||||
|
||||
it = m_transformationCache.insert(std::make_pair(key, transform)).first;
|
||||
|
@ -652,6 +827,54 @@ QColor PDFCMSGeneric::getColorFromICC(const PDFColor& color,
|
|||
return QColor();
|
||||
}
|
||||
|
||||
bool PDFCMSGeneric::fillRGBBufferFromDeviceGray(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
Q_UNUSED(colors);
|
||||
Q_UNUSED(intent);
|
||||
Q_UNUSED(outputBuffer);
|
||||
Q_UNUSED(reporter);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PDFCMSGeneric::fillRGBBufferFromDeviceRGB(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
Q_UNUSED(colors);
|
||||
Q_UNUSED(intent);
|
||||
Q_UNUSED(outputBuffer);
|
||||
Q_UNUSED(reporter);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PDFCMSGeneric::fillRGBBufferFromDeviceCMYK(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
Q_UNUSED(colors);
|
||||
Q_UNUSED(intent);
|
||||
Q_UNUSED(outputBuffer);
|
||||
Q_UNUSED(reporter);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PDFCMSGeneric::fillRGBBufferFromXYZ(const PDFColor3& whitePoint, const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
Q_UNUSED(whitePoint);
|
||||
Q_UNUSED(colors);
|
||||
Q_UNUSED(intent);
|
||||
Q_UNUSED(outputBuffer);
|
||||
Q_UNUSED(reporter);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PDFCMSGeneric::fillRGBBufferFromICC(const std::vector<float>& colors, RenderingIntent renderingIntent, unsigned char* outputBuffer, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
Q_UNUSED(colors);
|
||||
Q_UNUSED(renderingIntent);
|
||||
Q_UNUSED(outputBuffer);
|
||||
Q_UNUSED(iccID);
|
||||
Q_UNUSED(iccData);
|
||||
Q_UNUSED(reporter);
|
||||
return false;
|
||||
}
|
||||
|
||||
PDFCMSManager::PDFCMSManager(QObject* parent) :
|
||||
BaseClass(parent),
|
||||
m_mutex(QMutex::Recursive)
|
||||
|
@ -961,4 +1184,3 @@ PDFColorProfileIdentifier PDFColorProfileIdentifier::createFile(Type type, QStri
|
|||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
|
|
|
@ -128,7 +128,47 @@ public:
|
|||
/// \param color Input color
|
||||
/// \param iccID Unique ICC profile identifier
|
||||
/// \param iccData Color profile data
|
||||
/// \param reporter Render error reporter (used, when color transform fails)
|
||||
virtual QColor getColorFromICC(const PDFColor& color, RenderingIntent renderingIntent, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const = 0;
|
||||
|
||||
/// Fills colors in Device Gray color space to the RGB buffer. If error occurs, then false is returned.
|
||||
/// Caller then should handle this - try to convert color as accurate as possible.
|
||||
/// \param color Gray values
|
||||
/// \param intent Rendering intent
|
||||
/// \param outputBuffer Output buffer in format RGB_888 (8-bit RGB values)
|
||||
/// \param reporter Render error reporter (used, when color transform fails)
|
||||
virtual bool fillRGBBufferFromDeviceGray(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const = 0;
|
||||
|
||||
/// Fills colors in Device RGB color space to RGB buffer. If error occurs, then false is returned.
|
||||
/// Caller then should handle this - try to convert color as accurate as possible.
|
||||
/// \param colors Buffer with three color channels, so it has pixels * tuple(R, G, B) size
|
||||
/// \param intent Rendering intent
|
||||
/// \param outputBuffer Output buffer in format RGB_888 (8-bit RGB values)
|
||||
/// \param reporter Render error reporter (used, when color transform fails)
|
||||
virtual bool fillRGBBufferFromDeviceRGB(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const = 0;
|
||||
|
||||
/// Fills colors in Device CMYK color space to the RGB buffer. If error occurs, then false is returned.
|
||||
/// Caller then should handle this - try to convert color as accurate as possible.
|
||||
/// \param colors FBuffer with four color channels (C,M,Y,K channel), so it has pixels * tuple(C, M, Y, K) size
|
||||
/// \param intent Rendering intent
|
||||
/// \param outputBuffer Output buffer in format RGB_888 (8-bit RGB values)
|
||||
/// \param reporter Render error reporter (used, when color transform fails)
|
||||
virtual bool fillRGBBufferFromDeviceCMYK(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const = 0;
|
||||
|
||||
/// Fills colors in XYZ color space to the RGB buffer. If error occurs, then false is returned.
|
||||
/// Caller then should handle this - try to convert color as accurate as possible.
|
||||
/// \param whitePoint White point of source XYZ color space
|
||||
/// \param Three color channel value (X,Y,Z channel)
|
||||
/// \param intent Rendering intent
|
||||
/// \param reporter Render error reporter (used, when color transform fails)
|
||||
virtual bool fillRGBBufferFromXYZ(const PDFColor3& whitePoint, const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const = 0;
|
||||
|
||||
/// Fills RGB buffer from ICC color profile colors
|
||||
/// \param colors Input colors
|
||||
/// \param iccID Unique ICC profile identifier
|
||||
/// \param iccData Color profile data
|
||||
/// \param reporter Render error reporter (used, when color transform fails)
|
||||
virtual bool fillRGBBufferFromICC(const std::vector<float>& colors, RenderingIntent renderingIntent, unsigned char* outputBuffer, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const = 0;
|
||||
};
|
||||
|
||||
using PDFCMSPointer = QSharedPointer<PDFCMS>;
|
||||
|
@ -145,6 +185,11 @@ public:
|
|||
virtual QColor getColorFromDeviceCMYK(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual QColor getColorFromXYZ(const PDFColor3& whitePoint, const PDFColor3& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual QColor getColorFromICC(const PDFColor& color, RenderingIntent renderingIntent, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromDeviceGray(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromDeviceRGB(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromDeviceCMYK(const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromXYZ(const PDFColor3& whitePoint, const std::vector<float>& colors, RenderingIntent intent, unsigned char* outputBuffer, PDFRenderErrorReporter* reporter) const override;
|
||||
virtual bool fillRGBBufferFromICC(const std::vector<float>& colors, RenderingIntent renderingIntent, unsigned char* outputBuffer, const QByteArray& iccID, const QByteArray& iccData, PDFRenderErrorReporter* reporter) const override;
|
||||
};
|
||||
|
||||
struct PDFColorProfileIdentifier
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include <execution>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
|
@ -58,6 +60,14 @@ size_t PDFDeviceGrayColorSpace::getColorComponentCount() const
|
|||
return 1;
|
||||
}
|
||||
|
||||
void PDFDeviceGrayColorSpace::fillRGBBuffer(const std::vector<float>& colors, unsigned char* outputBuffer, RenderingIntent intent, const PDFCMS* cms, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
if (!cms->fillRGBBufferFromDeviceGray(colors, intent, outputBuffer, reporter))
|
||||
{
|
||||
PDFAbstractColorSpace::fillRGBBuffer(colors, outputBuffer, intent, cms, reporter);
|
||||
}
|
||||
}
|
||||
|
||||
QColor PDFDeviceRGBColorSpace::getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
return getColor(PDFColor(0.0f, 0.0f, 0.0f), cms, intent, reporter);
|
||||
|
@ -88,6 +98,14 @@ size_t PDFDeviceRGBColorSpace::getColorComponentCount() const
|
|||
return 3;
|
||||
}
|
||||
|
||||
void PDFDeviceRGBColorSpace::fillRGBBuffer(const std::vector<float>& colors, unsigned char* outputBuffer, RenderingIntent intent, const PDFCMS* cms, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
if (!cms->fillRGBBufferFromDeviceRGB(colors, intent, outputBuffer, reporter))
|
||||
{
|
||||
PDFAbstractColorSpace::fillRGBBuffer(colors, outputBuffer, intent, cms, reporter);
|
||||
}
|
||||
}
|
||||
|
||||
QColor PDFDeviceCMYKColorSpace::getDefaultColor(const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
return getColor(PDFColor(0.0f, 0.0f, 0.0f, 1.0f), cms, intent, reporter);
|
||||
|
@ -119,6 +137,14 @@ size_t PDFDeviceCMYKColorSpace::getColorComponentCount() const
|
|||
return 4;
|
||||
}
|
||||
|
||||
void PDFDeviceCMYKColorSpace::fillRGBBuffer(const std::vector<float>& colors, unsigned char* outputBuffer, RenderingIntent intent, const PDFCMS* cms, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
if (!cms->fillRGBBufferFromDeviceCMYK(colors, intent, outputBuffer, reporter))
|
||||
{
|
||||
PDFAbstractColorSpace::fillRGBBuffer(colors, outputBuffer, intent, cms, reporter);
|
||||
}
|
||||
}
|
||||
|
||||
QImage PDFAbstractColorSpace::getImage(const PDFImageData& imageData,
|
||||
const PDFImageData& softMask,
|
||||
const PDFCMS* cms,
|
||||
|
@ -146,18 +172,20 @@ QImage PDFAbstractColorSpace::getImage(const PDFImageData& imageData,
|
|||
throw PDFException(PDFTranslationContext::tr("Invalid size of the decode array. Expected %1, actual %2.").arg(componentCount * 2).arg(decode.size()));
|
||||
}
|
||||
|
||||
PDFBitReader reader(&imageData.getData(), imageData.getBitsPerComponent());
|
||||
|
||||
PDFColor color;
|
||||
color.resize(componentCount);
|
||||
|
||||
const double max = reader.max();
|
||||
const double coefficient = 1.0 / max;
|
||||
for (unsigned int i = 0, rowCount = imageData.getHeight(); i < rowCount; ++i)
|
||||
const unsigned int imageWidth = imageData.getWidth();
|
||||
const unsigned int imageHeight = imageData.getHeight();
|
||||
//for (unsigned int i = 0, rowCount = imageData.getHeight(); i < rowCount; ++i)
|
||||
auto transformPixelLine = [&](unsigned int i)
|
||||
{
|
||||
PDFBitReader reader(&imageData.getData(), imageData.getBitsPerComponent());
|
||||
reader.seek(i * imageData.getStride());
|
||||
|
||||
const double max = reader.max();
|
||||
const double coefficient = 1.0 / max;
|
||||
unsigned char* outputLine = image.scanLine(i);
|
||||
|
||||
std::vector<float> inputColors(imageWidth * componentCount, 0.0f);
|
||||
auto itInputColor = inputColors.begin();
|
||||
for (unsigned int j = 0; j < imageData.getWidth(); ++j)
|
||||
{
|
||||
for (unsigned int k = 0; k < componentCount; ++k)
|
||||
|
@ -167,22 +195,20 @@ QImage PDFAbstractColorSpace::getImage(const PDFImageData& imageData,
|
|||
// Interpolate value, if it is not empty
|
||||
if (!decode.empty())
|
||||
{
|
||||
color[k] = interpolate(value, 0.0, max, decode[2 * k], decode[2 * k + 1]);
|
||||
*itInputColor++ = interpolate(value, 0.0, max, decode[2 * k], decode[2 * k + 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
color[k] = value * coefficient;
|
||||
*itInputColor++ = value * coefficient;
|
||||
}
|
||||
}
|
||||
|
||||
QColor transformedColor = getColor(color, cms, intent, reporter);
|
||||
QRgb rgb = transformedColor.rgb();
|
||||
|
||||
*outputLine++ = qRed(rgb);
|
||||
*outputLine++ = qGreen(rgb);
|
||||
*outputLine++ = qBlue(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
fillRGBBuffer(inputColors, outputLine, intent, cms, reporter);
|
||||
};
|
||||
|
||||
auto range = PDFIntegerRange<unsigned int>(0, imageHeight);
|
||||
std::for_each(std::execution::parallel_policy(), range.begin(), range.end(), transformPixelLine);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
@ -341,6 +367,34 @@ QImage PDFAbstractColorSpace::getImage(const PDFImageData& imageData,
|
|||
return QImage();
|
||||
}
|
||||
|
||||
void PDFAbstractColorSpace::fillRGBBuffer(const std::vector<float>& colors,
|
||||
unsigned char* outputBuffer,
|
||||
RenderingIntent intent,
|
||||
const PDFCMS* cms,
|
||||
PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
// Generic solution
|
||||
size_t colorComponentCount = getColorComponentCount();
|
||||
size_t pixels = colors.size() / colorComponentCount;
|
||||
|
||||
auto it = colors.cbegin();
|
||||
for (size_t i = 0; i < pixels; ++i)
|
||||
{
|
||||
PDFColor color;
|
||||
color.resize(colorComponentCount);
|
||||
for (size_t j = 0; j < colorComponentCount; ++j)
|
||||
{
|
||||
color[j] = *it++;
|
||||
}
|
||||
QColor transformedColor = getColor(color, cms, intent, reporter);
|
||||
QRgb rgb = transformedColor.rgb();
|
||||
|
||||
*outputBuffer++ = qRed(rgb);
|
||||
*outputBuffer++ = qGreen(rgb);
|
||||
*outputBuffer++ = qBlue(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
QColor PDFAbstractColorSpace::getCheckedColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
if (getColorComponentCount() != color.size())
|
||||
|
@ -700,6 +754,25 @@ size_t PDFCalGrayColorSpace::getColorComponentCount() const
|
|||
return 1;
|
||||
}
|
||||
|
||||
void PDFCalGrayColorSpace::fillRGBBuffer(const std::vector<float>& colors, unsigned char* outputBuffer, RenderingIntent intent, const PDFCMS* cms, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
std::vector<float> xyzColors(colors.size() * 3, 0.0f);
|
||||
auto it = xyzColors.begin();
|
||||
for (float gray : colors)
|
||||
{
|
||||
const PDFColorComponent xyzColor = std::powf(clip01(gray), m_gamma);
|
||||
*it++ = xyzColor;
|
||||
*it++ = xyzColor;
|
||||
*it++ = xyzColor;
|
||||
}
|
||||
|
||||
Q_ASSERT(xyzColors.size() == colors.size() * 3);
|
||||
if (!cms->fillRGBBufferFromXYZ(m_whitePoint, xyzColors, intent, outputBuffer, reporter))
|
||||
{
|
||||
PDFAbstractColorSpace::fillRGBBuffer(colors, outputBuffer, intent, cms, reporter);
|
||||
}
|
||||
}
|
||||
|
||||
PDFColorSpacePointer PDFCalGrayColorSpace::createCalGrayColorSpace(const PDFDocument* document, const PDFDictionary* dictionary)
|
||||
{
|
||||
// Standard D65 white point
|
||||
|
@ -748,6 +821,29 @@ size_t PDFCalRGBColorSpace::getColorComponentCount() const
|
|||
return 3;
|
||||
}
|
||||
|
||||
void PDFCalRGBColorSpace::fillRGBBuffer(const std::vector<float>& colors, unsigned char* outputBuffer, RenderingIntent intent, const PDFCMS* cms, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
std::vector<float> xyzColors(colors.size(), 0.0f);
|
||||
auto it = xyzColors.begin();
|
||||
for (size_t i = 0; i < colors.size(); i += 3)
|
||||
{
|
||||
Q_ASSERT(i + 2 < colors.size());
|
||||
const PDFColor3 ABC = clip01(PDFColor3{ colors[i + 0], colors[i + 1], colors[i + 2] });
|
||||
const PDFColor3 ABCwithGamma = colorPowerByFactors(ABC, m_gamma);
|
||||
const PDFColor3 XYZ = m_matrix * ABCwithGamma;
|
||||
|
||||
*it++ = XYZ[0];
|
||||
*it++ = XYZ[1];
|
||||
*it++ = XYZ[2];
|
||||
}
|
||||
|
||||
Q_ASSERT(xyzColors.size() == colors.size());
|
||||
if (!cms->fillRGBBufferFromXYZ(m_whitePoint, xyzColors, intent, outputBuffer, reporter))
|
||||
{
|
||||
PDFAbstractColorSpace::fillRGBBuffer(colors, outputBuffer, intent, cms, reporter);
|
||||
}
|
||||
}
|
||||
|
||||
PDFColorSpacePointer PDFCalRGBColorSpace::createCalRGBColorSpace(const PDFDocument* document, const PDFDictionary* dictionary)
|
||||
{
|
||||
// Standard D65 white point
|
||||
|
@ -833,6 +929,50 @@ size_t PDFLabColorSpace::getColorComponentCount() const
|
|||
return 3;
|
||||
}
|
||||
|
||||
void PDFLabColorSpace::fillRGBBuffer(const std::vector<float>& colors, unsigned char* outputBuffer, RenderingIntent intent, const PDFCMS* cms, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
auto g = [](PDFColorComponent x) -> PDFColorComponent
|
||||
{
|
||||
if (x >= 6.0f / 29.0f)
|
||||
{
|
||||
return x * x * x;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (108.0f / 841.0f) * (x - 4.0f / 29.0f);
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<float> xyzColors(colors.size(), 0.0f);
|
||||
auto it = xyzColors.begin();
|
||||
for (size_t i = 0; i < colors.size(); i += 3)
|
||||
{
|
||||
Q_ASSERT(i + 2 < colors.size());
|
||||
|
||||
const PDFColorComponent LStar = qBound(0.0, interpolate(colors[i + 0], 0.0, 1.0, 0.0, 100.0), 100.0);
|
||||
const PDFColorComponent aStar = qBound<PDFColorComponent>(m_aMin, interpolate(colors[i + 1], 0.0, 1.0, m_aMin, m_aMax), m_aMax);
|
||||
const PDFColorComponent bStar = qBound<PDFColorComponent>(m_bMin, interpolate(colors[i + 2], 0.0, 1.0, m_bMin, m_bMax), m_bMax);
|
||||
|
||||
const PDFColorComponent param1 = (LStar + 16.0f) / 116.0f;
|
||||
const PDFColorComponent param2 = aStar / 500.0f;
|
||||
const PDFColorComponent param3 = bStar / 200.0f;
|
||||
|
||||
const PDFColorComponent L = param1 + param2;
|
||||
const PDFColorComponent M = param1;
|
||||
const PDFColorComponent N = param1 - param3;
|
||||
|
||||
*it++ = g(L);
|
||||
*it++ = g(M);
|
||||
*it++ = g(N);
|
||||
}
|
||||
|
||||
Q_ASSERT(xyzColors.size() == colors.size());
|
||||
if (!cms->fillRGBBufferFromXYZ(m_whitePoint, xyzColors, intent, outputBuffer, reporter))
|
||||
{
|
||||
PDFAbstractColorSpace::fillRGBBuffer(colors, outputBuffer, intent, cms, reporter);
|
||||
}
|
||||
}
|
||||
|
||||
PDFColorSpacePointer PDFLabColorSpace::createLabColorSpace(const PDFDocument* document, const PDFDictionary* dictionary)
|
||||
{
|
||||
// Standard D65 white point
|
||||
|
@ -901,6 +1041,25 @@ size_t PDFICCBasedColorSpace::getColorComponentCount() const
|
|||
return m_alternateColorSpace->getColorComponentCount();
|
||||
}
|
||||
|
||||
void PDFICCBasedColorSpace::fillRGBBuffer(const std::vector<float>& colors, unsigned char* outputBuffer, RenderingIntent intent, const PDFCMS* cms, PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
size_t colorComponentCount = getColorComponentCount();
|
||||
std::vector<float> clippedColors(colors.size(), 0.0f);
|
||||
for (size_t i = 0, colorCount = colors.size(); i < colorCount; ++i)
|
||||
{
|
||||
const size_t componentIndex = i % colorComponentCount;
|
||||
const size_t imin = 2 * componentIndex + 0;
|
||||
const size_t imax = 2 * componentIndex + 1;
|
||||
clippedColors[i] = qBound(m_range[imin], colors[i], m_range[imax]);
|
||||
}
|
||||
|
||||
if (!cms->fillRGBBufferFromICC(clippedColors, intent, outputBuffer, m_iccProfileDataChecksum, m_iccProfileData, reporter))
|
||||
{
|
||||
// Try to fill buffer from alternate color space
|
||||
m_alternateColorSpace->fillRGBBuffer(clippedColors, outputBuffer, intent, cms, reporter);
|
||||
}
|
||||
}
|
||||
|
||||
PDFColorSpacePointer PDFICCBasedColorSpace::createICCBasedColorSpace(const PDFDictionary* colorSpaceDictionary,
|
||||
const PDFDocument* document,
|
||||
const PDFStream* stream,
|
||||
|
|
|
@ -245,6 +245,20 @@ public:
|
|||
RenderingIntent intent,
|
||||
PDFRenderErrorReporter* reporter) const;
|
||||
|
||||
/// Fills RGB buffer using colors from \p colors. Colors are transformed
|
||||
/// by this color space (or color management system is used). Buffer
|
||||
/// must be big enough to contain all 8-bit RGB data.
|
||||
/// \param Colors Input color buffer
|
||||
/// \param intent Rendering intent
|
||||
/// \param outputBuffer 8-bit RGB output buffer
|
||||
/// \param cms Color management system
|
||||
/// \param reporter Render error reporter
|
||||
virtual void fillRGBBuffer(const std::vector<float>& colors,
|
||||
unsigned char* outputBuffer,
|
||||
RenderingIntent intent,
|
||||
const PDFCMS* cms,
|
||||
PDFRenderErrorReporter* reporter) const;
|
||||
|
||||
/// If this class is pattern space, returns this, otherwise returns nullptr.
|
||||
virtual const PDFPatternColorSpace* asPatternColorSpace() const { return nullptr; }
|
||||
|
||||
|
@ -400,6 +414,7 @@ public:
|
|||
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) 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;
|
||||
};
|
||||
|
||||
class PDFDeviceRGBColorSpace : public PDFAbstractColorSpace
|
||||
|
@ -411,6 +426,7 @@ public:
|
|||
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) 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;
|
||||
};
|
||||
|
||||
class PDFDeviceCMYKColorSpace : public PDFAbstractColorSpace
|
||||
|
@ -422,6 +438,7 @@ public:
|
|||
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) 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;
|
||||
};
|
||||
|
||||
class PDFXYZColorSpace : public PDFAbstractColorSpace
|
||||
|
@ -450,6 +467,7 @@ public:
|
|||
|
||||
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) 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;
|
||||
|
||||
/// Creates CalGray color space from provided values.
|
||||
/// \param document Document
|
||||
|
@ -469,6 +487,7 @@ public:
|
|||
|
||||
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) 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;
|
||||
|
||||
/// Creates CalRGB color space from provided values.
|
||||
/// \param document Document
|
||||
|
@ -489,6 +508,7 @@ public:
|
|||
|
||||
virtual QColor getColor(const PDFColor& color, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) 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;
|
||||
|
||||
/// Creates Lab color space from provided values.
|
||||
/// \param document Document
|
||||
|
@ -516,6 +536,7 @@ public:
|
|||
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) 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;
|
||||
|
||||
/// Creates ICC based color space from provided values.
|
||||
/// \param colorSpaceDictionary Color space dictionary
|
||||
|
|
Loading…
Reference in New Issue