mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2024-12-28 01:00:40 +01:00
Spot color conversion
This commit is contained in:
parent
e63d5aa242
commit
6844114397
@ -120,7 +120,7 @@ size_t PDFFloatBitmap::getPixelIndex(size_t x, size_t y) const
|
||||
return (y * m_width + x) * m_pixelSize;
|
||||
}
|
||||
|
||||
PDFFloatBitmap PDFFloatBitmap::extractProcessColors()
|
||||
PDFFloatBitmap PDFFloatBitmap::extractProcessColors() const
|
||||
{
|
||||
PDFPixelFormat format = PDFPixelFormat::createFormat(m_format.getProcessColorChannelCount(), 0, false, m_format.hasProcessColorsSubtractive());
|
||||
PDFFloatBitmap result(getWidth(), getHeight(), format);
|
||||
@ -129,7 +129,7 @@ PDFFloatBitmap PDFFloatBitmap::extractProcessColors()
|
||||
{
|
||||
for (size_t y = 0; y < getHeight(); ++y)
|
||||
{
|
||||
PDFColorBuffer sourceProcessColorBuffer = getPixel(x, y);
|
||||
PDFConstColorBuffer sourceProcessColorBuffer = getPixel(x, y);
|
||||
PDFColorBuffer targetProcessColorBuffer = result.getPixel(x, y);
|
||||
|
||||
Q_ASSERT(sourceProcessColorBuffer.size() >= targetProcessColorBuffer.size());
|
||||
@ -140,6 +140,29 @@ PDFFloatBitmap PDFFloatBitmap::extractProcessColors()
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFFloatBitmap PDFFloatBitmap::extractSpotChannel(uint8_t channel) const
|
||||
{
|
||||
PDFPixelFormat format = PDFPixelFormat::createFormat(0, 1, false, m_format.hasProcessColorsSubtractive());
|
||||
PDFFloatBitmap result(getWidth(), getHeight(), format);
|
||||
|
||||
Q_ASSERT(m_format.hasSpotColors());
|
||||
Q_ASSERT(m_format.getSpotColorChannelIndexStart() <= channel);
|
||||
Q_ASSERT(m_format.getSpotColorChannelIndexEnd() > channel);
|
||||
|
||||
for (size_t x = 0; x < getWidth(); ++x)
|
||||
{
|
||||
for (size_t y = 0; y < getHeight(); ++y)
|
||||
{
|
||||
PDFConstColorBuffer sourceProcessColorBuffer = getPixel(x, y);
|
||||
PDFColorBuffer targetProcessColorBuffer = result.getPixel(x, y);
|
||||
|
||||
targetProcessColorBuffer[0] = sourceProcessColorBuffer[channel];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PDFFloatBitmap::blend(const PDFFloatBitmap& source,
|
||||
PDFFloatBitmap& target,
|
||||
const PDFFloatBitmap& backdrop,
|
||||
@ -455,6 +478,30 @@ void PDFFloatBitmap::blend(const PDFFloatBitmap& source,
|
||||
}
|
||||
}
|
||||
|
||||
void PDFFloatBitmap::blendConvertedSpots(const PDFFloatBitmap& convertedSpotColors)
|
||||
{
|
||||
Q_ASSERT(convertedSpotColors.getPixelFormat().getProcessColorChannelCount() == m_format.getProcessColorChannelCount());
|
||||
|
||||
const uint8_t processColorChannelStart = m_format.getProcessColorChannelIndexStart();
|
||||
const uint8_t processColorChannelEnd = m_format.getProcessColorChannelIndexEnd();
|
||||
|
||||
const PDFColorComponent* sourcePixel = convertedSpotColors.begin();
|
||||
for (PDFColorComponent* targetPixel = begin(); targetPixel != end(); targetPixel += m_pixelSize, sourcePixel+= convertedSpotColors.getPixelSize())
|
||||
{
|
||||
for (uint8_t i = processColorChannelStart; i < processColorChannelEnd; ++i)
|
||||
{
|
||||
if (m_format.hasProcessColorsSubtractive())
|
||||
{
|
||||
targetPixel[i] = PDFBlendFunction::blend_Union(targetPixel[i], sourcePixel[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPixel[i] = targetPixel[i] * sourcePixel[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PDFFloatBitmap::fillProcessColorChannels(PDFColorComponent value)
|
||||
{
|
||||
if (!m_format.hasProcessColors())
|
||||
@ -644,6 +691,7 @@ void PDFTransparencyRenderer::beginPaint(QSize pixelSize)
|
||||
m_transparencyGroupDataStack.back().filterColorsUsingMask = (m_settings.flags.testFlag(PDFTransparencyRendererSettings::ActiveColorMask) &&
|
||||
m_settings.activeColorMask != PDFPixelFormat::getAllColorsMask());
|
||||
m_transparencyGroupDataStack.back().activeColorMask = m_settings.activeColorMask;
|
||||
m_transparencyGroupDataStack.back().transformSpotsToDevice = m_settings.flags.testFlag(PDFTransparencyRendererSettings::SeparationSimulation);
|
||||
}
|
||||
|
||||
const PDFFloatBitmap& PDFTransparencyRenderer::endPaint()
|
||||
@ -790,6 +838,48 @@ void PDFTransparencyRenderer::performPixelSampling(const PDFReal shape,
|
||||
}
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::collapseSpotColorsToDeviceColors(PDFFloatBitmapWithColorSpace& bitmap)
|
||||
{
|
||||
PDFPixelFormat pixelFormat = bitmap.getPixelFormat();
|
||||
|
||||
if (!pixelFormat.hasSpotColors())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t spotColorIndexStart = pixelFormat.getSpotColorChannelIndexStart();
|
||||
const uint8_t spotColorIndexEnd = pixelFormat.getSpotColorChannelIndexEnd();
|
||||
|
||||
for (uint8_t i = spotColorIndexStart; i < spotColorIndexEnd; ++i)
|
||||
{
|
||||
// Collapse spot color
|
||||
PDFFloatBitmap spotColorBitmap = bitmap.extractSpotChannel(i);
|
||||
|
||||
const PDFInkMapper::ColorInfo* spotColor = m_inkMapper->getActiveSpotColor(i - spotColorIndexStart);
|
||||
Q_ASSERT(spotColor);
|
||||
|
||||
switch (spotColor->colorSpace->getColorSpace())
|
||||
{
|
||||
case PDFAbstractColorSpace::ColorSpace::Separation:
|
||||
{
|
||||
PDFFloatBitmap processColorBitmap(spotColorBitmap.getWidth(), spotColorBitmap.getHeight(), PDFPixelFormat::createFormat(pixelFormat.getProcessColorChannelCount(), 0, false, pixelFormat.hasProcessColorsSubtractive()));
|
||||
if (!PDFAbstractColorSpace::transform(spotColor->colorSpace.data(), bitmap.getColorSpace().data(), getCMS(), getGraphicState()->getRenderingIntent(), spotColorBitmap.getPixels(), processColorBitmap.getPixels(), this))
|
||||
{
|
||||
reportRenderError(RenderErrorType::Error, PDFTranslationContext::tr("Transformation of spot color to blend color space failed."));
|
||||
}
|
||||
|
||||
bitmap.blendConvertedSpots(processColorBitmap);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reportRenderError(RenderErrorType::Error, PDFTranslationContext::tr("Transformation of spot color to blend color space failed."));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule)
|
||||
{
|
||||
Q_UNUSED(fillRule);
|
||||
@ -1118,6 +1208,12 @@ void PDFTransparencyRenderer::performEndTransparencyGroup(ProcessOrder order, co
|
||||
}
|
||||
}
|
||||
|
||||
// Collapse spot colors
|
||||
if (sourceData.transformSpotsToDevice)
|
||||
{
|
||||
collapseSpotColorsToDeviceColors(sourceData.immediateBackdrop);
|
||||
}
|
||||
|
||||
PDFTransparencyGroupPainterData& targetData = m_transparencyGroupDataStack.back();
|
||||
sourceData.immediateBackdrop.convertToColorSpace(getCMS(), targetData.renderingIntent, targetData.blendColorSpace, this);
|
||||
|
||||
@ -1685,6 +1781,24 @@ const PDFInkMapper::ColorInfo* PDFInkMapper::getSpotColor(const QByteArray& colo
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const PDFInkMapper::ColorInfo* PDFInkMapper::getActiveSpotColor(size_t index) const
|
||||
{
|
||||
for (const ColorInfo& info : m_spotColors)
|
||||
{
|
||||
if (info.active)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
return &info;
|
||||
}
|
||||
|
||||
--index;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PDFInkMapper::setSpotColorsActive(bool active)
|
||||
{
|
||||
m_activeSpotColors = 0;
|
||||
|
@ -177,7 +177,11 @@ public:
|
||||
size_t getPixelIndex(size_t x, size_t y) const;
|
||||
|
||||
/// Extract process colors into another bitmap
|
||||
PDFFloatBitmap extractProcessColors();
|
||||
PDFFloatBitmap extractProcessColors() const;
|
||||
|
||||
/// Extract spot channel
|
||||
/// \param channel Channel
|
||||
PDFFloatBitmap extractSpotChannel(uint8_t channel) const;
|
||||
|
||||
enum class OverprintMode
|
||||
{
|
||||
@ -216,6 +220,11 @@ public:
|
||||
OverprintMode overprintMode,
|
||||
QRect blendRegion);
|
||||
|
||||
/// Blends converted spot colors, which are in \p convertedSpotColors bitmap.
|
||||
/// Process colors must match.
|
||||
/// \param convertedSpotColors Bitmap with converted spot colors
|
||||
void blendConvertedSpots(const PDFFloatBitmap& convertedSpotColors);
|
||||
|
||||
void fillProcessColorChannels(PDFColorComponent value);
|
||||
void fillChannel(size_t channel, PDFColorComponent value);
|
||||
|
||||
@ -316,6 +325,12 @@ public:
|
||||
/// \param colorName Color name
|
||||
const ColorInfo* getSpotColor(const QByteArray& colorName) 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.
|
||||
/// \param index Active color index
|
||||
const ColorInfo* getActiveSpotColor(size_t index) const;
|
||||
|
||||
/// Activates / deactivates spot colors
|
||||
/// \param active Make spot colors active?
|
||||
void setSpotColorsActive(bool active);
|
||||
@ -577,6 +592,7 @@ private:
|
||||
PDFColorSpacePointer blendColorSpace;
|
||||
bool filterColorsUsingMask = false;
|
||||
uint32_t activeColorMask = PDFPixelFormat::getAllColorsMask();
|
||||
bool transformSpotsToDevice = false;
|
||||
};
|
||||
|
||||
struct PDFTransparencyPainterState
|
||||
@ -666,6 +682,10 @@ private:
|
||||
const PDFPainterPathSampler& clipSampler,
|
||||
const PDFPainterPathSampler& pathSampler);
|
||||
|
||||
/// Collapses spot colors to device colors
|
||||
/// \param data Bitmap with data
|
||||
void collapseSpotColorsToDeviceColors(PDFFloatBitmapWithColorSpace& bitmap);
|
||||
|
||||
PDFColorSpacePointer m_deviceColorSpace; ///< Device color space (color space for final result)
|
||||
PDFColorSpacePointer m_processColorSpace; ///< Process color space (color space, in which is page graphic's blended)
|
||||
std::unique_ptr<PDFTransparencyGroupGuard> m_pageTransparencyGroupGuard;
|
||||
|
@ -272,6 +272,7 @@ OutputPreviewDialog::RenderedImage OutputPreviewDialog::renderPage(const pdf::PD
|
||||
#endif
|
||||
|
||||
settings.flags.setFlag(pdf::PDFTransparencyRendererSettings::ActiveColorMask, activeColorMask != pdf::PDFPixelFormat::getAllColorsMask());
|
||||
settings.flags.setFlag(pdf::PDFTransparencyRendererSettings::SeparationSimulation, m_inkMapperForRendering.getActiveSpotColorCount() > 0);
|
||||
settings.activeColorMask = activeColorMask;
|
||||
|
||||
QMatrix pagePointToDevicePoint = pdf::PDFRenderer::createPagePointToDevicePointMatrix(page, QRect(QPoint(0, 0), imageSize));
|
||||
|
Loading…
Reference in New Issue
Block a user