1066 lines
37 KiB
C
1066 lines
37 KiB
C
|
#include "generic.h"
|
||
|
#include "stdio.h"
|
||
|
#pragma code_seg(_ICMSEG)
|
||
|
|
||
|
char ICMSEG BeginString[] = "<";
|
||
|
char ICMSEG EndString[] = ">";
|
||
|
char ICMSEG BeginArray[] = "[";
|
||
|
char ICMSEG EndArray[] = "]";
|
||
|
char ICMSEG BeginFunction[] = "{";
|
||
|
char ICMSEG EndFunction[] = "}bind ";
|
||
|
char ICMSEG BeginDict[] = "<<";
|
||
|
char ICMSEG EndDict[] = ">>";
|
||
|
char ICMSEG BlackPoint[] = "[0 0 0]";
|
||
|
char ICMSEG DictType[] = "/ColorRenderingType 1 ";
|
||
|
char ICMSEG IntentType[] = "/RenderingIntent ";
|
||
|
char ICMSEG IntentPer[] = "/Perceptual";
|
||
|
char ICMSEG IntentSat[] = "/Saturation";
|
||
|
char ICMSEG IntentACol[] = "/AbsoluteColorimetric";
|
||
|
char ICMSEG IntentRCol[] = "/RelativeColorimetric";
|
||
|
|
||
|
char ICMSEG WhitePointTag[] = "/WhitePoint ";
|
||
|
char ICMSEG BlackPointTag[] = "/BlackPoint ";
|
||
|
char ICMSEG RangePQRTag[] = "/RangePQR ";
|
||
|
char ICMSEG TransformPQRTag[] = "/TransformPQR ";
|
||
|
char ICMSEG MatrixPQRTag[] = "/MatrixPQR ";
|
||
|
|
||
|
char ICMSEG RangeABCTag[] = "/RangeABC ";
|
||
|
char ICMSEG MatrixATag[] = "/MatrixA ";
|
||
|
char ICMSEG MatrixABCTag[] = "/MatrixABC ";
|
||
|
char ICMSEG EncodeABCTag[] = "/EncodeABC ";
|
||
|
char ICMSEG RangeLMNTag[] = "/RangeLMN ";
|
||
|
char ICMSEG MatrixLMNTag[] = "/MatrixLMN ";
|
||
|
char ICMSEG EncodeLMNTag[] = "/EncodeLMN ";
|
||
|
char ICMSEG RenderTableTag[] = "/RenderTable ";
|
||
|
char ICMSEG CIEBasedATag[] = "/CIEBasedA ";
|
||
|
char ICMSEG CIEBasedABCTag[] = "/CIEBasedABC ";
|
||
|
char ICMSEG CIEBasedDEFGTag[] = "/CIEBasedDEFG ";
|
||
|
char ICMSEG CIEBasedDEFTag[] = "/CIEBasedDEF ";
|
||
|
char ICMSEG DecodeATag[] = "/DecodeA ";
|
||
|
char ICMSEG DecodeABCTag[] = "/DecodeABC ";
|
||
|
char ICMSEG DecodeLMNTag[] = "/DecodeLMN ";
|
||
|
char ICMSEG DeviceRGBTag[] = "/DeviceRGB ";
|
||
|
char ICMSEG DeviceCMYKTag[] = "/DeviceCMYK ";
|
||
|
char ICMSEG DeviceGrayTag[] = "/DeviceGray ";
|
||
|
char ICMSEG TableTag[] = "/Table ";
|
||
|
char ICMSEG DecodeDEFGTag[] = "/DecodeDEFG ";
|
||
|
char ICMSEG DecodeDEFTag[] = "/DecodeDEF ";
|
||
|
|
||
|
char ICMSEG NullOp[] = "";
|
||
|
char ICMSEG DupOp[] = "dup ";
|
||
|
char ICMSEG UserDictOp[] = "userdict ";
|
||
|
char ICMSEG GlobalDictOp[] = "globaldict ";
|
||
|
char ICMSEG CurrentGlobalOp[] = "currentglobal ";
|
||
|
char ICMSEG SetGlobalOp[] = "setglobal ";
|
||
|
char ICMSEG DefOp[] = "def ";
|
||
|
char ICMSEG BeginOp[] = "begin ";
|
||
|
char ICMSEG EndOp[] = "end ";
|
||
|
char ICMSEG TrueOp[] = "true ";
|
||
|
char ICMSEG FalseOp[] = "false ";
|
||
|
char ICMSEG MulOp[] = "mul ";
|
||
|
char ICMSEG DivOp[] = "div ";
|
||
|
|
||
|
char ICMSEG NewLine[] = "\n";
|
||
|
char ICMSEG Slash[] = "/";
|
||
|
char ICMSEG Space[] = " ";
|
||
|
char ICMSEG CRDBegin[] = "%** CRD Begin ";
|
||
|
char ICMSEG CRDEnd[] = "%** CRD End ";
|
||
|
char ICMSEG CieBasedDEFGBegin[] = "%** CieBasedDEFG CSA Begin ";
|
||
|
char ICMSEG CieBasedDEFBegin[] = "%** CieBasedDEF CSA Begin ";
|
||
|
char ICMSEG CieBasedABCBegin[] = "%** CieBasedABC CSA Begin ";
|
||
|
char ICMSEG CieBasedABegin[] = "%** CieBasedA CSA Begin ";
|
||
|
char ICMSEG CieBasedDEFGEnd[] = "%** CieBasedDEFG CSA End ";
|
||
|
char ICMSEG CieBasedDEFEnd[] = "%** CieBasedDEF CSA End ";
|
||
|
char ICMSEG CieBasedABCEnd[] = "%** CieBasedABC CSA End ";
|
||
|
char ICMSEG CieBasedAEnd[] = "%** CieBasedA CSA End ";
|
||
|
char ICMSEG RangeABC[] = "[ 0 1 0 1 0 1 ] ";
|
||
|
char ICMSEG RangeLMN[] = "[ 0 2 0 2 0 2 ] ";
|
||
|
char ICMSEG Identity[] = "[1 0 0 0 1 0 0 0 1]";
|
||
|
char ICMSEG RangeABC_Lab[] = "[0 100 -128 127 -128 127]";
|
||
|
|
||
|
/********** This PostScript code clips incoming value between 0.0 and 1.0
|
||
|
Use: x <clip> -- <clipped x> */
|
||
|
char ICMSEG Clip01[] = "dup 1.0 ge{pop 1.0}{dup 0.0 lt{pop 0.0}if}ifelse ";
|
||
|
char ICMSEG DecodeA3[] = "256 div exp ";
|
||
|
char ICMSEG DecodeA3Rev[] = "256 div 1.0 exch div exp ";
|
||
|
char ICMSEG DecodeABCArray[] = "DecodeABC_";
|
||
|
char ICMSEG InputArray[] = "Inp_";
|
||
|
char ICMSEG OutputArray[] = "Out_";
|
||
|
char ICMSEG PreViewInArray[] = "IPV_";
|
||
|
char ICMSEG PreViewOutArray[] = "OPV_";
|
||
|
|
||
|
char ICMSEG AdobeCSA[] = "[ /CIEBasedABC << /DecodeLMN [\n\
|
||
|
{dup 0.03928 le {12.92321 div}{0.055 add 1.055 div 2.4 exp}ifelse} bind dup dup ]\n\
|
||
|
/MatrixLMN [0.412457 0.212673 0.019334 0.357576 0.715152 0.119192 0.180437 0.072175 0.950301]\n\
|
||
|
/WhitePoint [ 0.9505 1 1.0890 ] >> ]";
|
||
|
|
||
|
char ICMSEG AdobeCRD[] = " /RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n\
|
||
|
/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296]\n\
|
||
|
/TransformPQR [{exch pop exch 3 get mul exch pop exch 3 get div} bind\n\
|
||
|
{exch pop exch 4 get mul exch pop exch 4 get div} bind\n\
|
||
|
{exch pop exch 5 get mul exch pop exch 5 get div} bind]\n\
|
||
|
/MatrixLMN [3.240449 -0.969265 0.055643 -1.537136 1.876011 -0.204026 -0.498531 0.041556 1.057229]\n\
|
||
|
/EncodeABC [{dup 0.00304 le {12.92321 mul}{1 2.4 div exp 1.055 mul 0.055 sub}ifelse} bind dup dup]\n\
|
||
|
/WhitePoint[0.9505 1 1.0890] >>";
|
||
|
|
||
|
// This PostScript segment takes value in range from 0.0 to 1.0 and
|
||
|
// interpolates the result using array supplied.
|
||
|
// x [array] -- <interpolated value>
|
||
|
|
||
|
char ICMSEG IndexArray16b[] = \
|
||
|
" dup length 1 sub 3 -1 roll mul dup dup floor cvi \
|
||
|
exch ceiling cvi 3 index exch get 32768 add 4 -1 roll 3 -1 roll get 32768 add \
|
||
|
dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add ";
|
||
|
|
||
|
char ICMSEG IndexArray[] = \
|
||
|
" dup length 1 sub 3 -1 roll mul dup dup floor cvi \
|
||
|
exch ceiling cvi 3 index exch get 4 -1 roll 3 -1 roll get \
|
||
|
dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add ";
|
||
|
|
||
|
char ICMSEG TestingDEFG[] = \
|
||
|
"/SupportDEFG? {/CIEBasedDEFG /ColorSpaceFamily resourcestatus { pop pop languagelevel 3 ge}{false} ifelse} def";
|
||
|
|
||
|
char ICMSEG SupportDEFG_S[] = "SupportDEFG? { ";
|
||
|
char ICMSEG NotSupportDEFG_S[] = "SupportDEFG? not { ";
|
||
|
char ICMSEG SupportDEFG_E[] = "}if ";
|
||
|
|
||
|
char ICMSEG StartClip[] = "dup 1.0 le{dup 0.0 ge{";
|
||
|
char ICMSEG EndClip[] = "}if}if ";
|
||
|
|
||
|
char ICMSEG Scale8[] = "255 div ";
|
||
|
char ICMSEG Scale16[] = "65535 div ";
|
||
|
char ICMSEG Scale16XYZ[] = "32768 div ";
|
||
|
char ICMSEG TFunction8[] = "exch 255 mul round cvi get 255 div ";
|
||
|
char ICMSEG TFunction8XYZ[] = "exch 255 mul round cvi get 128 div ";
|
||
|
char ICMSEG MatrixABCLab[] = "[1 1 1 1 0 0 0 0 -1]";
|
||
|
char ICMSEG DecodeABCLab1[] = "[{16 add 116 div} bind {500 div} bind {200 div} bind]";
|
||
|
char ICMSEG DecodeALab[] = " 50 mul 16 add 116 div ";
|
||
|
char ICMSEG DecodeLMNLab[] = \
|
||
|
"dup 0.206897 ge{dup dup mul mul}{0.137931 sub 0.128419 mul} ifelse ";
|
||
|
|
||
|
char ICMSEG RangeLMNLab[] = "[0 1 0 1 0 1]";
|
||
|
char ICMSEG EncodeLMNLab[] = "\
|
||
|
dup 0.008856 le{7.787 mul 0.13793 add}{0.3333 exp}ifelse ";
|
||
|
|
||
|
char ICMSEG MatrixABCLabCRD[] = "[0 500 0 116 -500 200 0 0 -200]";
|
||
|
char ICMSEG MatrixABCXYZCRD[] = "[0 1 0 1 0 0 0 0 1]";
|
||
|
char ICMSEG EncodeABCLab1[] = "16 sub 100 div ";
|
||
|
char ICMSEG EncodeABCLab2[] = "128 add 255 div ";
|
||
|
|
||
|
char ICMSEG RangePQR[] = "[ -0.07 2.2 -0.02 1.4 -0.2 4.8 ]";
|
||
|
char ICMSEG MatrixPQR[] = "[0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296]";
|
||
|
|
||
|
char *TransformPQR[3] = {
|
||
|
"exch pop exch 3 get mul exch pop exch 3 get div ",
|
||
|
"exch pop exch 4 get mul exch pop exch 4 get div ",
|
||
|
"exch pop exch 5 get mul exch pop exch 5 get div "};
|
||
|
|
||
|
#define SRGBCRC 0x678175D2L
|
||
|
|
||
|
#pragma optimize("",off)
|
||
|
|
||
|
/*
|
||
|
* CreateLutCRD
|
||
|
* function:
|
||
|
* this is the function which creates the Color Rendering Dictionary (CRD)
|
||
|
* from the data supplied in the ColorProfile's LUT8 or LUT16 tag.
|
||
|
* prototype:
|
||
|
* SINT EXTERN CreateLutCRD(
|
||
|
* CHANDLE cp,
|
||
|
* SINT Index,
|
||
|
* MEMPTR lpMem,
|
||
|
* BOOL AllowBinary)
|
||
|
* parameters:
|
||
|
* cp -- Color Profile handle
|
||
|
* Index -- Index of the tag
|
||
|
* lpMem -- Pointer to the memory block
|
||
|
* AllowBinary -- 1: binary CRD allowed, 0: only ascii CRD allowed.
|
||
|
|
||
|
* returns:
|
||
|
* SINT -- !=0 if the function was successful,
|
||
|
* 0 otherwise.
|
||
|
* Returns number of bytes required/transferred
|
||
|
*/
|
||
|
|
||
|
SINT EXTERN
|
||
|
CreateLutCRD(CHANDLE cp, SINT Index, MEMPTR lpMem, DWORD InputIntent, BOOL AllowBinary)
|
||
|
{
|
||
|
SINT nInputCh, nOutputCh, nGrids;
|
||
|
SINT nInputTable, nOutputTable, nNumbers;
|
||
|
CSIG Tag, PCS;
|
||
|
CSIG IntentSig;
|
||
|
|
||
|
SINT Ret;
|
||
|
SINT i, j;
|
||
|
MEMPTR lpTable;
|
||
|
|
||
|
SFLOAT IlluminantWP[3];
|
||
|
SFLOAT MediaWP[3];
|
||
|
MEMPTR Buff = NULL;
|
||
|
SINT MemSize = 0;
|
||
|
MEMPTR lpOldMem = lpMem;
|
||
|
char PublicArrayName[TempBfSize];
|
||
|
HGLOBAL hMem;
|
||
|
MEMPTR lpLineStart;
|
||
|
// Check if we can generate the CRD
|
||
|
if (!GetCPTagSig(cp, Index, (LPCSIG)& IntentSig) ||
|
||
|
!GetCPElementType(cp, Index, (LPCSIG)& Tag) ||
|
||
|
((Tag != icSigLut8Type) && (Tag != icSigLut16Type)) ||
|
||
|
!GetCPConnSpace(cp, (LPCSIG)& PCS) ||
|
||
|
!GetCPElementSize(cp, Index, (LPSINT)& MemSize) ||
|
||
|
!MemAlloc(MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR)& Buff) ||
|
||
|
!GetCPElement(cp, Index, Buff, MemSize)) {
|
||
|
if (NULL != Buff) {
|
||
|
MemFree(hMem);
|
||
|
}
|
||
|
return (0);
|
||
|
}
|
||
|
GetCLUTinfo(Tag, Buff, &nInputCh, &nOutputCh,
|
||
|
&nGrids, &nInputTable, &nOutputTable, &i);
|
||
|
// Level 2 printers support only tri-component CIEBasedABC input,
|
||
|
// but can have either 3 or 4 output channels.
|
||
|
if (((nOutputCh != 3) &&
|
||
|
(nOutputCh != 4)) ||
|
||
|
(nInputCh != 3)) {
|
||
|
SetCPLastError(CP_POSTSCRIPT_ERR);
|
||
|
MemFree(hMem);
|
||
|
return (0);
|
||
|
}
|
||
|
Ret = nInputCh * nInputTable * 6 +
|
||
|
nOutputCh * nOutputTable * 6 + // Number of INT bytes
|
||
|
nOutputCh * nGrids * nGrids * nGrids * 2 + // LUT HEX bytes
|
||
|
nInputCh * (lstrlen(IndexArray) +
|
||
|
lstrlen(StartClip) +
|
||
|
lstrlen(EndClip)) +
|
||
|
nOutputCh * (lstrlen(IndexArray) +
|
||
|
lstrlen(StartClip) +
|
||
|
lstrlen(EndClip)) +
|
||
|
2048; // + other PS stuff
|
||
|
|
||
|
if (lpMem == NULL) // This is a size request
|
||
|
{
|
||
|
MemFree(hMem);
|
||
|
return (Ret);
|
||
|
}
|
||
|
// Get all necessary params from the header
|
||
|
// GetCPRenderIntent (cp, (LPCSIG) & Intent); // Get Intent
|
||
|
GetCPWhitePoint(cp, (LPSFLOAT)& IlluminantWP); // .. Illuminant
|
||
|
|
||
|
// Support absolute whitePoint
|
||
|
if (InputIntent == icAbsoluteColorimetric) {
|
||
|
if (!GetCPMediaWhitePoint(cp, (LPSFLOAT)& MediaWP)) // .. Media WhitePoint
|
||
|
{
|
||
|
MediaWP[0] = IlluminantWP[0];
|
||
|
MediaWP[1] = IlluminantWP[1];
|
||
|
MediaWP[2] = IlluminantWP[2];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//******** Define golbal array used in EncodeABC and RenderTaber
|
||
|
GetPublicArrayName(cp, IntentSig, PublicArrayName);
|
||
|
lpMem += WriteNewLineObject(lpMem, CRDBegin);
|
||
|
|
||
|
lpMem += EnableGlobalDict(lpMem);
|
||
|
lpMem += BeginGlobalDict(lpMem);
|
||
|
|
||
|
lpMem += CreateInputArray(lpMem, nInputCh, nInputTable,
|
||
|
(MEMPTR)PublicArrayName, Tag, Buff, AllowBinary, NULL);
|
||
|
|
||
|
i = nInputTable * nInputCh +
|
||
|
nGrids * nGrids * nGrids * nOutputCh;
|
||
|
lpMem += CreateOutputArray(lpMem, nOutputCh, nOutputTable, i,
|
||
|
(MEMPTR)PublicArrayName, Tag, Buff, AllowBinary, NULL);
|
||
|
|
||
|
lpMem += EndGlobalDict(lpMem);
|
||
|
|
||
|
//************* Start writing CRD ****************************
|
||
|
lpMem += WriteNewLineObject(lpMem, BeginDict); // Begin dictionary
|
||
|
lpMem += WriteObject(lpMem, DictType); // Dictionary type
|
||
|
|
||
|
lpMem += WriteNewLineObject(lpMem, IntentType); // RenderingIntent
|
||
|
switch (InputIntent) {
|
||
|
case icPerceptual:
|
||
|
lpMem += WriteObject(lpMem, IntentPer);
|
||
|
break;
|
||
|
|
||
|
case icSaturation:
|
||
|
lpMem += WriteObject(lpMem, IntentSat);
|
||
|
break;
|
||
|
|
||
|
case icRelativeColorimetric:
|
||
|
lpMem += WriteObject(lpMem, IntentRCol);
|
||
|
break;
|
||
|
|
||
|
case icAbsoluteColorimetric:
|
||
|
lpMem += WriteObject(lpMem, IntentACol);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//********** Send Black/White Point.
|
||
|
lpMem += SendCRDBWPoint(lpMem, IlluminantWP);
|
||
|
|
||
|
//********** Send PQR - used for Absolute Colorimetric *****
|
||
|
lpMem += SendCRDPQR(lpMem, InputIntent, IlluminantWP);
|
||
|
|
||
|
//********** Send LMN - For Absolute Colorimetric use WhitePoint's XYZs
|
||
|
lpMem += SendCRDLMN(lpMem, InputIntent, IlluminantWP, MediaWP, PCS);
|
||
|
|
||
|
// ******** Create MatrixABC and EncodeABC stuff
|
||
|
lpMem += SendCRDABC(lpMem, PublicArrayName,
|
||
|
PCS, nInputCh, Buff, NULL, Tag, AllowBinary);
|
||
|
|
||
|
//********** /RenderTable
|
||
|
lpMem += WriteNewLineObject(lpMem, RenderTableTag);
|
||
|
lpMem += WriteObject(lpMem, BeginArray);
|
||
|
|
||
|
lpMem += WriteInt(lpMem, nGrids); // Send down Na
|
||
|
lpMem += WriteInt(lpMem, nGrids); // Send down Nb
|
||
|
lpMem += WriteInt(lpMem, nGrids); // Send down Nc
|
||
|
|
||
|
lpLineStart = lpMem;
|
||
|
lpMem += WriteNewLineObject(lpMem, BeginArray);
|
||
|
nNumbers = nGrids * nGrids * nOutputCh;
|
||
|
for (i = 0; i < nGrids; i++) // Na strings should be sent
|
||
|
{
|
||
|
lpMem += WriteObject(lpMem, NewLine);
|
||
|
lpLineStart = lpMem;
|
||
|
if (Tag == icSigLut8Type) {
|
||
|
lpTable = (MEMPTR)(((lpcpLut8Type)Buff)->lut.data) +
|
||
|
nInputTable * nInputCh +
|
||
|
nNumbers * i;
|
||
|
} else {
|
||
|
lpTable = (MEMPTR)(((lpcpLut16Type)Buff)->lut.data) +
|
||
|
2 * nInputTable * nInputCh +
|
||
|
2 * nNumbers * i;
|
||
|
}
|
||
|
if (!AllowBinary) // Output ASCII CRD
|
||
|
{
|
||
|
lpMem += WriteObject(lpMem, BeginString);
|
||
|
if (Tag == icSigLut8Type)
|
||
|
lpMem += WriteHexBuffer(lpMem, lpTable, lpLineStart, nNumbers);
|
||
|
else {
|
||
|
for (j = 0; j < nNumbers; j++) {
|
||
|
lpMem += WriteHex(lpMem, ui16toSINT(lpTable) / 256);
|
||
|
lpTable += sizeof(icUInt16Number);
|
||
|
if (((SINT)(lpMem - lpLineStart)) > MAX_LINELENG) {
|
||
|
lpLineStart = lpMem;
|
||
|
lpMem += WriteObject(lpMem, NewLine);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, EndString);
|
||
|
} else { // Output BINARY CRD
|
||
|
lpMem += WriteStringToken(lpMem, 143, nNumbers);
|
||
|
if (Tag == icSigLut8Type)
|
||
|
lpMem += WriteByteString(lpMem, lpTable, nNumbers);
|
||
|
else
|
||
|
lpMem += WriteInt2ByteString(lpMem, lpTable, nNumbers);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lpMem += WriteObject(lpMem, EndArray); // End array
|
||
|
lpMem += WriteInt(lpMem, nOutputCh); // Send down m
|
||
|
|
||
|
//********** Send Output Table.
|
||
|
lpMem += SendCRDOutputTable(lpMem, PublicArrayName,
|
||
|
nOutputCh, Tag, FALSE, AllowBinary);
|
||
|
|
||
|
lpMem += WriteObject(lpMem, EndArray); // End array
|
||
|
lpMem += WriteObject(lpMem, EndDict); // End dictionary definition
|
||
|
|
||
|
lpMem += WriteNewLineObject(lpMem, CRDEnd);
|
||
|
|
||
|
// Testing Convert binary to ascii
|
||
|
// i = ConvertBinaryData2Ascii(lpOldMem, (SINT)(lpMem - lpOldMem), Ret);
|
||
|
// lpMem = lpOldMem + i;
|
||
|
// Testing Convert binary to ascii
|
||
|
|
||
|
MemFree(hMem);
|
||
|
return ((SINT)((unsigned long)(lpMem - lpOldMem)));
|
||
|
}
|
||
|
/*
|
||
|
* GetRevCurve
|
||
|
* function:
|
||
|
* prototype:
|
||
|
* BOOL GetRevCurve(
|
||
|
* MEMPTR Buff,
|
||
|
* MEMPTR lpRevCurve)
|
||
|
* parameters:
|
||
|
* Buff --
|
||
|
* lpRevCurve --
|
||
|
* returns:
|
||
|
* BOOL -- TRUE: successful,
|
||
|
* FALSE: otherwise.
|
||
|
*/
|
||
|
|
||
|
BOOL
|
||
|
GetRevCurve(MEMPTR lpBuff, MEMPTR lpCurve, MEMPTR lpRevCurve)
|
||
|
{
|
||
|
SINT i, j, nCount;
|
||
|
MEMPTR lpTable;
|
||
|
PUSHORT lpInput, lpOutput;
|
||
|
SFLOAT fTemp;
|
||
|
SINT iBegin, iEnd, iTemp;
|
||
|
nCount = ui32toSINT(((lpcpCurveType)lpBuff)->curve.count);
|
||
|
lpTable = (MEMPTR)(((lpcpCurveType)lpBuff)->curve.data);
|
||
|
lpOutput = (PUSHORT)lpRevCurve;
|
||
|
lpInput = (PUSHORT)lpCurve;
|
||
|
|
||
|
for (i = 0; i < nCount; i++) {
|
||
|
lpInput[i] = (USHORT)(ui16toSINT(lpTable));
|
||
|
lpTable += sizeof(icUInt16Number);
|
||
|
}
|
||
|
|
||
|
j = nCount * REVCURVE_RATIO;
|
||
|
for (i = 0; i < j; i++) {
|
||
|
fTemp = (SFLOAT)i * 65535 / (j - 1);
|
||
|
lpOutput[i] = (fTemp < 65535) ? (USHORT)fTemp : (USHORT)65535;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < j; i++) {
|
||
|
iBegin = 0;
|
||
|
iEnd = nCount - 1;
|
||
|
for (;;) {
|
||
|
if ((iEnd - iBegin) <= 1)
|
||
|
break;
|
||
|
iTemp = (iEnd + iBegin) / 2;
|
||
|
if (lpOutput[i] < lpInput[iTemp])
|
||
|
iEnd = iTemp;
|
||
|
else
|
||
|
iBegin = iTemp;
|
||
|
}
|
||
|
if (lpOutput[i] <= lpInput[iBegin])
|
||
|
fTemp = (SFLOAT)iBegin;
|
||
|
else if (lpOutput[i] >= lpInput[iEnd])
|
||
|
fTemp = (SFLOAT)iEnd;
|
||
|
else {
|
||
|
fTemp = ((SFLOAT)(lpInput[iEnd] - lpOutput[i])) /
|
||
|
(lpOutput[i] - lpInput[iBegin]);
|
||
|
fTemp = (iBegin * fTemp + iEnd) / (fTemp + 1);
|
||
|
}
|
||
|
fTemp = (fTemp / (nCount - 1)) * 65535;
|
||
|
lpOutput[i] = (fTemp < 65535) ? (USHORT)fTemp : (USHORT)65535;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
/*
|
||
|
* CreateMonoCRD
|
||
|
* function:
|
||
|
* this is the function which creates the Color Rendering Dictionary (CRD)
|
||
|
* from the data supplied in the GrayTRC tag.
|
||
|
* prototype:
|
||
|
* BOOL EXTERN CreateMonoCRD(
|
||
|
* CHANDLE cp,
|
||
|
* SINT Index,
|
||
|
* MEMPTR lpMem)
|
||
|
* parameters:
|
||
|
* cp -- Color Profile handle
|
||
|
* Index -- Index of the tag
|
||
|
* lpMem -- Pointer to the memory block
|
||
|
* returns:
|
||
|
* SINT -- !=0 if the function was successful,
|
||
|
* 0 otherwise.
|
||
|
* Returns number of bytes required/transferred
|
||
|
*/
|
||
|
// According to the spec this tag-based function only converts from
|
||
|
// Device to PCS, so we need to create an inverse function to perform
|
||
|
// PCS->device conversion. By definition the CRD is only
|
||
|
// for XYZ->DeviceRGB/CMYK conversion.
|
||
|
SINT EXTERN
|
||
|
CreateMonoCRD(CHANDLE cp, SINT Index, MEMPTR lpMem, DWORD InputIntent)
|
||
|
{
|
||
|
SINT nCount;
|
||
|
CSIG Tag, PCS;
|
||
|
|
||
|
MEMPTR Buff = NULL;
|
||
|
SINT MemSize = 0;
|
||
|
MEMPTR lpOldMem = lpMem;
|
||
|
MEMPTR lpCurve, lpRevCurve;
|
||
|
HGLOBAL hRevCurve;
|
||
|
SINT Ret = 0;
|
||
|
HGLOBAL hMem;
|
||
|
SINT i;
|
||
|
MEMPTR lpTable;
|
||
|
SFLOAT IlluminantWP[3];
|
||
|
SFLOAT MediaWP[3];
|
||
|
MEMPTR lpLineStart;
|
||
|
// Check if we can generate the CRD
|
||
|
if (!GetCPElementType(cp, Index, (LPCSIG)& Tag) ||
|
||
|
(Tag != icSigCurveType) ||
|
||
|
!GetCPConnSpace(cp, (LPCSIG)& PCS) ||
|
||
|
!GetCPElementSize(cp, Index, (LPSINT)& MemSize) ||
|
||
|
!MemAlloc(MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR)& Buff) ||
|
||
|
!GetCPElement(cp, Index, Buff, MemSize)) {
|
||
|
if (NULL != Buff) {
|
||
|
MemFree(hMem);
|
||
|
}
|
||
|
return (0);
|
||
|
}
|
||
|
nCount = ui32toSINT(((lpcpCurveType)Buff)->curve.count);
|
||
|
|
||
|
// Estimate the memory size required to hold CRD
|
||
|
// SRGB98
|
||
|
Ret = nCount * 6 * REVCURVE_RATIO + // Number of INT elements
|
||
|
2048; // + other PS stuff
|
||
|
if (lpMem == NULL) // This is a size request
|
||
|
{
|
||
|
MemFree(hMem);
|
||
|
return (Ret);
|
||
|
}
|
||
|
if (!MemAlloc(nCount * 2 * (REVCURVE_RATIO + 1),
|
||
|
(HGLOBAL FAR *) &hRevCurve, (LPMEMPTR)& lpRevCurve)) {
|
||
|
MemFree(hMem);
|
||
|
return (FALSE);
|
||
|
}
|
||
|
lpCurve = lpRevCurve + 2 * REVCURVE_RATIO * nCount;
|
||
|
GetRevCurve(Buff, lpCurve, lpRevCurve);
|
||
|
|
||
|
// GetCPCMMType (cp, (LPCSIG) & Intent); // Get Intent
|
||
|
GetCPWhitePoint(cp, (LPSFLOAT)& IlluminantWP); // .. Illuminant
|
||
|
|
||
|
// Support absolute whitePoint
|
||
|
if (InputIntent == icAbsoluteColorimetric) {
|
||
|
if (!GetCPMediaWhitePoint(cp, (LPSFLOAT)& MediaWP)) // .. Media WhitePoint
|
||
|
{
|
||
|
MediaWP[0] = IlluminantWP[0];
|
||
|
MediaWP[1] = IlluminantWP[1];
|
||
|
MediaWP[2] = IlluminantWP[2];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//************* Start writing CRD ****************************
|
||
|
lpMem += WriteNewLineObject(lpMem, BeginDict); // Begin dictionary
|
||
|
lpMem += WriteObject(lpMem, DictType); // Dictionary type
|
||
|
|
||
|
lpMem += WriteNewLineObject(lpMem, IntentType); // RenderingIntent
|
||
|
switch (InputIntent) {
|
||
|
case icPerceptual:
|
||
|
lpMem += WriteObject(lpMem, IntentPer);
|
||
|
break;
|
||
|
|
||
|
case icSaturation:
|
||
|
lpMem += WriteObject(lpMem, IntentSat);
|
||
|
break;
|
||
|
|
||
|
case icRelativeColorimetric:
|
||
|
lpMem += WriteObject(lpMem, IntentRCol);
|
||
|
break;
|
||
|
|
||
|
case icAbsoluteColorimetric:
|
||
|
lpMem += WriteObject(lpMem, IntentACol);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//********** Send Black/White Point.
|
||
|
lpMem += SendCRDBWPoint(lpMem, IlluminantWP);
|
||
|
|
||
|
//********** /TransformPQR
|
||
|
lpMem += SendCRDPQR(lpMem, InputIntent, IlluminantWP);
|
||
|
|
||
|
//********** /MatrixLMN
|
||
|
lpMem += SendCRDLMN(lpMem, InputIntent, IlluminantWP, MediaWP, PCS);
|
||
|
|
||
|
//********** /MatrixABC
|
||
|
if (PCS == icSigXYZData) { // Switch ABC to BAC, since we want to output B which is converted from Y.
|
||
|
lpMem += WriteNewLineObject(lpMem, MatrixABCTag);
|
||
|
lpMem += WriteObject(lpMem, MatrixABCXYZCRD);
|
||
|
} else if (PCS == icSigLabData) {
|
||
|
lpMem += WriteNewLineObject(lpMem, MatrixABCTag);
|
||
|
lpMem += WriteObject(lpMem, MatrixABCLabCRD);
|
||
|
}
|
||
|
//********** /EncodeABC
|
||
|
if (nCount != 0) {
|
||
|
lpMem += WriteObject(lpMem, NewLine);
|
||
|
lpLineStart = lpMem;
|
||
|
lpMem += WriteObject(lpMem, EncodeABCTag);
|
||
|
lpMem += WriteObject(lpMem, BeginArray);
|
||
|
lpMem += WriteObject(lpMem, BeginFunction);
|
||
|
if (nCount == 1) // Gamma supplied in ui16 format
|
||
|
{
|
||
|
lpTable = (MEMPTR)(((lpcpCurveType)Buff)->curve.data);
|
||
|
lpMem += WriteInt(lpMem, ui16toSINT(lpTable));
|
||
|
lpMem += WriteObject(lpMem, DecodeA3Rev);
|
||
|
} else {
|
||
|
if (PCS == icSigLabData) {
|
||
|
lpMem += WriteObject(lpMem, EncodeABCLab1);
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, StartClip);
|
||
|
lpMem += WriteObject(lpMem, BeginArray);
|
||
|
for (i = 0; i < nCount * REVCURVE_RATIO; i++) {
|
||
|
lpMem += WriteInt(lpMem, (SINT)(*((PUSHORT)lpRevCurve)));
|
||
|
lpRevCurve += sizeof(icUInt16Number);
|
||
|
if (((SINT)(lpMem - lpLineStart)) > MAX_LINELENG) {
|
||
|
lpLineStart = lpMem;
|
||
|
lpMem += WriteObject(lpMem, NewLine);
|
||
|
}
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, EndArray);
|
||
|
lpLineStart = lpMem;
|
||
|
lpMem += WriteNewLineObject(lpMem, IndexArray);
|
||
|
lpMem += WriteObject(lpMem, Scale16);
|
||
|
lpMem += WriteObject(lpMem, EndClip);
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, EndFunction);
|
||
|
lpMem += WriteObject(lpMem, DupOp);
|
||
|
lpMem += WriteObject(lpMem, DupOp);
|
||
|
lpMem += WriteObject(lpMem, EndArray);
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, EndDict); // End dictionary definition
|
||
|
|
||
|
MemFree(hRevCurve);
|
||
|
MemFree(hMem);
|
||
|
return ((SINT)((unsigned long)(lpMem - lpOldMem)));
|
||
|
}
|
||
|
|
||
|
// SRGB98 start
|
||
|
BOOL
|
||
|
GetTRCElementSize(CHANDLE cp, CSIG icSigXTRCTag, LPSINT pIndex, LPSINT pTRCSize)
|
||
|
{
|
||
|
CSIG Tag;
|
||
|
|
||
|
if (!GetCPTagIndex(cp, icSigXTRCTag, (LPSINT)pIndex) ||
|
||
|
!GetCPElementType(cp, *pIndex, (LPCSIG)& Tag) ||
|
||
|
!(Tag == icSigCurveType) ||
|
||
|
!GetCPElementSize(cp, *pIndex, (LPSINT)pTRCSize)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
DoesTRCAndColorantTagExist(CHANDLE cp)
|
||
|
{
|
||
|
if (DoesCPTagExist(cp, icSigRedColorantTag) &&
|
||
|
DoesCPTagExist(cp, icSigRedTRCTag) &&
|
||
|
DoesCPTagExist(cp, icSigGreenColorantTag) &&
|
||
|
DoesCPTagExist(cp, icSigGreenTRCTag) &&
|
||
|
DoesCPTagExist(cp, icSigBlueColorantTag) &&
|
||
|
DoesCPTagExist(cp, icSigBlueTRCTag)) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static SINT
|
||
|
CreateRevArray(CHANDLE cp, MEMPTR lpMem, MEMPTR lpBuff,
|
||
|
MEMPTR lpRevCurve, CSIG CPTag, BOOL AllowBinary)
|
||
|
{
|
||
|
SINT i, nCount;
|
||
|
SINT MemSize = 0;
|
||
|
MEMPTR lpOldMem, lpLineStart;
|
||
|
MEMPTR lpCurve;
|
||
|
|
||
|
lpOldMem = lpMem;
|
||
|
|
||
|
lpLineStart = lpMem;
|
||
|
nCount = ui32toSINT(((lpcpCurveType)lpBuff)->curve.count);
|
||
|
if (nCount > 1) {
|
||
|
lpMem += WriteNewLineObject(lpMem, Slash);
|
||
|
lpMem += WriteObject(lpMem, InputArray);
|
||
|
lpMem += WriteInt(lpMem, (SINT)CPTag);
|
||
|
|
||
|
lpCurve = lpRevCurve + 2 * REVCURVE_RATIO * nCount;
|
||
|
GetRevCurve(lpBuff, lpCurve, lpRevCurve);
|
||
|
|
||
|
if (!AllowBinary) // Output ASCII DATA
|
||
|
{
|
||
|
lpMem += WriteObject(lpMem, BeginArray);
|
||
|
for (i = 0; i < nCount * REVCURVE_RATIO; i++) {
|
||
|
lpMem += WriteInt(lpMem, (SINT)(*((PUSHORT)lpRevCurve)));
|
||
|
lpRevCurve += sizeof(icUInt16Number);
|
||
|
if (((SINT)(lpMem - lpLineStart)) > MAX_LINELENG) {
|
||
|
lpLineStart = lpMem;
|
||
|
lpMem += WriteObject(lpMem, NewLine);
|
||
|
}
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, EndArray);
|
||
|
} else { // Output BINARY DATA
|
||
|
lpMem += WriteHNAToken(lpMem, 149, nCount);
|
||
|
lpMem += WriteIntStringU2S_L(lpMem, lpRevCurve, nCount);
|
||
|
}
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, DefOp);
|
||
|
return ((SINT)(lpMem - lpOldMem));
|
||
|
}
|
||
|
|
||
|
static SINT
|
||
|
SendRevArray(CHANDLE cp, MEMPTR lpMem, MEMPTR lpBuff,
|
||
|
CSIG CPTag, BOOL AllowBinary)
|
||
|
{
|
||
|
SINT nCount;
|
||
|
MEMPTR lpOldMem;
|
||
|
MEMPTR lpTable;
|
||
|
|
||
|
lpOldMem = lpMem;
|
||
|
lpMem += WriteObject(lpMem, BeginFunction);
|
||
|
nCount = ui32toSINT(((lpcpCurveType)lpBuff)->curve.count);
|
||
|
if (nCount != 0) {
|
||
|
if (nCount == 1) // Gamma supplied in ui16 format
|
||
|
{
|
||
|
lpTable = (MEMPTR)(((lpcpCurveType)lpBuff)->curve.data);
|
||
|
lpMem += WriteInt(lpMem, ui16toSINT(lpTable));
|
||
|
lpMem += WriteObject(lpMem, DecodeA3Rev);
|
||
|
} else {
|
||
|
lpMem += WriteObject(lpMem, StartClip);
|
||
|
lpMem += WriteObject(lpMem, InputArray);
|
||
|
lpMem += WriteInt(lpMem, (SINT)CPTag);
|
||
|
|
||
|
if (!AllowBinary) // Output ASCII CS
|
||
|
{
|
||
|
lpMem += WriteObject(lpMem, IndexArray);
|
||
|
} else { // Output BINARY CS
|
||
|
lpMem += WriteObject(lpMem, IndexArray16b);
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, Scale16);
|
||
|
lpMem += WriteObject(lpMem, EndClip);
|
||
|
}
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, EndFunction);
|
||
|
return ((SINT)(lpMem - lpOldMem));
|
||
|
}
|
||
|
|
||
|
SINT
|
||
|
CreateColorantArray(CHANDLE cp, double FAR *lpArray, CSIG CPTag)
|
||
|
{
|
||
|
SINT i, Index;
|
||
|
MEMPTR lpTable;
|
||
|
MEMPTR Buff = NULL;
|
||
|
SINT MemSize = 0;
|
||
|
HGLOBAL hBuff;
|
||
|
|
||
|
if (GetCPTagIndex(cp, CPTag, (LPSINT)& Index) &&
|
||
|
GetCPElementSize(cp, Index, (LPSINT)& MemSize) &&
|
||
|
MemAlloc(MemSize, (HGLOBAL FAR *)&hBuff, (LPMEMPTR)& Buff) &&
|
||
|
GetCPElement(cp, Index, Buff, MemSize)) {
|
||
|
lpTable = (MEMPTR) & (((lpcpXYZType)Buff)->data);
|
||
|
for (i = 0; i < 3; i++) {
|
||
|
*lpArray++ = (SFLOAT)si16f16toSFLOAT(lpTable);
|
||
|
lpTable += sizeof(icS15Fixed16Number);
|
||
|
}
|
||
|
MemFree(hBuff);
|
||
|
}
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* IsSRGB
|
||
|
* function: check if the profile is sRGB
|
||
|
|
||
|
* parameters:
|
||
|
* cp -- Color Profile handle
|
||
|
|
||
|
* returns:
|
||
|
* BOOL -- TRUE if the profile is sRGB
|
||
|
* FALSE otherwise.
|
||
|
*/
|
||
|
BOOL FAR IsSRGB(CHANDLE cp)
|
||
|
{
|
||
|
BOOL match = FALSE;
|
||
|
SINT RedTRCIndex, GreenTRCIndex, BlueTRCIndex, RedCIndex, GreenCIndex, BlueCIndex;
|
||
|
SINT MemSize;
|
||
|
SINT RedTRCSize = 0, GreenTRCSize = 0, BlueTRCSize = 0, RedCSize = 0, GreenCSize = 0, BlueCSize = 0;
|
||
|
HGLOBAL hMem;
|
||
|
MEMPTR lpRed = NULL, lpGreen, lpBlue, lpRedC, lpGreenC, lpBlueC;
|
||
|
DWORD crc;
|
||
|
|
||
|
if (GetCPTagIndex(cp, icSigRedTRCTag, &RedTRCIndex) &&
|
||
|
GetCPElementSize(cp, RedTRCIndex, &RedTRCSize) &&
|
||
|
|
||
|
GetCPTagIndex(cp, icSigGreenTRCTag, &GreenTRCIndex) &&
|
||
|
GetCPElementSize(cp, GreenTRCIndex, &GreenTRCSize) &&
|
||
|
|
||
|
GetCPTagIndex(cp, icSigBlueTRCTag, &BlueTRCIndex) &&
|
||
|
GetCPElementSize(cp, BlueTRCIndex, &BlueTRCSize) &&
|
||
|
|
||
|
GetCPTagIndex(cp, icSigRedColorantTag, &RedCIndex) &&
|
||
|
GetCPElementSize(cp, RedCIndex, &RedCSize) &&
|
||
|
|
||
|
GetCPTagIndex(cp, icSigGreenColorantTag, &GreenCIndex) &&
|
||
|
GetCPElementSize(cp, GreenCIndex, &GreenCSize) &&
|
||
|
|
||
|
GetCPTagIndex(cp, icSigBlueColorantTag, &BlueCIndex) &&
|
||
|
GetCPElementSize(cp, BlueCIndex, &BlueCSize)) {
|
||
|
MemSize = RedTRCSize + GreenTRCSize + BlueTRCSize + RedCSize + GreenCSize + BlueCSize;
|
||
|
|
||
|
if ((MemSize == 6240) && // #bytes in sRGBColorTags
|
||
|
MemAlloc(MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR)&lpRed)) {
|
||
|
lpGreen = lpRed + RedTRCSize;
|
||
|
lpBlue = lpGreen + GreenTRCSize;
|
||
|
lpRedC = lpBlue + BlueTRCSize;
|
||
|
lpGreenC = lpRedC + RedCSize;
|
||
|
lpBlueC = lpGreenC + GreenCSize;
|
||
|
|
||
|
if (GetCPElement(cp, RedTRCIndex, lpRed, RedTRCSize) &&
|
||
|
GetCPElement(cp, GreenTRCIndex, lpGreen, GreenTRCSize) &&
|
||
|
GetCPElement(cp, BlueTRCIndex, lpBlue, BlueTRCSize) &&
|
||
|
GetCPElement(cp, RedCIndex, lpRedC, RedCSize) &&
|
||
|
GetCPElement(cp, GreenCIndex, lpGreenC, GreenCSize) &&
|
||
|
GetCPElement(cp, BlueCIndex, lpBlueC, BlueCSize)) {
|
||
|
crc = crc32(lpRed, 6240);
|
||
|
match = (crc == SRGBCRC);
|
||
|
}
|
||
|
MemFree(hMem);
|
||
|
}
|
||
|
}
|
||
|
return (match);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* CreateMatrixCRD
|
||
|
* function:
|
||
|
* this is the function which creates the Color Rendering Dictionary (CRD)
|
||
|
* from the data supplied in the redTRC, greenTRC, blueTRA, redColorant,
|
||
|
* greenColorant and BlueColorant tags
|
||
|
* prototype:
|
||
|
* BOOL EXTERN CreateMatrixCRD(
|
||
|
* CHANDLE cp,
|
||
|
* MEMPTR lpMem,
|
||
|
* BOOL AllowBinary)
|
||
|
* parameters:
|
||
|
* cp -- Color Profile handle
|
||
|
* lpMem -- Pointer to the memory block
|
||
|
* AllowBinary --
|
||
|
* returns:
|
||
|
* SINT -- !=0 if the function was successful,
|
||
|
* 0 otherwise.
|
||
|
* Returns number of bytes required/transferred
|
||
|
*/
|
||
|
// With matrix/TRC model, only the CIEXYZ encoding of the PCS can be used.
|
||
|
// So, we don't need to worry about CIELAB.
|
||
|
SINT EXTERN
|
||
|
CreateMatrixCRD(CHANDLE cp, MEMPTR lpMem, DWORD InputIntent, BOOL AllowBinary)
|
||
|
{
|
||
|
SINT RedTRCIndex, GreenTRCIndex, BlueTRCIndex;
|
||
|
SINT i, MemSize;
|
||
|
SINT nRedCount, nGreenCount, nBlueCount;
|
||
|
MEMPTR lpRed = NULL, lpGreen, lpBlue;
|
||
|
SINT RedTRCSize = 0, GreenTRCSize = 0, BlueTRCSize = 0;
|
||
|
MEMPTR lpOldMem = lpMem;
|
||
|
MEMPTR lpRevCurve;
|
||
|
HGLOBAL hRevCurve;
|
||
|
SINT Ret = 0;
|
||
|
HGLOBAL hMem;
|
||
|
SFLOAT IlluminantWP[3];
|
||
|
double Colorant[9];
|
||
|
double RevColorant[9];
|
||
|
|
||
|
// Check if we can generate the CRD
|
||
|
if (!GetTRCElementSize(cp, icSigRedTRCTag, &RedTRCIndex, &RedTRCSize) ||
|
||
|
!GetTRCElementSize(cp, icSigGreenTRCTag, &GreenTRCIndex, &GreenTRCSize) ||
|
||
|
!GetTRCElementSize(cp, icSigBlueTRCTag, &BlueTRCIndex, &BlueTRCSize)) {
|
||
|
return 0;
|
||
|
}
|
||
|
MemSize = RedTRCSize + GreenTRCSize + BlueTRCSize;
|
||
|
if (!MemAlloc(MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR)& lpRed))
|
||
|
return 0;
|
||
|
|
||
|
lpGreen = lpRed + RedTRCSize;
|
||
|
lpBlue = lpGreen + GreenTRCSize;
|
||
|
if (!GetCPElement(cp, RedTRCIndex, lpRed, RedTRCSize) ||
|
||
|
!GetCPElement(cp, GreenTRCIndex, lpGreen, GreenTRCSize) ||
|
||
|
!GetCPElement(cp, BlueTRCIndex, lpBlue, BlueTRCSize)) {
|
||
|
MemFree(hMem);
|
||
|
return (0);
|
||
|
}
|
||
|
nRedCount = ui32toSINT(((lpcpCurveType)lpRed)->curve.count);
|
||
|
nGreenCount = ui32toSINT(((lpcpCurveType)lpGreen)->curve.count);
|
||
|
nBlueCount = ui32toSINT(((lpcpCurveType)lpBlue)->curve.count);
|
||
|
|
||
|
// Estimate the memory size required to hold CRD
|
||
|
Ret = (nRedCount + nGreenCount + nBlueCount) * 6 * REVCURVE_RATIO +
|
||
|
2048; // Number of INT elements + other PS stuff
|
||
|
if (lpMem == NULL) // This is a size request
|
||
|
{
|
||
|
MemFree(hMem);
|
||
|
return (Ret);
|
||
|
}
|
||
|
|
||
|
if (!MemAlloc(nRedCount * 2 * (REVCURVE_RATIO + 1),
|
||
|
(HGLOBAL FAR *) &hRevCurve, (LPMEMPTR)& lpRevCurve)) {
|
||
|
MemFree(hMem);
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
if (IsSRGB(cp)) {
|
||
|
lpMem += WriteNewLineObject(lpMem, CRDBegin);
|
||
|
lpMem += WriteNewLineObject(lpMem, BeginDict); // Begin dictionary
|
||
|
lpMem += WriteObject(lpMem, DictType); // Dictionary type
|
||
|
lpMem += WriteNewLineObject(lpMem, IntentType); // RenderingIntent
|
||
|
switch (InputIntent) {
|
||
|
case icPerceptual:
|
||
|
lpMem += WriteObject(lpMem, IntentPer);
|
||
|
break;
|
||
|
|
||
|
case icSaturation:
|
||
|
lpMem += WriteObject(lpMem, IntentSat);
|
||
|
break;
|
||
|
|
||
|
case icRelativeColorimetric:
|
||
|
lpMem += WriteObject(lpMem, IntentRCol);
|
||
|
break;
|
||
|
|
||
|
case icAbsoluteColorimetric:
|
||
|
lpMem += WriteObject(lpMem, IntentACol);
|
||
|
break;
|
||
|
}
|
||
|
lpMem += WriteNewLineObject(lpMem, AdobeCRD);
|
||
|
lpMem += WriteNewLineObject(lpMem, CRDEnd);
|
||
|
} else {
|
||
|
lpMem += EnableGlobalDict(lpMem);
|
||
|
lpMem += BeginGlobalDict(lpMem);
|
||
|
|
||
|
lpMem += CreateRevArray(cp, lpMem, lpRed, lpRevCurve, icSigRedTRCTag, AllowBinary);
|
||
|
lpMem += CreateRevArray(cp, lpMem, lpGreen, lpRevCurve, icSigGreenTRCTag, AllowBinary);
|
||
|
lpMem += CreateRevArray(cp, lpMem, lpBlue, lpRevCurve, icSigBlueTRCTag, AllowBinary);
|
||
|
|
||
|
lpMem += EndGlobalDict(lpMem);
|
||
|
|
||
|
// GetCPCMMType (cp, (LPCSIG) & Intent); // Get Intent
|
||
|
GetCPWhitePoint(cp, (LPSFLOAT)& IlluminantWP); // .. Illuminant
|
||
|
|
||
|
//************* Start writing CRD ****************************
|
||
|
lpMem += WriteNewLineObject(lpMem, CRDBegin);
|
||
|
|
||
|
lpMem += WriteNewLineObject(lpMem, BeginDict); // Begin dictionary
|
||
|
lpMem += WriteObject(lpMem, DictType); // Dictionary type
|
||
|
|
||
|
lpMem += WriteNewLineObject(lpMem, IntentType); // RenderingIntent
|
||
|
switch (InputIntent) {
|
||
|
case icPerceptual:
|
||
|
lpMem += WriteObject(lpMem, IntentPer);
|
||
|
break;
|
||
|
|
||
|
case icSaturation:
|
||
|
lpMem += WriteObject(lpMem, IntentSat);
|
||
|
break;
|
||
|
|
||
|
case icRelativeColorimetric:
|
||
|
lpMem += WriteObject(lpMem, IntentRCol);
|
||
|
break;
|
||
|
|
||
|
case icAbsoluteColorimetric:
|
||
|
lpMem += WriteObject(lpMem, IntentACol);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//********** Send Black/White Point.
|
||
|
lpMem += SendCRDBWPoint(lpMem, IlluminantWP);
|
||
|
|
||
|
//********** /TransformPQR
|
||
|
lpMem += SendCRDPQR(lpMem, InputIntent, IlluminantWP);
|
||
|
|
||
|
//********** /MatrixLMN
|
||
|
CreateColorantArray(cp, &Colorant[0], icSigRedColorantTag);
|
||
|
CreateColorantArray(cp, &Colorant[3], icSigGreenColorantTag);
|
||
|
CreateColorantArray(cp, &Colorant[6], icSigBlueColorantTag);
|
||
|
InvertMatrix(Colorant, RevColorant);
|
||
|
|
||
|
lpMem += WriteNewLineObject(lpMem, MatrixLMNTag);
|
||
|
|
||
|
lpMem += WriteObject(lpMem, BeginArray);
|
||
|
for (i = 0; i < 9; i++) {
|
||
|
lpMem += WriteFloat(lpMem, (SFLOAT)RevColorant[i]);
|
||
|
}
|
||
|
lpMem += WriteObject(lpMem, EndArray);
|
||
|
|
||
|
//********** /EncodeABC
|
||
|
lpMem += WriteNewLineObject(lpMem, EncodeABCTag);
|
||
|
lpMem += WriteObject(lpMem, BeginArray);
|
||
|
|
||
|
lpMem += WriteObject(lpMem, NewLine);
|
||
|
lpMem += SendRevArray(cp, lpMem, lpRed, icSigRedTRCTag, AllowBinary);
|
||
|
lpMem += WriteObject(lpMem, NewLine);
|
||
|
lpMem += SendRevArray(cp, lpMem, lpGreen, icSigGreenTRCTag, AllowBinary);
|
||
|
lpMem += WriteObject(lpMem, NewLine);
|
||
|
lpMem += SendRevArray(cp, lpMem, lpBlue, icSigBlueTRCTag, AllowBinary);
|
||
|
lpMem += WriteNewLineObject(lpMem, EndArray);
|
||
|
|
||
|
lpMem += WriteObject(lpMem, EndDict); // End dictionary definition
|
||
|
|
||
|
lpMem += WriteNewLineObject(lpMem, CRDEnd);
|
||
|
}
|
||
|
MemFree(hRevCurve);
|
||
|
MemFree(hMem);
|
||
|
return ((SINT)((unsigned long)(lpMem - lpOldMem)));
|
||
|
}
|
||
|
// SRGB98 End
|
||
|
|
||
|
BOOL EXTERN
|
||
|
GetPS2ColorRenderingDictionary(
|
||
|
CHANDLE cp,
|
||
|
DWORD Intent,
|
||
|
MEMPTR lpMem,
|
||
|
LPDWORD lpcbSize,
|
||
|
BOOL AllowBinary)
|
||
|
{
|
||
|
SINT Index;
|
||
|
SINT Ret, Size;
|
||
|
CSIG icSigPs2CRDx, icSigBToAx;
|
||
|
|
||
|
if (!cp)
|
||
|
return FALSE;
|
||
|
|
||
|
if ((lpMem == NULL) || (*lpcbSize == 0)) {
|
||
|
lpMem = NULL;
|
||
|
*lpcbSize = 0;
|
||
|
}
|
||
|
Ret = 0;
|
||
|
Size = (SINT)* lpcbSize;
|
||
|
|
||
|
switch (Intent) {
|
||
|
case icPerceptual:
|
||
|
icSigPs2CRDx = icSigPs2CRD0Tag;
|
||
|
icSigBToAx = icSigBToA0Tag;
|
||
|
break;
|
||
|
|
||
|
case icRelativeColorimetric:
|
||
|
icSigPs2CRDx = icSigPs2CRD1Tag;
|
||
|
icSigBToAx = icSigBToA1Tag;
|
||
|
break;
|
||
|
|
||
|
case icSaturation:
|
||
|
icSigPs2CRDx = icSigPs2CRD2Tag;
|
||
|
icSigBToAx = icSigBToA2Tag;
|
||
|
break;
|
||
|
|
||
|
case icAbsoluteColorimetric:
|
||
|
icSigPs2CRDx = icSigPs2CRD3Tag;
|
||
|
icSigBToAx = icSigBToA1Tag;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
*lpcbSize = (DWORD)Ret;
|
||
|
return (Ret > 0);
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
(DoesCPTagExist(cp, icSigPs2CRDx) &&
|
||
|
GetCPTagIndex(cp, icSigPs2CRDx, (LPSINT)& Index) &&
|
||
|
GetCPElementDataSize(cp, Index, (LPSINT)& Ret) &&
|
||
|
((Size == 0) ||
|
||
|
GetCPElementData(cp, Index, lpMem, Size)) &&
|
||
|
(Ret = Convert2Ascii(cp, Index, lpMem, Size, Ret, AllowBinary))
|
||
|
) ||
|
||
|
(DoesCPTagExist(cp, icSigBToAx) &&
|
||
|
GetCPTagIndex(cp, icSigBToAx, (LPSINT)& Index) &&
|
||
|
(Ret = CreateLutCRD(cp, Index, lpMem, Intent, AllowBinary))
|
||
|
) ||
|
||
|
// SRGB98 Support Windows 98 sRGB icc profile.
|
||
|
// Create CRD from TRC and Colorant Tags.
|
||
|
(DoesTRCAndColorantTagExist(cp) &&
|
||
|
(Ret = CreateMatrixCRD(cp, lpMem, Intent, AllowBinary))
|
||
|
) ||
|
||
|
(DoesCPTagExist(cp, icSigGrayTRCTag) &&
|
||
|
GetCPTagIndex(cp, icSigGrayTRCTag, (LPSINT)& Index) &&
|
||
|
(Ret = CreateMonoCRD(cp, Index, lpMem, Intent))
|
||
|
)
|
||
|
) {
|
||
|
}
|
||
|
|
||
|
*lpcbSize = (DWORD)Ret;
|
||
|
return (Ret > 0);
|
||
|
}
|