Create a DeviceN colorspace

Community Beginner ,
Feb 06, 2019

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

TOPICS
Acrobat SDK and JavaScript

Views

197

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

1 Correct Answer

Most Valuable Participant , Feb 07, 2019
Test Screen Name Most Valuable Participant , Feb 07, 2019
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 !

Likes

Translate

Translate
Jump to answer Jump to answer
Most Valuable Participant ,
Feb 06, 2019

Copy link to clipboard

Copied

This code makes a Cos object for the color space. What do you do with that next?

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Feb 06, 2019

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;

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Most Valuable Participant ,
Feb 07, 2019

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.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Feb 07, 2019

Copy link to clipboard

Copied

In fact { pop } is what I want to do but it's no working.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Most Valuable Participant ,
Feb 07, 2019

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 !

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Feb 07, 2019

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 ?

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Most Valuable Participant ,
Feb 07, 2019

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.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Feb 07, 2019

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.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Most Valuable Participant ,
Feb 07, 2019

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.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Most Valuable Participant ,
Feb 07, 2019

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.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
michelm76805089 AUTHOR LATEST
Community Beginner ,
Feb 07, 2019

Copy link to clipboard

Copied

Ok I understand now. I will write the good transformation function. Thank you very much for your help.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more