mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-02-21 22:17:44 +01:00
Axial mapping finishing, fix of color mapping
This commit is contained in:
parent
d9c6c5e2b4
commit
08815d1b8b
@ -271,7 +271,8 @@ public:
|
||||
Indexed,
|
||||
Separation,
|
||||
DeviceN,
|
||||
Pattern
|
||||
Pattern,
|
||||
Invalid
|
||||
};
|
||||
|
||||
/// Returns color space identification
|
||||
|
@ -362,6 +362,8 @@ void PDFPageContentProcessor::performPathPainting(const QPainterPath& path, bool
|
||||
bool PDFPageContentProcessor::performPathPaintingUsingShading(const QPainterPath& path, bool stroke, bool fill, const PDFShadingPattern* shadingPattern)
|
||||
{
|
||||
Q_UNUSED(path);
|
||||
Q_UNUSED(stroke);
|
||||
Q_UNUSED(fill);
|
||||
Q_UNUSED(shadingPattern);
|
||||
|
||||
return false;
|
||||
|
@ -319,6 +319,9 @@ public:
|
||||
/// Returns color space of the pattern.
|
||||
const PDFAbstractColorSpace* getColorSpace() const;
|
||||
|
||||
/// Returns color space pointer
|
||||
const PDFColorSpacePointer& getColorSpacePtr() const { return m_colorSpace; }
|
||||
|
||||
/// Returns patterns background color (if pattern has background color).
|
||||
/// If pattern has not background color, then invalid color is returned.
|
||||
const QColor& getBackgroundColor() const { return m_backgroundColor; }
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "pdfimage.h"
|
||||
#include "pdfpattern.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
@ -711,7 +713,7 @@ PDFFloatBitmapWithColorSpace::PDFFloatBitmapWithColorSpace(size_t width, size_t
|
||||
PDFFloatBitmap(width, height, format),
|
||||
m_colorSpace(blendColorSpace)
|
||||
{
|
||||
Q_ASSERT(!blendColorSpace || blendColorSpace->isBlendColorSpace());
|
||||
|
||||
}
|
||||
|
||||
PDFColorSpacePointer PDFFloatBitmapWithColorSpace::getColorSpace() const
|
||||
@ -1188,6 +1190,60 @@ PDFFloatBitmapWithColorSpace PDFTransparencyRenderer::getImage(const PDFImage& s
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
PDFFloatBitmapWithColorSpace PDFTransparencyRenderer::convertImageToBlendSpace(const PDFFloatBitmapWithColorSpace& image)
|
||||
{
|
||||
PDFFloatBitmapWithColorSpace convertedImage(image.getWidth(), image.getHeight(), m_drawBuffer.getPixelFormat(), getBlendColorSpace());
|
||||
auto imageColorSpace = image.getColorSpace();
|
||||
Q_ASSERT(imageColorSpace);
|
||||
const PDFFloatBitmapWithColorSpace* sourceImage = ℑ
|
||||
PDFFloatBitmapWithColorSpace temporaryImage;
|
||||
|
||||
PDFInkMapping inkMapping = m_inkMapper->createMapping(imageColorSpace.data(), getBlendColorSpace().data(), m_drawBuffer.getPixelFormat());
|
||||
if (!inkMapping.isValid())
|
||||
{
|
||||
temporaryImage = image;
|
||||
temporaryImage.convertToColorSpace(getCMS(), getGraphicState()->getRenderingIntent(), getBlendColorSpace(), this);
|
||||
inkMapping = m_inkMapper->createMapping(getBlendColorSpace().data(), getBlendColorSpace().data(), m_drawBuffer.getPixelFormat());
|
||||
sourceImage = &temporaryImage;
|
||||
}
|
||||
|
||||
Q_ASSERT(inkMapping.isValid());
|
||||
|
||||
const uint8_t sourceBufferShapeChannelIndex = sourceImage->getPixelFormat().getShapeChannelIndex();
|
||||
const uint8_t sourceBufferOpacityChannelIndex = sourceImage->getPixelFormat().getOpacityChannelIndex();
|
||||
const uint8_t targetBufferShapeChannelIndex = convertedImage.getPixelFormat().getShapeChannelIndex();
|
||||
const uint8_t targetBufferOpacityChannelIndex = convertedImage.getPixelFormat().getOpacityChannelIndex();
|
||||
|
||||
for (size_t y = 0; y < sourceImage->getHeight(); ++y)
|
||||
{
|
||||
for (size_t x = 0; x < sourceImage->getWidth(); ++x)
|
||||
{
|
||||
PDFConstColorBuffer sourceBuffer = sourceImage->getPixel(x, y);
|
||||
PDFColorBuffer targetBuffer = convertedImage.getPixel(x, y);
|
||||
|
||||
for (const PDFInkMapping::Mapping& ink : inkMapping.mapping)
|
||||
{
|
||||
switch (ink.type)
|
||||
{
|
||||
case pdf::PDFInkMapping::Pass:
|
||||
targetBuffer[ink.target] = sourceBuffer[ink.source];
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
targetBuffer[targetBufferShapeChannelIndex] = sourceBuffer[sourceBufferShapeChannelIndex];
|
||||
targetBuffer[targetBufferOpacityChannelIndex] = sourceBuffer[sourceBufferOpacityChannelIndex];
|
||||
}
|
||||
}
|
||||
|
||||
convertedImage.setColorActivity(inkMapping.activeChannels);
|
||||
return convertedImage;
|
||||
}
|
||||
|
||||
PDFFloatBitmapWithColorSpace PDFTransparencyRenderer::getColoredImage(const PDFImage& sourceImage)
|
||||
{
|
||||
PDFFloatBitmapWithColorSpace result;
|
||||
@ -1564,51 +1620,7 @@ PDFFloatBitmapWithColorSpace PDFTransparencyRenderer::getColoredImage(const PDFI
|
||||
}
|
||||
|
||||
// Jakub Melka: We are mapping into draw buffer, so we must use draw buffer pixel format
|
||||
PDFInkMapping inkMapping = m_inkMapper->createMapping(imageColorSpace.data(), getBlendColorSpace().data(), m_drawBuffer.getPixelFormat());
|
||||
if (!inkMapping.isValid())
|
||||
{
|
||||
result.convertToColorSpace(getCMS(), getGraphicState()->getRenderingIntent(), getBlendColorSpace(), this);
|
||||
inkMapping = m_inkMapper->createMapping(getBlendColorSpace().data(), getBlendColorSpace().data(), m_drawBuffer.getPixelFormat());
|
||||
}
|
||||
|
||||
Q_ASSERT(inkMapping.isValid());
|
||||
|
||||
PDFFloatBitmapWithColorSpace finalResult(result.getWidth(), result.getHeight(), m_drawBuffer.getPixelFormat(), getBlendColorSpace());
|
||||
|
||||
const uint8_t sourceBufferShapeChannelIndex = result.getPixelFormat().getShapeChannelIndex();
|
||||
const uint8_t sourceBufferOpacityChannelIndex = result.getPixelFormat().getOpacityChannelIndex();
|
||||
const uint8_t targetBufferShapeChannelIndex = finalResult.getPixelFormat().getShapeChannelIndex();
|
||||
const uint8_t targetBufferOpacityChannelIndex = finalResult.getPixelFormat().getOpacityChannelIndex();
|
||||
|
||||
for (size_t y = 0; y < result.getHeight(); ++y)
|
||||
{
|
||||
for (size_t x = 0; x < result.getWidth(); ++x)
|
||||
{
|
||||
PDFColorBuffer sourceBuffer = result.getPixel(x, y);
|
||||
PDFColorBuffer targetBuffer = finalResult.getPixel(x, y);
|
||||
|
||||
for (const PDFInkMapping::Mapping& ink : inkMapping.mapping)
|
||||
{
|
||||
switch (ink.type)
|
||||
{
|
||||
case pdf::PDFInkMapping::Pass:
|
||||
targetBuffer[ink.target] = sourceBuffer[ink.source];
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
targetBuffer[targetBufferShapeChannelIndex] = sourceBuffer[sourceBufferShapeChannelIndex];
|
||||
targetBuffer[targetBufferOpacityChannelIndex] = sourceBuffer[sourceBufferOpacityChannelIndex];
|
||||
}
|
||||
}
|
||||
|
||||
result = qMove(finalResult);
|
||||
result.setColorActivity(inkMapping.activeChannels);
|
||||
return result;
|
||||
return convertImageToBlendSpace(result);
|
||||
}
|
||||
|
||||
PDFFloatBitmap PDFTransparencyRenderer::getAlphaMaskFromSoftMask(const PDFImageData& softMask)
|
||||
@ -1840,6 +1852,9 @@ bool PDFTransparencyRenderer::performPathPaintingUsingShading(const QPainterPath
|
||||
return true;
|
||||
}
|
||||
|
||||
// Exactly one of stroke/fill must be true and other must be false
|
||||
Q_ASSERT(stroke != fill);
|
||||
|
||||
QMatrix worldMatrix = getCurrentWorldMatrix();
|
||||
QPainterPath worldPath = worldMatrix.map(path);
|
||||
QRect fillRect = getActualFillRect(worldPath.controlPointRect());
|
||||
@ -1862,12 +1877,12 @@ bool PDFTransparencyRenderer::performPathPaintingUsingShading(const QPainterPath
|
||||
// as color source.
|
||||
const PDFAbstractColorSpace* colorSpace = shadingPattern->getColorSpace();
|
||||
const size_t shadingColorComponentCount = colorSpace->getColorComponentCount();
|
||||
PDFFloatBitmapWithColorSpace texture(fillRect.width() + 1, fillRect.height() + 1, PDFPixelFormat::createFormat(shadingColorComponentCount, 0, true, shadingColorComponentCount == 4, false), colorSpace);
|
||||
PDFFloatBitmapWithColorSpace texture(fillRect.width() + 1, fillRect.height() + 1, PDFPixelFormat::createFormat(uint8_t(shadingColorComponentCount), 0, true, shadingColorComponentCount == 4, false), shadingPattern->getColorSpacePtr());
|
||||
QPointF offset = fillRect.topLeft();
|
||||
|
||||
const PDFPixelFormat texturePixelFormat = texture.getPixelFormat();
|
||||
const uint8_t textureShapeChannel = texturePixelFormat.getShapeChannelIndex();
|
||||
const uint8_t textureOpacityChannel = texturePixelFormat.getOpacityChannelIndex();
|
||||
PDFPixelFormat texturePixelFormat = texture.getPixelFormat();
|
||||
uint8_t textureShapeChannel = texturePixelFormat.getShapeChannelIndex();
|
||||
uint8_t textureOpacityChannel = texturePixelFormat.getOpacityChannelIndex();
|
||||
|
||||
if (fillRect.width() > fillRect.height())
|
||||
{
|
||||
@ -1904,14 +1919,58 @@ bool PDFTransparencyRenderer::performPathPaintingUsingShading(const QPainterPath
|
||||
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, range.begin(), range.end(), processEntry);
|
||||
}
|
||||
|
||||
// Convert image to a blend color space
|
||||
texture = convertImageToBlendSpace(texture);
|
||||
texturePixelFormat = texture.getPixelFormat();
|
||||
textureShapeChannel = texturePixelFormat.getShapeChannelIndex();
|
||||
textureOpacityChannel = texturePixelFormat.getOpacityChannelIndex();
|
||||
|
||||
PDFPainterPathSampler clipSampler(m_painterStateStack.top().clipPath, m_settings.samplesCount, 1.0f, fillRect, m_settings.flags.testFlag(PDFTransparencyRendererSettings::PrecisePathSampler));
|
||||
PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f, fillRect, m_settings.flags.testFlag(PDFTransparencyRendererSettings::PrecisePathSampler));
|
||||
|
||||
const PDFReal constantShape = stroke ? getShapeStroking() : getShapeFilling();
|
||||
const PDFReal constantOpacity = stroke ? getOpacityStroking() : getOpacityFilling();
|
||||
|
||||
Q_ASSERT(m_drawBuffer.getPixelFormat() == texture.getPixelFormat());
|
||||
|
||||
const PDFPixelFormat drawBufferPixelFormat = m_drawBuffer.getPixelFormat();
|
||||
const uint8_t drawBufferShapeChannel = drawBufferPixelFormat.getShapeChannelIndex();
|
||||
const uint8_t drawBufferOpacityChannel = drawBufferPixelFormat.getOpacityChannelIndex();
|
||||
const uint32_t colorChannelStart = drawBufferPixelFormat.getColorChannelIndexStart();
|
||||
const uint32_t colorChannelEnd = drawBufferPixelFormat.getColorChannelIndexEnd();
|
||||
|
||||
for (int x = fillRect.left(); x <= fillRect.right(); ++x)
|
||||
{
|
||||
for (int y = fillRect.top(); y <= fillRect.bottom(); ++y)
|
||||
{
|
||||
/* performPixelSampling(shapeStroking, opacityStroking, shapeChannel, opacityChannel, colorChannelStart, colorChannelEnd, x, y, strokeColor, clipSampler, pathSampler);*/
|
||||
const int texelCoordinateX = x - fillRect.left();
|
||||
const int texelCoordinateY = y - fillRect.top();
|
||||
PDFColorBuffer texel = texture.getPixel(texelCoordinateX, texelCoordinateY);
|
||||
|
||||
const PDFColorComponent textureShape = texel[drawBufferShapeChannel];
|
||||
const PDFColorComponent textureOpacity = texel[drawBufferOpacityChannel];
|
||||
const PDFColorComponent clipValue = clipSampler.sample(QPoint(x, y));
|
||||
const PDFColorComponent objectShapeValue = pathSampler.sample(QPoint(x, y));
|
||||
const PDFColorComponent shapeValue = objectShapeValue * clipValue * constantShape * textureShape;
|
||||
const PDFColorComponent opacityValue = shapeValue * constantOpacity * textureOpacity;
|
||||
|
||||
if (shapeValue > 0.0f)
|
||||
{
|
||||
// We consider old object shape - we use Union function to
|
||||
// set shape channel value.
|
||||
|
||||
PDFColorBuffer pixel = m_drawBuffer.getPixel(x, y);
|
||||
pixel[drawBufferShapeChannel] = PDFBlendFunction::blend_Union(shapeValue, pixel[drawBufferShapeChannel]);
|
||||
pixel[drawBufferOpacityChannel] = opacityValue;
|
||||
|
||||
// Copy color
|
||||
for (uint8_t colorChannelIndex = colorChannelStart; colorChannelIndex < colorChannelEnd; ++colorChannelIndex)
|
||||
{
|
||||
pixel[colorChannelIndex] = texel[colorChannelIndex];
|
||||
}
|
||||
|
||||
m_drawBuffer.markPixelActiveColorMask(x, y, texture.getPixelActiveColorMask(texelCoordinateX, texelCoordinateY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2572,10 +2631,17 @@ bool PDFTransparencyRenderer::isMultithreadedPathSamplingUsed(QRect fillRect) co
|
||||
PDFInkMapper::PDFInkMapper(const PDFDocument* document) :
|
||||
m_document(document)
|
||||
{
|
||||
// Initialize device separations
|
||||
std::vector<ColorInfo> graySeparations = getSeparations(1, false);
|
||||
std::vector<ColorInfo> rgbSeparations = getSeparations(3, false);
|
||||
std::vector<ColorInfo> cmykSeparations = getSeparations(4, false);
|
||||
|
||||
m_deviceColors.insert(m_deviceColors.end(), std::make_move_iterator(graySeparations.begin()), std::make_move_iterator(graySeparations.end()));
|
||||
m_deviceColors.insert(m_deviceColors.end(), std::make_move_iterator(rgbSeparations.begin()), std::make_move_iterator(rgbSeparations.end()));
|
||||
m_deviceColors.insert(m_deviceColors.end(), std::make_move_iterator(cmykSeparations.begin()), std::make_move_iterator(cmykSeparations.end()));
|
||||
}
|
||||
|
||||
std::vector<PDFInkMapper::ColorInfo> PDFInkMapper::getSeparations(uint32_t processColorCount) const
|
||||
std::vector<PDFInkMapper::ColorInfo> PDFInkMapper::getSeparations(uint32_t processColorCount, bool withSpots) const
|
||||
{
|
||||
std::vector<ColorInfo> result;
|
||||
result.reserve(getActiveSpotColorCount() + processColorCount);
|
||||
@ -2585,11 +2651,13 @@ std::vector<PDFInkMapper::ColorInfo> PDFInkMapper::getSeparations(uint32_t proce
|
||||
case 1:
|
||||
{
|
||||
ColorInfo gray;
|
||||
gray.name = "Process Gray";
|
||||
gray.name = "Gray";
|
||||
gray.textName = PDFTranslationContext::tr("Process Gray");
|
||||
gray.canBeActive = true;
|
||||
gray.active = true;
|
||||
gray.isSpot = false;
|
||||
gray.spotColorIndex = 0;
|
||||
gray.colorSpaceType = PDFAbstractColorSpace::ColorSpace::DeviceGray;
|
||||
result.emplace_back(qMove(gray));
|
||||
break;
|
||||
}
|
||||
@ -2597,27 +2665,33 @@ std::vector<PDFInkMapper::ColorInfo> PDFInkMapper::getSeparations(uint32_t proce
|
||||
case 3:
|
||||
{
|
||||
ColorInfo red;
|
||||
red.name = "Process Red";
|
||||
red.name = "Red";
|
||||
red.textName = PDFTranslationContext::tr("Process Red");
|
||||
red.canBeActive = true;
|
||||
red.active = true;
|
||||
red.isSpot = false;
|
||||
red.spotColorIndex = 0;
|
||||
red.colorSpaceType = PDFAbstractColorSpace::ColorSpace::DeviceRGB;
|
||||
result.emplace_back(qMove(red));
|
||||
|
||||
ColorInfo green;
|
||||
green.name = "Process Green";
|
||||
green.name = "Green";
|
||||
green.textName = PDFTranslationContext::tr("Process Green");
|
||||
green.canBeActive = true;
|
||||
green.active = true;
|
||||
green.isSpot = false;
|
||||
green.spotColorIndex = 1;
|
||||
green.colorSpaceType = PDFAbstractColorSpace::ColorSpace::DeviceRGB;
|
||||
result.emplace_back(qMove(green));
|
||||
|
||||
ColorInfo blue;
|
||||
blue.name = "Process Blue";
|
||||
blue.name = "Blue";
|
||||
blue.textName = PDFTranslationContext::tr("Process Blue");
|
||||
blue.canBeActive = true;
|
||||
blue.active = true;
|
||||
blue.isSpot = false;
|
||||
blue.spotColorIndex = 2;
|
||||
blue.colorSpaceType = PDFAbstractColorSpace::ColorSpace::DeviceRGB;
|
||||
result.emplace_back(qMove(blue));
|
||||
break;
|
||||
}
|
||||
@ -2625,35 +2699,43 @@ std::vector<PDFInkMapper::ColorInfo> PDFInkMapper::getSeparations(uint32_t proce
|
||||
case 4:
|
||||
{
|
||||
ColorInfo cyan;
|
||||
cyan.name = "Process Cyan";
|
||||
cyan.name = "Cyan";
|
||||
cyan.textName = PDFTranslationContext::tr("Process Cyan");
|
||||
cyan.canBeActive = true;
|
||||
cyan.active = true;
|
||||
cyan.isSpot = false;
|
||||
cyan.spotColorIndex = 0;
|
||||
cyan.colorSpaceType = PDFAbstractColorSpace::ColorSpace::DeviceCMYK;
|
||||
result.emplace_back(qMove(cyan));
|
||||
|
||||
ColorInfo magenta;
|
||||
magenta.name = "Process Magenta";
|
||||
magenta.name = "Magenta";
|
||||
magenta.textName = PDFTranslationContext::tr("Process Magenta");
|
||||
magenta.canBeActive = true;
|
||||
magenta.active = true;
|
||||
magenta.isSpot = false;
|
||||
magenta.spotColorIndex = 1;
|
||||
magenta.colorSpaceType = PDFAbstractColorSpace::ColorSpace::DeviceCMYK;
|
||||
result.emplace_back(qMove(magenta));
|
||||
|
||||
ColorInfo yellow;
|
||||
yellow.name = "Process Yellow";
|
||||
yellow.name = "Yellow";
|
||||
yellow.textName = PDFTranslationContext::tr("Process Yellow");
|
||||
yellow.canBeActive = true;
|
||||
yellow.active = true;
|
||||
yellow.isSpot = false;
|
||||
yellow.spotColorIndex = 2;
|
||||
yellow.colorSpaceType = PDFAbstractColorSpace::ColorSpace::DeviceCMYK;
|
||||
result.emplace_back(qMove(yellow));
|
||||
|
||||
ColorInfo black;
|
||||
black.name = "Process Black";
|
||||
black.name = "Black";
|
||||
black.textName = PDFTranslationContext::tr("Process Black");
|
||||
black.canBeActive = true;
|
||||
black.active = true;
|
||||
black.isSpot = false;
|
||||
black.spotColorIndex = 3;
|
||||
black.colorSpaceType = PDFAbstractColorSpace::ColorSpace::DeviceCMYK;
|
||||
result.emplace_back(qMove(black));
|
||||
break;
|
||||
}
|
||||
@ -2668,11 +2750,14 @@ std::vector<PDFInkMapper::ColorInfo> PDFInkMapper::getSeparations(uint32_t proce
|
||||
generic.canBeActive = true;
|
||||
generic.active = true;
|
||||
generic.isSpot = false;
|
||||
generic.spotColorIndex = i;
|
||||
result.emplace_back(qMove(generic));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (withSpots)
|
||||
{
|
||||
for (const auto& spotColor : m_spotColors)
|
||||
{
|
||||
if (!spotColor.active)
|
||||
@ -2683,6 +2768,7 @@ std::vector<PDFInkMapper::ColorInfo> PDFInkMapper::getSeparations(uint32_t proce
|
||||
|
||||
result.emplace_back(spotColor);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -2806,6 +2892,28 @@ const PDFInkMapper::ColorInfo* PDFInkMapper::getSpotColor(const QByteArray& colo
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const PDFInkMapper::ColorInfo* PDFInkMapper::getProcessColor(const QByteArray& colorName) const
|
||||
{
|
||||
auto it = std::find_if(m_deviceColors.cbegin(), m_deviceColors.cend(), [&colorName](const auto& info) { return info.name == colorName; });
|
||||
if (it != m_spotColors.cend())
|
||||
{
|
||||
return &*it;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const PDFInkMapper::ColorInfo* PDFInkMapper::getActiveProcessColor(const QByteArray& colorName, PDFAbstractColorSpace::ColorSpace colorSpace) const
|
||||
{
|
||||
auto it = std::find_if(m_deviceColors.cbegin(), m_deviceColors.cend(), [&colorName, colorSpace](const auto& info) { return info.name == colorName && info.active && info.colorSpaceType == colorSpace; });
|
||||
if (it != m_deviceColors.cend())
|
||||
{
|
||||
return &*it;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const PDFInkMapper::ColorInfo* PDFInkMapper::getActiveSpotColor(size_t index) const
|
||||
{
|
||||
for (const ColorInfo& info : m_spotColors)
|
||||
@ -2854,6 +2962,7 @@ PDFInkMapping PDFInkMapper::createMapping(const PDFAbstractColorSpace* sourceCol
|
||||
{
|
||||
PDFInkMapping mapping;
|
||||
|
||||
const PDFAbstractColorSpace::ColorSpace colorSpaceType = targetColorSpace->getColorSpace();
|
||||
Q_ASSERT(targetColorSpace->getColorComponentCount() == targetPixelFormat.getProcessColorChannelCount());
|
||||
|
||||
if (sourceColorSpace->equals(targetColorSpace))
|
||||
@ -2890,10 +2999,23 @@ PDFInkMapping PDFInkMapper::createMapping(const PDFAbstractColorSpace* sourceCol
|
||||
else if (!separationColorSpace->isNone() && !separationColorSpace->getColorName().isEmpty())
|
||||
{
|
||||
const QByteArray& colorName = separationColorSpace->getColorName();
|
||||
const ColorInfo* info = getSpotColor(colorName);
|
||||
if (info && info->active && targetPixelFormat.hasSpotColors() && info->spotColorIndex < targetPixelFormat.getSpotColorChannelCount())
|
||||
|
||||
// First try to map it as process color, if we do not succeed, then map it as spot color
|
||||
const ColorInfo* processColor = getActiveProcessColor(colorName, colorSpaceType);
|
||||
if (processColor)
|
||||
{
|
||||
mapping.map(0, uint8_t(targetPixelFormat.getSpotColorChannelIndexStart() + info->spotColorIndex));
|
||||
if (targetPixelFormat.hasProcessColors() && processColor->spotColorIndex < targetPixelFormat.getProcessColorChannelCount())
|
||||
{
|
||||
mapping.map(0, uint8_t(targetPixelFormat.getProcessColorChannelIndexStart() + processColor->spotColorIndex));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const ColorInfo* spotColor = getSpotColor(colorName);
|
||||
if (spotColor && spotColor->active && targetPixelFormat.hasSpotColors() && spotColor->spotColorIndex < targetPixelFormat.getSpotColorChannelCount())
|
||||
{
|
||||
mapping.map(0, uint8_t(targetPixelFormat.getSpotColorChannelIndexStart() + spotColor->spotColorIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2910,6 +3032,18 @@ PDFInkMapping PDFInkMapper::createMapping(const PDFAbstractColorSpace* sourceCol
|
||||
for (size_t i = 0; i < colorants.size(); ++i)
|
||||
{
|
||||
const PDFDeviceNColorSpace::ColorantInfo& colorantInfo = colorants[i];
|
||||
|
||||
// First try to map it as process color, if we do not succeed, then map it as spot color
|
||||
const ColorInfo* processColor = getActiveProcessColor(colorantInfo.name, colorSpaceType);
|
||||
if (processColor)
|
||||
{
|
||||
if (targetPixelFormat.hasProcessColors() && processColor->spotColorIndex < targetPixelFormat.getProcessColorChannelCount())
|
||||
{
|
||||
mapping.map(0, uint8_t(targetPixelFormat.getProcessColorChannelIndexStart() + processColor->spotColorIndex));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const ColorInfo* info = getSpotColor(colorantInfo.name);
|
||||
|
||||
if (info && info->active && targetPixelFormat.hasSpotColors() && info->spotColorIndex < targetPixelFormat.getSpotColorChannelCount())
|
||||
@ -2918,6 +3052,7 @@ PDFInkMapping PDFInkMapper::createMapping(const PDFAbstractColorSpace* sourceCol
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -339,6 +339,7 @@ public:
|
||||
bool canBeActive = false; ///< Can spot color be activated?
|
||||
bool active = false; ///< Is spot color active?
|
||||
bool isSpot = true;
|
||||
PDFAbstractColorSpace::ColorSpace colorSpaceType = PDFAbstractColorSpace::ColorSpace::Invalid;
|
||||
};
|
||||
|
||||
static constexpr const uint32_t MAX_COLOR_COMPONENTS = PDF_MAX_COLOR_COMPONENTS;
|
||||
@ -349,7 +350,8 @@ public:
|
||||
/// and spot colors. Only active spot colors are added. Only 1, 3 and 4
|
||||
/// process colors are supported.
|
||||
/// \param processColorCount Process color count
|
||||
std::vector<ColorInfo> getSeparations(uint32_t processColorCount) const;
|
||||
/// \param withSpots Add active spot colors?
|
||||
std::vector<ColorInfo> getSeparations(uint32_t processColorCount, bool withSpots = true) const;
|
||||
|
||||
/// Scan document for spot colors and fills color info
|
||||
/// \param activate Set spot colors active?
|
||||
@ -366,6 +368,15 @@ public:
|
||||
/// \param colorName Color name
|
||||
const ColorInfo* getSpotColor(const QByteArray& colorName) const;
|
||||
|
||||
/// Returns process color information (or nullptr, if process color is not present)
|
||||
/// \param colorName Color name
|
||||
const ColorInfo* getProcessColor(const QByteArray& colorName) const;
|
||||
|
||||
/// Returns process color information (or nullptr, if process color is not present or is inactive)
|
||||
/// \param colorName Color name
|
||||
/// \param colorSpace Color space (actively used color space)
|
||||
const ColorInfo* getActiveProcessColor(const QByteArray& colorName, PDFAbstractColorSpace::ColorSpace colorSpace) const;
|
||||
|
||||
/// Returns active spot color with given index. If index
|
||||
/// of the spot color is invalid, or no active spot color
|
||||
/// is found, then nullptr is returned.
|
||||
@ -390,6 +401,7 @@ public:
|
||||
private:
|
||||
const PDFDocument* m_document;
|
||||
std::vector<ColorInfo> m_spotColors;
|
||||
std::vector<ColorInfo> m_deviceColors; ///< Device color space separations
|
||||
size_t m_activeSpotColors = 0;
|
||||
};
|
||||
|
||||
@ -666,6 +678,12 @@ private:
|
||||
PDFMappedColor createMappedColor(const PDFColor& sourceColor,
|
||||
const PDFAbstractColorSpace* sourceColorSpace);
|
||||
|
||||
/// Converts image in some other color space to the blend color space,
|
||||
/// so pixel format is equal to the draw buffer's pixel format and active
|
||||
/// colors are set.
|
||||
/// \param image Image
|
||||
PDFFloatBitmapWithColorSpace convertImageToBlendSpace(const PDFFloatBitmapWithColorSpace& image);
|
||||
|
||||
/// Converts RGB bitmap to the image.
|
||||
QImage toImageImpl(const PDFFloatBitmapWithColorSpace& floatImage, bool use16Bit) const;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user