Commit 75abc683 authored by Philipp Knechtges's avatar Philipp Knechtges Committed by Albert Astals Cid
Browse files

PSOutputDev: use the DeviceN8 bitmap for rasterization with CMYK-output + overprint

This mostly mimics the pdftoppm behaviour.
parent 0c772071
......@@ -3141,6 +3141,7 @@ bool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/, i
unsigned char digit;
bool isOptimizedGray;
bool overprint;
SplashColorMode internalColorFormat;
#endif
if (!postInitDone) {
......@@ -3176,13 +3177,25 @@ bool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/, i
startPage(page->getNum(), state, xref);
delete state;
// If we would not rasterize this page, we would emit the overprint code anyway for language level 2 and upwards.
// As such it is safe to assume for a CMYK printer that it would respect the overprint operands.
overprint = globalParams->getOverprintPreview() || (processColorFormat == splashModeCMYK8 && level >= psLevel2);
// set up the SplashOutputDev
internalColorFormat = processColorFormat;
if (processColorFormat == splashModeMono8) {
numComps = 1;
paperColor[0] = 0xff;
} else if (processColorFormat == splashModeCMYK8) {
numComps = 4;
paperColor[0] = paperColor[1] = paperColor[2] = paperColor[3] = 0;
// If overprinting is emulated, it is not sufficient to just store the CMYK values in a bitmap.
// All separation channels need to be stored and collapsed at the end.
// Cf. PDF32000_2008 Section 11.7.4.5 and Tables 148, 149
if (overprint) {
internalColorFormat = splashModeDeviceN8;
}
} else if (processColorFormat == splashModeRGB8) {
numComps = 3;
paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
......@@ -3192,10 +3205,7 @@ bool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/, i
numComps = 3;
paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
}
// If we would not rasterize this page, we would emit the overprint code anyway for language level 2 and upwards.
// As such it is safe to assume for a CMYK printer that it would respect the overprint operands.
overprint = globalParams->getOverprintPreview() || (processColorFormat == splashModeCMYK8 && level >= psLevel2);
splashOut = new SplashOutputDev(processColorFormat, 1, false, paperColor, false, splashThinLineDefault, overprint);
splashOut = new SplashOutputDev(internalColorFormat, 1, false, paperColor, false, splashThinLineDefault, overprint);
splashOut->setFontAntialias(rasterAntialias);
splashOut->setVectorAntialias(rasterAntialias);
# ifdef USE_CMS
......@@ -3440,7 +3450,11 @@ bool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/, i
case psLevel3:
case psLevel3Sep:
p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
str0 = new MemStream((char *)p, 0, w * h * numComps, Object(objNull));
if (processColorFormat == splashModeCMYK8 && internalColorFormat != splashModeCMYK8) {
str0 = new SplashBitmapCMYKEncoder(bitmap);
} else {
str0 = new MemStream((char *)p, 0, w * h * numComps, Object(objNull));
}
// Check for a color image that uses only gray
if (!getOptimizeColorSpace()) {
isOptimizedGray = false;
......
......@@ -68,6 +68,10 @@
#include "Stream-CCITT.h"
#include "CachedFile.h"
#ifdef HAVE_SPLASH
# include "splash/SplashBitmap.h"
#endif
#ifdef ENABLE_LIBJPEG
# include "DCTStream.h"
#endif
......@@ -5137,3 +5141,81 @@ bool RGBGrayEncoder::fillBuf()
*bufEnd++ = (char)i;
return true;
}
//------------------------------------------------------------------------
// SplashBitmapCMYKEncoder
//------------------------------------------------------------------------
#ifdef HAVE_SPLASH
SplashBitmapCMYKEncoder::SplashBitmapCMYKEncoder(SplashBitmap *bitmapA) : bitmap(bitmapA)
{
width = (size_t)4 * bitmap->getWidth();
height = bitmap->getHeight();
buf.resize(width);
bufPtr = width;
curLine = height - 1;
}
SplashBitmapCMYKEncoder::~SplashBitmapCMYKEncoder() { }
void SplashBitmapCMYKEncoder::reset()
{
bufPtr = width;
curLine = height - 1;
}
int SplashBitmapCMYKEncoder::lookChar()
{
if (bufPtr >= width && !fillBuf()) {
return EOF;
}
return buf[bufPtr];
}
int SplashBitmapCMYKEncoder::getChar()
{
int ret = lookChar();
bufPtr++;
return ret;
}
bool SplashBitmapCMYKEncoder::fillBuf()
{
if (curLine < 0) {
return false;
}
if (bufPtr < width) {
return true;
}
bitmap->getCMYKLine(curLine, &buf[0]);
bufPtr = 0;
curLine--;
return true;
}
Goffset SplashBitmapCMYKEncoder::getPos()
{
return (height - 1 - curLine) * width + bufPtr;
}
void SplashBitmapCMYKEncoder::setPos(Goffset pos, int dir)
{
// This code is mostly untested!
if (dir < 0) {
curLine = pos / width;
} else {
curLine = height - 1 - pos / width;
}
bufPtr = width;
fillBuf();
if (dir < 0) {
bufPtr = width - 1 - pos % width;
} else {
bufPtr = pos % width;
}
}
#endif
......@@ -47,6 +47,9 @@
class GooFile;
class BaseStream;
class CachedFile;
#ifdef HAVE_SPLASH
class SplashBitmap;
#endif
//------------------------------------------------------------------------
......@@ -1428,4 +1431,53 @@ private:
bool fillBuf();
};
//------------------------------------------------------------------------
// SplashBitmapCMYKEncoder
//
// This stream helps to condense SplashBitmaps (mostly of DeviceN8 type) into
// pure CMYK colors. In particular for a DeviceN8 bitmap it redacts the spot colorants.
//------------------------------------------------------------------------
#ifdef HAVE_SPLASH
class SplashBitmapCMYKEncoder : public Stream
{
public:
SplashBitmapCMYKEncoder(SplashBitmap *bitmapA);
~SplashBitmapCMYKEncoder() override;
StreamKind getKind() const override { return strWeird; }
void reset() override;
int getChar() override;
int lookChar() override;
GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) override { return nullptr; }
bool isBinary(bool /*last = true*/) override { return true; }
// Although we are an encoder, we return false here, since we do not want do be auto-deleted by
// successive streams.
bool isEncoder() override { return false; }
int getUnfilteredChar() override { return getChar(); }
void unfilteredReset() override { reset(); }
BaseStream *getBaseStream() override { return nullptr; }
Stream *getUndecodedStream() override { return this; }
Dict *getDict() override { return nullptr; }
Object *getDictObject() override { return nullptr; }
Goffset getPos() override;
void setPos(Goffset pos, int dir = 0) override;
private:
SplashBitmap *bitmap;
size_t width;
int height;
std::vector<unsigned char> buf;
size_t bufPtr;
int curLine;
bool fillBuf();
};
#endif
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment