Commit 2e77799a authored by Thomas Freitag's avatar Thomas Freitag Committed by Albert Astals Cid

Splash: Implement DeviceN support

Bug #53140

Some copying from the bug tracker

 To explain
it a little bit more I copy a few lines from "Patch 8.01 — DeviceN Support (6
colors)" of the Ghent PDF workgroup:
"This patch tests the DeviceN capabilities of a workflow. If DeviceN is not
handled correctly the colors are converted to CMYK. Instead of the check marks
an X will appear in the lower left corner of each image and in the gradient.
In addition you could inspect the color separations. The objects should appear
only in the Black, Pantone 265C and GWG Green separations as indicated in the
captions."
Without the patch all DeviceN colors are immediately converted to CMYK (with
SPLASH_CMYK). This leads especially to problems, if overprint is used: in
overprint mode a CMYK color will knockout the underlying CMYK components, BUT
neither any spot colors. But if underlying spot colors are immediately
converted to CMYK colors, they will be kocked out then, too!
The patch now spends up to four (or up to SPOT_NCOMPS) additional spot colors
in the splash bitmap, so the order in the bitmap will be
CMYKSTUVCMYKSTUVCMYKSTUV... where S, T, U, V are spot colors (I would use
S1,S2, S3, S4 if it's possible to use indexes), and all painting operations are
done now in this new device. Only at the end, when we want to store the bitmap
in a CMYK or RGB color, the spot colors are converted and their alternate CMYK
components are added to the normal CMYK components.
According to the PDF spec are PDF writer should use different spot color names
if they have a different appearance in their alternate CMYK colorspace.
"hasDifferntResultSet" (sorry for the typo) proofs that: if the same spot color
name is reused BUT has a different appearance in the alternate colorspace, it
will be converted immediately to its alternate colorspace.
"createMapping" is used so that getDeviceN (color) returns the components in
the correct order according their appearance in the splash bitmap, i.e. the
fourth detected spot color must be placed in index 7 of the color array.
updateFill- and updateStrokeColorspace are needed to create this mapping at the
appropriate place. And they are not called once but everytime the colorspace
changed in the PDF (but of course only once in Gfx).
The GooList *getSeparationList() is used to store the functions for converting
the spot colors to their alternate colorspace in order of their appearance in
the splash bitmap. The functions are needed to compare if a spot color with the
same name has really the same appearance and at the end when the splash bitmap
has to be converted to a CMYK or RGB bitmap (s. ahead).
deviceNTransfer is needed simular to rgbTransferX or cmykTransferX if a
transfer function is specified in the ExtGState and splash uses the DeviceN8.
"Do we really need splashModeDeviceN8?": Do we really need splashModeXBGR8? But
kidding aside: splashModeDeviceN8 needs four more components than
splashModeCMYK8, so the bitmap size in memory doubles the size of a pure CMYK
bitmap, and it is only needed if the PDF uses spot colors. So I think it's a
good idea to spend an additional mode and let it up to the calling application
and the cirumstances if it wants to use this new mode or not.
parent cb2ed646
......@@ -510,6 +510,20 @@ void SampledFunction::transform(double *in, double *out) {
}
}
GBool SampledFunction::hasDifferentResultSet(Function *func) {
if (func->getType() == 0) {
SampledFunction *compTo = (SampledFunction *) func;
if (compTo->getSampleNumber() != nSamples)
return gTrue;
double *compSamples = compTo->getSamples();
for (int i = 0; i < nSamples; i++) {
if (samples[i] != compSamples[i])
return gTrue;
}
}
return gFalse;
}
//------------------------------------------------------------------------
// ExponentialFunction
//------------------------------------------------------------------------
......
......@@ -16,6 +16,7 @@
// Copyright (C) 2009, 2010 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
// Copyright (C) 2011 Andrea Canciani <ranma42@gmail.com>
// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -79,6 +80,7 @@ public:
double getRangeMin(int i) { return range[i][0]; }
double getRangeMax(int i) { return range[i][1]; }
GBool getHasRange() { return hasRange; }
virtual GBool hasDifferentResultSet(Function *func) { return gFalse; }
// Transform an input tuple into an output tuple.
virtual void transform(double *in, double *out) = 0;
......@@ -126,6 +128,7 @@ public:
virtual int getType() { return 0; }
virtual void transform(double *in, double *out);
virtual GBool isOk() { return ok; }
virtual GBool hasDifferentResultSet(Function *func);
int getSampleSize(int i) { return sampleSize[i]; }
double getEncodeMin(int i) { return encode[i][0]; }
......@@ -133,6 +136,7 @@ public:
double getDecodeMin(int i) { return decode[i][0]; }
double getDecodeMax(int i) { return decode[i][1]; }
double *getSamples() { return samples; }
int getSampleNumber() { return nSamples; }
private:
......
This diff is collapsed.
......@@ -20,7 +20,7 @@
// Copyright (C) 2009-2011 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
// Copyright (C) 2011 Andrea Canciani <ranma42@gmail.com>
// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2011, 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -48,6 +48,7 @@ class GfxFont;
class PDFRectangle;
class GfxShading;
class PopplerCache;
class GooList;
class Matrix {
public:
......@@ -202,11 +203,15 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray) = 0;
virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0;
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0;
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN) = 0;
virtual void getGrayLine(Guchar * /*in*/, Guchar * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getGrayLine this should not happen"); }
virtual void getRGBLine(Guchar * /*in*/, unsigned int * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getRGBLine (first variant) this should not happen"); }
virtual void getRGBLine(Guchar * /*in*/, Guchar * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getRGBLine (second variant) this should not happen"); }
virtual void getRGBXLine(Guchar * /*in*/, Guchar * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getRGBXLine this should not happen"); }
// create mapping for spot colorants
virtual void createMapping(GooList *separationList, int maxSepComps);
// Does this ColorSpace support getRGBLine?
virtual GBool useGetRGBLine() { return gFalse; }
// Does this ColorSpace support getGrayLine?
......@@ -249,6 +254,7 @@ public:
protected:
Guint overprintMask;
int *mapping;
};
//------------------------------------------------------------------------
......@@ -266,6 +272,7 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual void getGrayLine(Guchar *in, Guchar *out, int length);
virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
virtual void getRGBLine(Guchar *in, Guchar *out, int length);
......@@ -298,6 +305,7 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual int getNComps() { return 1; }
virtual void getDefaultColor(GfxColor *color);
......@@ -335,6 +343,7 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual void getGrayLine(Guchar *in, Guchar *out, int length);
virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
virtual void getRGBLine(Guchar *in, Guchar *out, int length);
......@@ -367,6 +376,7 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual int getNComps() { return 3; }
virtual void getDefaultColor(GfxColor *color);
......@@ -408,6 +418,7 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
virtual void getRGBLine(Guchar *, Guchar *out, int length);
virtual void getRGBXLine(Guchar *in, Guchar *out, int length);
......@@ -437,6 +448,7 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual int getNComps() { return 3; }
virtual void getDefaultColor(GfxColor *color);
......@@ -484,6 +496,7 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
virtual void getRGBLine(Guchar *in, Guchar *out, int length);
virtual void getRGBXLine(Guchar *in, Guchar *out, int length);
......@@ -529,6 +542,7 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
virtual void getRGBLine(Guchar *in, Guchar *out, int length);
virtual void getRGBXLine(Guchar *in, Guchar *out, int length);
......@@ -546,6 +560,10 @@ public:
int getIndexHigh() { return indexHigh; }
Guchar *getLookup() { return lookup; }
GfxColor *mapColorToBase(GfxColor *color, GfxColor *baseColor);
Guint getOverprintMask() { return base->getOverprintMask(); }
virtual void createMapping(GooList *separationList, int maxSepComps)
{ base->createMapping(separationList, maxSepComps); }
private:
......@@ -573,6 +591,9 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual void createMapping(GooList *separationList, int maxSepComps);
virtual int getNComps() { return 1; }
virtual void getDefaultColor(GfxColor *color);
......@@ -588,7 +609,7 @@ private:
GfxSeparationColorSpace(GooString *nameA, GfxColorSpace *altA,
Function *funcA, GBool nonMarkingA,
Guint overprintMaskA);
Guint overprintMaskA, int *mappingA);
GooString *name; // colorant name
GfxColorSpace *alt; // alternate color space
......@@ -604,7 +625,7 @@ class GfxDeviceNColorSpace: public GfxColorSpace {
public:
GfxDeviceNColorSpace(int nCompsA, GooString **namesA,
GfxColorSpace *alt, Function *func);
GfxColorSpace *alt, Function *func, GooList *sepsCS);
virtual ~GfxDeviceNColorSpace();
virtual GfxColorSpace *copy();
virtual GfxColorSpaceMode getMode() { return csDeviceN; }
......@@ -615,6 +636,9 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual void createMapping(GooList *separationList, int maxSepComps);
virtual int getNComps() { return nComps; }
virtual void getDefaultColor(GfxColor *color);
......@@ -629,8 +653,8 @@ public:
private:
GfxDeviceNColorSpace(int nCompsA, GooString **namesA,
GfxColorSpace *alt, Function *func,
GBool nonMarkingA, Guint overprintMaskA);
GfxColorSpace *alt, Function *func, GooList *sepsCSA,
int *mappingA, GBool nonMarkingA, Guint overprintMaskA);
int nComps; // number of components
GooString // colorant names
......@@ -638,6 +662,7 @@ private:
GfxColorSpace *alt; // alternate color space
Function *func; // tint transform (into alternate color space)
GBool nonMarking;
GooList *sepsCS; // list of separation cs for spot colorants;
};
//------------------------------------------------------------------------
......@@ -658,6 +683,7 @@ public:
virtual void getGray(GfxColor *color, GfxGray *gray);
virtual void getRGB(GfxColor *color, GfxRGB *rgb);
virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
virtual void getDeviceN(GfxColor *color, GfxColor *deviceN);
virtual int getNComps() { return 0; }
virtual void getDefaultColor(GfxColor *color);
......@@ -1107,6 +1133,7 @@ public:
void getRGBXLine(Guchar *in, Guchar *out, int length);
void getGrayLine(Guchar *in, Guchar *out, int length);
void getCMYK(Guchar *x, GfxCMYK *cmyk);
void getDeviceN(Guchar *x, GfxColor *deviceN);
void getColor(Guchar *x, GfxColor *color);
private:
......@@ -1342,8 +1369,12 @@ public:
{ strokeColorSpace->getRGB(&strokeColor, rgb); }
void getFillCMYK(GfxCMYK *cmyk)
{ fillColorSpace->getCMYK(&fillColor, cmyk); }
void getFillDeviceN(GfxColor *deviceN)
{ fillColorSpace->getDeviceN(&fillColor, deviceN); }
void getStrokeCMYK(GfxCMYK *cmyk)
{ strokeColorSpace->getCMYK(&strokeColor, cmyk); }
void getStrokeDeviceN(GfxColor *deviceN)
{ strokeColorSpace->getDeviceN(&strokeColor, deviceN); }
GfxColorSpace *getFillColorSpace() { return fillColorSpace; }
GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; }
GfxPattern *getFillPattern() { return fillPattern; }
......
This diff is collapsed.
......@@ -215,6 +215,8 @@ public:
virtual void updateMiterLimit(GfxState *state);
virtual void updateLineWidth(GfxState *state);
virtual void updateStrokeAdjust(GfxState *state);
virtual void updateFillColorSpace(GfxState *state);
virtual void updateStrokeColorSpace(GfxState *state);
virtual void updateFillColor(GfxState *state);
virtual void updateStrokeColor(GfxState *state);
virtual void updateBlendMode(GfxState *state);
......@@ -362,6 +364,7 @@ private:
SplashPattern *getColor(GfxRGB *rgb);
#if SPLASH_CMYK
SplashPattern *getColor(GfxCMYK *cmyk);
SplashPattern *getColor(GfxColor *deviceN);
#endif
void setOverprintMask(GfxColorSpace *colorSpace, GBool overprintFlag,
int overprintMode, GfxColor *singleColor, GBool grayIndexed = gFalse);
......
This diff is collapsed.
......@@ -60,6 +60,7 @@ typedef GBool (*SplashImageSource)(void *data, SplashColorPtr colorLine,
enum SplashPipeResultColorCtrl {
#if SPLASH_CMYK
splashPipeResultColorNoAlphaBlendCMYK,
splashPipeResultColorNoAlphaBlendDeviceN,
#endif
splashPipeResultColorNoAlphaBlendRGB,
splashPipeResultColorNoAlphaBlendMono,
......@@ -67,12 +68,14 @@ enum SplashPipeResultColorCtrl {
splashPipeResultColorAlphaNoBlendRGB,
#if SPLASH_CMYK
splashPipeResultColorAlphaNoBlendCMYK,
splashPipeResultColorAlphaNoBlendDeviceN,
#endif
splashPipeResultColorAlphaBlendMono,
splashPipeResultColorAlphaBlendRGB
#if SPLASH_CMYK
,
splashPipeResultColorAlphaBlendCMYK
splashPipeResultColorAlphaBlendCMYK,
splashPipeResultColorAlphaBlendDeviceN
#endif
};
......@@ -285,6 +288,7 @@ private:
void pipeRunSimpleBGR8(SplashPipe *pipe);
#if SPLASH_CMYK
void pipeRunSimpleCMYK8(SplashPipe *pipe);
void pipeRunSimpleDeviceN8(SplashPipe *pipe);
#endif
void pipeRunAAMono1(SplashPipe *pipe);
void pipeRunAAMono8(SplashPipe *pipe);
......@@ -293,6 +297,7 @@ private:
void pipeRunAABGR8(SplashPipe *pipe);
#if SPLASH_CMYK
void pipeRunAACMYK8(SplashPipe *pipe);
void pipeRunAADeviceN8(SplashPipe *pipe);
#endif
void pipeSetXY(SplashPipe *pipe, int x, int y);
void pipeIncX(SplashPipe *pipe);
......
......@@ -45,6 +45,7 @@
#include "goo/PNGWriter.h"
#include "goo/TiffWriter.h"
#include "goo/ImgWriter.h"
#include "goo/GooList.h"
//------------------------------------------------------------------------
// SplashBitmap
......@@ -52,7 +53,7 @@
SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPadA,
SplashColorMode modeA, GBool alphaA,
GBool topDown) {
GBool topDown, GooList *separationListA) {
width = widthA;
height = heightA;
mode = modeA;
......@@ -95,6 +96,13 @@ SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPadA,
rowSize = -1;
}
break;
case splashModeDeviceN8:
if (width > 0 && width <= INT_MAX / 4) {
rowSize = width * (SPOT_NCOMPS + 4);
} else {
rowSize = -1;
}
break;
#endif
}
if (rowSize > 0) {
......@@ -115,11 +123,15 @@ SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPadA,
} else {
alpha = NULL;
}
separationList = new GooList();
if (separationListA != NULL)
for (int i = 0; i < separationListA->getLength(); i++)
separationList->append(((GfxSeparationColorSpace *) separationListA->get(i))->copy());
}
SplashBitmap *SplashBitmap::copy(SplashBitmap *src) {
SplashBitmap *result = new SplashBitmap(src->getWidth(), src->getHeight(), src->getRowPad(),
src->getMode(), src->getAlphaPtr() != NULL, src->getRowSize() >= 0);
src->getMode(), src->getAlphaPtr() != NULL, src->getRowSize() >= 0, src->getSeparationList());
Guchar *dataSource = src->getDataPtr();
Guchar *dataDest = result->getDataPtr();
int amount = src->getRowSize();
......@@ -146,6 +158,7 @@ SplashBitmap::~SplashBitmap() {
}
}
gfree(alpha);
deleteGooList(separationList, GfxSeparationColorSpace);
}
......@@ -234,6 +247,7 @@ SplashError SplashBitmap::writePNMFile(FILE *f) {
#if SPLASH_CMYK
case splashModeCMYK8:
case splashModeDeviceN8:
// PNM doesn't support CMYK
error(errInternal, -1, "unsupported SplashBitmap mode");
return splashErrGeneric;
......@@ -300,6 +314,11 @@ void SplashBitmap::getPixel(int x, int y, SplashColorPtr pixel) {
pixel[2] = p[2];
pixel[3] = p[3];
break;
case splashModeDeviceN8:
p = &data[y * rowSize + (SPOT_NCOMPS + 4) * x];
for (int cp = 0; cp < SPOT_NCOMPS + 4; cp++)
pixel[cp] = p[cp];
break;
#endif
}
}
......@@ -386,6 +405,31 @@ void SplashBitmap::getRGBLine(int yl, SplashColorPtr line) {
m = byteToDbl(col[1]);
y = byteToDbl(col[2]);
k = byteToDbl(col[3]);
#if SPLASH_CMYK
if (separationList->getLength() > 0) {
for (int i = 0; i < separationList->getLength(); i++) {
if (col[i+4] > 0) {
GfxCMYK cmyk;
GfxColor input;
input.c[0] = byteToCol(col[i+4]);
GfxSeparationColorSpace *sepCS = (GfxSeparationColorSpace *)separationList->get(i);
sepCS->getCMYK(&input, &cmyk);
col[0] = colToByte(cmyk.c);
col[1] = colToByte(cmyk.m);
col[2] = colToByte(cmyk.y);
col[3] = colToByte(cmyk.k);
c += byteToDbl(col[0]);
m += byteToDbl(col[1]);
y += byteToDbl(col[2]);
k += byteToDbl(col[3]);
}
}
if (c > 1) c = 1;
if (m > 1) m = 1;
if (y > 1) y = 1;
if (k > 1) k = 1;
}
#endif
c1 = 1 - c;
m1 = 1 - m;
y1 = 1 - y;
......@@ -397,10 +441,52 @@ void SplashBitmap::getRGBLine(int yl, SplashColorPtr line) {
}
}
#if SPLASH_CMYK
void SplashBitmap::getCMYKLine(int yl, SplashColorPtr line) {
SplashColor col;
for (int x = 0; x < width; x++) {
getPixel(x, yl, col);
if (separationList->getLength() > 0) {
double c, m, y, k;
c = byteToDbl(col[0]);
m = byteToDbl(col[1]);
y = byteToDbl(col[2]);
k = byteToDbl(col[3]);
for (int i = 0; i < separationList->getLength(); i++) {
if (col[i+4] > 0) {
GfxCMYK cmyk;
GfxColor input;
input.c[0] = byteToCol(col[i+4]);
GfxSeparationColorSpace *sepCS = (GfxSeparationColorSpace *)separationList->get(i);
sepCS->getCMYK(&input, &cmyk);
col[0] = colToByte(cmyk.c);
col[1] = colToByte(cmyk.m);
col[2] = colToByte(cmyk.y);
col[3] = colToByte(cmyk.k);
c += byteToDbl(col[0]);
m += byteToDbl(col[1]);
y += byteToDbl(col[2]);
k += byteToDbl(col[3]);
}
}
col[0] = dblToByte(clip01(c));
col[1] = dblToByte(clip01(m));
col[2] = dblToByte(clip01(y));
col[3] = dblToByte(clip01(k));
}
*line++ = col[0];
*line++ = col[1];
*line++ = col[2];
*line++ = col[3];
}
}
#endif
SplashError SplashBitmap::writeImgFile(ImgWriter *writer, FILE *f, int hDPI, int vDPI) {
if (mode != splashModeRGB8 && mode != splashModeMono8 && mode != splashModeMono1 && mode != splashModeXBGR8
#if SPLASH_CMYK
&& mode != splashModeCMYK8
&& mode != splashModeCMYK8 && mode != splashModeDeviceN8
#endif
) {
error(errInternal, -1, "unsupported SplashBitmap mode");
......@@ -440,6 +526,29 @@ SplashError SplashBitmap::writeImgFile(ImgWriter *writer, FILE *f, int hDPI, int
delete[] row;
}
break;
case splashModeDeviceN8:
if (writer->supportCMYK()) {
unsigned char *row = new unsigned char[4 * width];
for (int y = 0; y < height; y++) {
getCMYKLine(y, row);
if (!writer->writeRow(&row)) {
delete[] row;
return splashErrGeneric;
}
}
delete[] row;
} else {
unsigned char *row = new unsigned char[3 * width];
for (int y = 0; y < height; y++) {
getRGBLine(y, row);
if (!writer->writeRow(&row)) {
delete[] row;
return splashErrGeneric;
}
}
delete[] row;
}
break;
#endif
case splashModeRGB8:
{
......
......@@ -34,6 +34,7 @@
#endif
#include "SplashTypes.h"
#include "poppler/GfxState.h"
#include <stdio.h>
class ImgWriter;
......@@ -51,7 +52,7 @@ public:
// upside-down, i.e., with the last row first in memory.
SplashBitmap(int widthA, int heightA, int rowPad,
SplashColorMode modeA, GBool alphaA,
GBool topDown = gTrue);
GBool topDown = gTrue, GooList *separationList = NULL);
static SplashBitmap *copy(SplashBitmap *src);
~SplashBitmap();
......@@ -64,6 +65,7 @@ public:
SplashColorMode getMode() { return mode; }
SplashColorPtr getDataPtr() { return data; }
Guchar *getAlphaPtr() { return alpha; }
GooList *getSeparationList() { return separationList; }
SplashError writePNMFile(char *fileName);
SplashError writePNMFile(FILE *f);
......@@ -75,6 +77,9 @@ public:
void getPixel(int x, int y, SplashColorPtr pixel);
void getRGBLine(int y, SplashColorPtr line);
#if SPLASH_CMYK
void getCMYKLine(int y, SplashColorPtr line);
#endif
Guchar getAlpha(int x, int y);
// Caller takes ownership of the bitmap data. The SplashBitmap
......@@ -92,6 +97,7 @@ private:
SplashColorPtr data; // pointer to row zero of the color data
Guchar *alpha; // pointer to row zero of the alpha data
// (always top-down)
GooList *separationList; // list of spot colorants and their mapping functions
friend class Splash;
};
......
......@@ -40,7 +40,7 @@
int splashColorModeNComps[] = {
1, 1, 3, 3, 4
#if SPLASH_CMYK
,4
, 4, 4 + SPOT_NCOMPS
#endif
};
......@@ -80,10 +80,14 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
rgbTransferG[i] = (Guchar)i;
rgbTransferB[i] = (Guchar)i;
grayTransfer[i] = (Guchar)i;
#if SPLASH_CMYK
cmykTransferC[i] = (Guchar)i;
cmykTransferM[i] = (Guchar)i;
cmykTransferY[i] = (Guchar)i;
cmykTransferK[i] = (Guchar)i;
for (int cp = 0; cp < SPOT_NCOMPS+4; cp++)
deviceNTransfer[cp][i] = (Guchar)i;
#endif
}
overprintMask = 0xffffffff;
overprintAdditive = gFalse;
......@@ -126,10 +130,14 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
rgbTransferG[i] = (Guchar)i;
rgbTransferB[i] = (Guchar)i;
grayTransfer[i] = (Guchar)i;
#if SPLASH_CMYK
cmykTransferC[i] = (Guchar)i;
cmykTransferM[i] = (Guchar)i;
cmykTransferY[i] = (Guchar)i;
cmykTransferK[i] = (Guchar)i;
for (int cp = 0; cp < SPOT_NCOMPS+4; cp++)
deviceNTransfer[cp][i] = (Guchar)i;
#endif
}
overprintMask = 0xffffffff;
overprintAdditive = gFalse;
......@@ -170,10 +178,14 @@ SplashState::SplashState(SplashState *state) {
memcpy(rgbTransferG, state->rgbTransferG, 256);
memcpy(rgbTransferB, state->rgbTransferB, 256);
memcpy(grayTransfer, state->grayTransfer, 256);
#if SPLASH_CMYK
memcpy(cmykTransferC, state->cmykTransferC, 256);
memcpy(cmykTransferM, state->cmykTransferM, 256);
memcpy(cmykTransferY, state->cmykTransferY, 256);
memcpy(cmykTransferK, state->cmykTransferK, 256);
for (int cp = 0; cp < SPOT_NCOMPS+4; cp++)
memcpy(deviceNTransfer[cp], state->deviceNTransfer[cp], 256);
#endif
overprintMask = state->overprintMask;
overprintAdditive = state->overprintAdditive;
next = NULL;
......@@ -228,16 +240,24 @@ void SplashState::setSoftMask(SplashBitmap *softMaskA) {
void SplashState::setTransfer(Guchar *red, Guchar *green, Guchar *blue,
Guchar *gray) {
#if SPLASH_CMYK
int i;
memcpy(rgbTransferR, red, 256);
memcpy(rgbTransferG, green, 256);
memcpy(rgbTransferB, blue, 256);
memcpy(grayTransfer, gray, 256);
for (i = 0; i < 256; ++i) {
cmykTransferC[i] = 255 - rgbTransferR[255 - i];
cmykTransferM[i] = 255 - rgbTransferG[255 - i];
cmykTransferY[i] = 255 - rgbTransferB[255 - i];
cmykTransferK[i] = 255 - grayTransfer[255 - i];
}
for (i = 0; i < 256; ++i) {
deviceNTransfer[0][i] = 255 - rgbTransferR[255 - i];
deviceNTransfer[1][i] = 255 - rgbTransferG[255 - i];
deviceNTransfer[2][i] = 255 - rgbTransferB[255 - i];
deviceNTransfer[3][i] = 255 - grayTransfer[255 - i];
}
#endif
memcpy(rgbTransferR, red, 256);
memcpy(rgbTransferG, green, 256);
memcpy(rgbTransferB, blue, 256);
memcpy(grayTransfer, gray, 256);
}
......@@ -121,10 +121,13 @@ private:
rgbTransferG[256],
rgbTransferB[256];
Guchar grayTransfer[256];
#if SPLASH_CMYK
Guchar cmykTransferC[256],
cmykTransferM[256],
cmykTransferY[256],
cmykTransferK[256];
Guchar deviceNTransfer[SPOT_NCOMPS+4][256];
#endif
Guint overprintMask;
GBool overprintAdditive;
......
......@@ -13,7 +13,7 @@
//
// Copyright (C) 2006, 2010 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
// Copyright (C) 2009, 2011 Thomas Freitag <Thomas.Freitag@alfa.de>