Copy link to clipboard
Copied
Hi,
I need some help to create a DeviceN colorspace.
Thanks to the PDF Reference and this forum, I have written this function
// Creates a DeviceN colorspace
PDEColorSpace createDeviceN(PDDoc pdDoc) {
PDEColorSpace deviceNColorSpace;
CosDoc cosDocObj = PDDocGetCosDoc(pdDoc);
CosObj colourSpaceCosObj = CosNewArray(cosDocObj, true, 4);
// Names array
CosObj namesCosObj = CosNewArray(cosDocObj, false, 5);
CosArrayPut(namesCosObj, 0, CosNewNameFromString(cosDocObj, false, "Cyan"));
CosArrayPut(namesCosObj, 1, CosNewNameFromString(cosDocObj, false, "Magenta"));
CosArrayPut(namesCosObj, 2, CosNewNameFromString(cosDocObj, false, "Yellow"));
CosArrayPut(namesCosObj, 3, CosNewNameFromString(cosDocObj, false, "Black"));
CosArrayPut(namesCosObj, 4, CosNewNameFromString(cosDocObj, false, "Blue"));
// Domain
CosObj cosDomainObj = CosNewArray(cosDocObj, false, 10);
CosArrayPut(cosDomainObj, 0, CosNewFloat(cosDocObj, false, (float) 0.0));
CosArrayPut(cosDomainObj, 1, CosNewFloat(cosDocObj, false, (float) 1.0));
[…]
// Range
CosObj cosRangeObj = CosNewArray(cosDocObj, false, 8);
CosArrayPut(cosRangeObj, 0, CosNewFloat(cosDocObj, false, (float) 0.0));
CosArrayPut(cosRangeObj, 1, CosNewFloat(cosDocObj, false, (float) 1.0));
[…]
// Function
//const char *PostScriptFunc = "{ pop }";
const char *PostScriptFunc = "{ 0.5 0.5 0.5 0.5 }";
ASInt32 Size = strlen(PostScriptFunc);
CosObj cosFunctDict = CosNewDict(cosDocObj, false, 4);
CosDictPut(cosFunctDict, ASAtomFromString("FunctionType"), CosNewInteger(cosDocObj, false, 4));
CosDictPut(cosFunctDict, ASAtomFromString("Domain"), cosDomainObj);
CosDictPut(cosFunctDict, ASAtomFromString("Range"), cosRangeObj);
CosDictPut(cosFunctDict, ASAtomFromString("Length"), CosNewInteger(cosDocObj, true, Size));
ASStm Stream = ASMemStmRdOpen(PostScriptFunc, Size);
CosObj PostScriptFuncStreamObj = CosNewStream(cosDocObj, true, Stream, 0, true, cosFunctDict, CosNewNull(), -1);
ASStmClose(Stream);
CosArrayPut(colourSpaceCosObj, 0, CosNewNameFromString(cosDocObj, false, "DeviceN"));
CosArrayPut(colourSpaceCosObj, 1, namesCosObjP);
CosArrayPut(colourSpaceCosObj, 2, CosNewNameFromString(cosDocObj, false, "DeviceCMYK"));
CosArrayPut(colourSpaceCosObj, 3, PostScriptFuncStreamObj);
deviceNColorSpace = PDEColorSpaceCreateFromCosObj(&colourSpaceCosObj);
return deviceNColorSpace;
}
According to an answer on a post of yokuju, I have tried to add the optional attributes by adding this part to the function
// Domain
CosObj cosDomainObj2 = CosNewArray(cosDocObj, false, 2);
CosArrayPut(cosDomainObj2, 0, CosNewFloat(cosDocObj, false, (float) 0.0));
CosArrayPut(cosDomainObj2, 1, CosNewFloat(cosDocObj, false, (float) 1.0));
// Range
CosObj cosRangeObj2 = CosNewArray(cosDocObj, false, 8);
CosArrayPut(cosRangeObj2, 0, CosNewFloat(cosDocObj, false, (float) 0.0));
CosArrayPut(cosRangeObj2, 1, CosNewFloat(cosDocObj, false, (float) 1.0));
[...]
// Function
const char *PostScriptFunc2 = "{ 1.0 1.0 0.0 0.0 }";
ASInt32 Size2 = strlen(PostScriptFunc2);
CosObj cosFunctDict2 = CosNewDict(cosDocObj, false, 4);
CosDictPut(cosFunctDict2, ASAtomFromString("FunctionType"), CosNewInteger(cosDocObj, false, 4));
CosDictPut(cosFunctDict2, ASAtomFromString("Domain"), cosDomainObj2);
CosDictPut(cosFunctDict2, ASAtomFromString("Range"), cosRangeObj2);
CosDictPut(cosFunctDict2, ASAtomFromString("Length"), CosNewInteger(cosDocObj, true, Size2));
ASStm Stream2 = ASMemStmRdOpen(PostScriptFunc2, Size2);
CosObj PostScriptFuncStreamObj2 = CosNewStream(cosDocObj, true, Stream2, 0, true, cosFunctDict2, CosNewNull(), -1);
ASStmClose(Stream2);
CosObj cosBlueObj = CosNewArray(cosDocObj, false, 4);
CosArrayPut(cosBlueObj, 0, CosNewNameFromString(cosDocObj, false, "Separation"));
CosArrayPut(cosBlueObj, 1, CosNewNameFromString(cosDocObj, false, "Blue"));
CosArrayPut(cosBlueObj, 2, CosNewNameFromString(cosDocObj, false, "DeviceCMYK"));
CosArrayPut(cosBlueObj, 3, PostScriptFuncStreamObj2);
// Colorants sictionary
CosObj cosColorantsDict = CosNewDict(cosDocObj, false, 1);
CosDictPut(cosFunctDict2, ASAtomFromString("Blue"), cosBlueObj);
CosArrayPut(colourSpaceCosObjP, 4, PostScriptFuncStreamObj2);
Even with the additionnal attribute, I still have the same issue as Sam BSW. If I use just one time this colorspace, the current page will be empty. In the PDF file instead of having something like
<</Contents 3 0 R/CropBox[0.0 0.0 612.0 842.4]/MediaBox[0.0 0.0 612.0 842.4]/Parent 162 0 R/Resources<</ColorSpace<</CS0 227 0 R/CS1 227 0 R>>/Font<</T1_0 12 0 R/ [...] /T1_9 29 0 R>>/ProcSet[/PDF/Text/ImageC]/XObject<</Im0 230 0 R>>>>/Rotate 0/Type/Page>>
for the page, I have simply
<</CropBox[0.0 0.0 612.0 842.4]/MediaBox[0.0 0.0 612.0 842.4]/Parent 162 0 R/Resources<<>>/Rotate 0/Type/Page>>
I am not a power user of the Adobe SDK so I am stuck here. I hope that someone can help me with my issue.
Thank you
Hmm. I've worked a lot with DeviceN but never in PDFEdit. I observe that the PDEColorValue structure has an element colorObj2, of type PDEObject. I can't immediately see what this is for or how to use it (the docs are silent), but this is interesting PDEPath & DeviceN -- I did contribute to the discussion but I have no recollection of it !
Copy link to clipboard
Copied
This code makes a Cos object for the color space. What do you do with that next?
Copy link to clipboard
Copied
It doesn't work, so maybe I am totally wrong.
I use this method like that (I have no problem with Lab, RGB and CMYK)
PDEColorSpace pdeColorSpace = NULL;
if ((strcmp(colorspacetype, "LAB") == 0) || (strcmp(colorspacetype, "Lab") == 0)) {
pdeColorSpace = createLab(*pdDoc);
}
else if (strcmp(colorspacetype, "RGB") == 0) {
pdeColorSpace = PDEColorSpaceCreateFromName(ASAtomFromString("DeviceRGB"));
}
else if (strcmp(colorspacetype, "CMYK") == 0) {
pdeColorSpace = PDEColorSpaceCreateFromName(ASAtomFromString("DeviceCMYK"));
}
else if (strcmp(colorspacetype, "Multi") == 0) {
pdeColorSpace = createDeviceN(*pdDoc);
}
PDEGraphicState gState;
PDEColorSpec strokeClrSpec, fillClrSpec;
PDEColorValue strokeClrValue, fillClrValue;
// Stroke
memset(&strokeClrValue, 0, sizeof(PDEColorValue));
strokeClrValue.color[0] = FloatToASFixed(value1);
strokeClrValue.color[1] = FloatToASFixed(value2);
strokeClrValue.color[2] = FloatToASFixed(value3);
strokeClrValue.color[3] = FloatToASFixed(value4);
strokeClrValue.color[4] = FloatToASFixed(value5);
// Fill
memset(&fillClrValue, 0, sizeof(PDEColorValue));
fillClrValue.color[0] = FloatToASFixed(value1);
fillClrValue.color[1] = FloatToASFixed(value2);
fillClrValue.color[2] = FloatToASFixed(value3);
fillClrValue.color[3] = FloatToASFixed(value4);
fillClrValue.color[4] = FloatToASFixed(value5);
strokeClrSpec.space = fillClrSpec.space = pdeColorspace;
strokeClrSpec.value = strokeClrValue;
fillClrSpec.value = fillClrValue;
memset(&gState, 0, sizeof(PDEGraphicState));
gState.fillColorSpec = fillClrSpec;
gState.strokeColorSpec = strokeClrSpec;
gState.lineWidth = width;
gState.miterLimit = fixedTen;
gState.flatness = fixedOne;
Copy link to clipboard
Copied
Thanks. Looking more closely, I observe that your type 4 function is definitely wrong.
Your function needs to transform 5 inputs to 4 outputs, but in practice it transforms 5 inputs to 9 outputs, and will likely produce internal stack overflows or something nasty.
Don't know if that's the issue. The Cos object produced looks to be what the code suggests you wanted to see, assuming the domain and range were correctly filled in.
{pop} would be syntactically valid for getting 4 outputs, though of course a true solution requires you to know the conversion algorithm you want and to implement it in PostScript.
Copy link to clipboard
Copied
In fact { pop } is what I want to do but it's no working.
Copy link to clipboard
Copied
Hmm. I've worked a lot with DeviceN but never in PDFEdit. I observe that the PDEColorValue structure has an element colorObj2, of type PDEObject. I can't immediately see what this is for or how to use it (the docs are silent), but this is interesting PDEPath & DeviceN -- I did contribute to the discussion but I have no recollection of it !
Copy link to clipboard
Copied
Thank you for the hint about the colorObj2. I have added this piece of code
PDEDeviceNColors fillClrObj2 = PDEDeviceNColorsCreate(fillClrValue.color, sizeof(fillClrValue.color));
PDEDeviceNColors strokeClrObj2 = PDEDeviceNColorsCreate(strokeClrValue.color, sizeof(strokeClrValue.color));
fillClrValue.colorObj2 = (PDEObject)fillClrObj2;
strokeClrValue.colorObj2 = (PDEObject)strokeClrObj2;
and now there is something written in my document. Maybe it's an other question but the alternative colorspace (DeviceCMYK) is always used even if the fifth value is in the domain [0.0, 1.0]. Is there something to add to use the Blue color ?
Copy link to clipboard
Copied
If this is about weird stuff PDFEdit does, I'm out of my experience, but if it's about what DeviceN does, that's a different story.
What are you expecting to see, or to find, and what are you actually seeing or finding? The alternate colour (CMYK in your case) is always used for display and non-PostScript printing.
Copy link to clipboard
Copied
I want for example fill a square with (CMYKB = 0.3 0.2 0.5 0.6 0.8) but it is always the alternate which is print (CMYK = 0.3 0.2 0.5 0.6).
I fill the PDEColorValue with the five values but I never say that the fifth value is supposed to be Blue.
Copy link to clipboard
Copied
The only time the alternative colour is NOT used is PostScript printing, when printing with named inks (inks in buckets). That’s all. The rest of the time you get the alternate, which MUST have a correct transform for this reason.
Copy link to clipboard
Copied
To put it another way: Blue is used in your case, when printing on a printing press with a named ink called “Blue” (from a bucket of blue ink). Anything else you expect isn’t going to happen.
Copy link to clipboard
Copied
Ok I understand now. I will write the good transformation function. Thank you very much for your help.