Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

5154 lines
146 KiB

/*++
Copyright (c) 1990-1991 Microsoft Corporation
Module Name:
htmapclr.c
Abstract:
This module contains low levels functions which map the input color to
the dyes' densities.
Author:
29-Jan-1991 Tue 10:28:20 created -by- Daniel Chou (danielc)
[Environment:]
GDI Device Driver - Halftone.
[Notes:]
1. In the near future we will also allowed the XYZ/LAB to be specified in
the color table
Revision History:
--*/
#define DBGP_VARNAME dbgpHTMapClr
#include "htp.h"
#include "htmapclr.h"
#include "htrender.h"
#include "htmath.h"
#include "htapi.h"
#define DBGP_SHOWXFORM_RGB 0x0001
#define DBGP_SHOWXFORM_ALL 0x0002
#define DBGP_CIEMATRIX 0x0004
#define DBGP_CSXFORM 0x0008
#define DBGP_CCT 0x0010
#define DBGP_DYE_CORRECT 0x0020
#define DBGP_HCA 0x0040
#define DBGP_PRIMARY_ORDER 0x0080
#define DBGP_CACHED_GAMMA 0x0100
#define DBGP_BFINFO 0x0200
#define DBGP_BFINFO_TABLE 0x0400
#define DBGP_CHKNONWHITE 0x0800
#define DBGP_SCALE_RGB 0x1000
#define DBGP_MONO_PRIM 0x2000
#define DBGP_SUB_ADJ 0x4000
DEF_DBGPVAR(BIT_IF(DBGP_SHOWXFORM_RGB, 0) |
BIT_IF(DBGP_SHOWXFORM_ALL, 0) |
BIT_IF(DBGP_CIEMATRIX, 0) |
BIT_IF(DBGP_CSXFORM, 0) |
BIT_IF(DBGP_CCT, 0) |
BIT_IF(DBGP_DYE_CORRECT, 0) |
BIT_IF(DBGP_HCA, 0) |
BIT_IF(DBGP_PRIMARY_ORDER, 0) |
BIT_IF(DBGP_CACHED_GAMMA, 0) |
BIT_IF(DBGP_BFINFO, 0) |
BIT_IF(DBGP_BFINFO_TABLE, 0) |
BIT_IF(DBGP_CHKNONWHITE, 0) |
BIT_IF(DBGP_SCALE_RGB, 0) |
BIT_IF(DBGP_MONO_PRIM, 0) |
BIT_IF(DBGP_SUB_ADJ, 0))
extern FD6 L2I_16bpp555[];
extern FD6 L2I_VGA256Mono[];
extern HTCOLORADJUSTMENT DefaultCA;
MATRIX3x3 YIQToRGB = {
FD6_1, (FD6)955700, (FD6)619900,
FD6_1, (FD6)-271600, (FD6)-646900,
FD6_1, (FD6)-1108200,(FD6)1705100
};
#define FD6_p25 (FD6_5 / 2)
#define FD6_p75 (FD6_p25 * 3)
#define JND_ADJ(j,x) RaisePower((j), (FD6)(x), RPF_INTEXP)
#define FD6_p1125 (FD6)112500
#define FD6_p225 (FD6)225000
#define FD6_p325 (FD6)325000
#define FD6_p55 (FD6)550000
#define FD6_p775 (FD6)775000
//
// Assume that screen for vga 16 color devices has gamma 2.0
//
#define VGA16_SCALE(w, m, l, h) (BYTE)((FD6xL((w-l),m)+((h-l)/2))/(h-l))
#define VGA16_00h FD6_0
#define VGA16_ffh FD6_1
#define _SCALE_VGA16MONO(w,l,h,m) (BYTE)((FD6xL(((w)-l),m)+((h-l)>>1))/(h-l))
#define GET_VGA16MONO_00h(w,m) _SCALE_VGA16MONO(w,VGA16_00h,VGA16_80h,m)
#define GET_VGA16MONO_80h(w,m) _SCALE_VGA16MONO(w,VGA16_80h,VGA16_c0h,m)
#define GET_VGA16MONO_c0h(w,m) _SCALE_VGA16MONO(w,VGA16_c0h,VGA16_ffh,m)
BYTE VGA256_BCubeIdx[] = { VGA256_B_CUBE_INC * 0,
VGA256_B_CUBE_INC * 1,
VGA256_B_CUBE_INC * 2,
VGA256_B_CUBE_INC * 3,
VGA256_B_CUBE_INC * 4,
VGA256_B_CUBE_INC * 5,
VGA256_B_CUBE_INC * 6,
VGA256_B_CUBE_INC * 7 };
BYTE VGA256_GCubeIdx[] = { VGA256_G_CUBE_INC * 0,
VGA256_G_CUBE_INC * 1,
VGA256_G_CUBE_INC * 2,
VGA256_G_CUBE_INC * 3,
VGA256_G_CUBE_INC * 4,
VGA256_G_CUBE_INC * 5,
VGA256_G_CUBE_INC * 6,
VGA256_G_CUBE_INC * 7 };
FD6 SinNumber[] = {
0, 17452, 34899, 52336, 69756, // 0
87156, 104528, 121869, 139173, 156434, // 5.0
173648, 190809, 207912, 224951, 241922, // 10
258819, 275637, 292372, 309017, 325568, // 15.0
342020, 358368, 374607, 390731, 406737, // 20
422618, 438371, 453990, 469472, 484810, // 25.0
500000, 515038, 529919, 544639, 559193, // 30
573576, 587785, 601815, 615661, 629320, // 35.0
642788, 656059, 669131, 681998, 694658, // 40
707107, 719340, 731354, 743145, 754710, // 45.0
766044, 777146, 788011, 798636, 809017, // 50
819152, 829038, 838671, 848048, 857167, // 55.0
866025, 874620, 882948, 891007, 898794, // 60
906308, 913545, 920505, 927184, 933580, // 65.0
939693, 945519, 951057, 956305, 961262, // 70
965926, 970296, 974370, 978148, 981627, // 75.0
984808, 987688, 990268, 992546, 994522, // 80
996195, 997564, 998630, 999391, 999848, // 85.0
1000000
};
#define CLAMP_0(x) if ((x) < FD6_0) { (x) = FD6_0; }
#define CLAMP_1(x) if ((x) > FD6_1) { (x) = FD6_1; }
#define CLAMP_01(x) CLAMP_0(x) else CLAMP_1(x)
#define CLAMP_PRIMS_0(a,b,c) CLAMP_0(a); CLAMP_0(b); CLAMP_0(c)
#define CLAMP_PRIMS_1(a,b,c) CLAMP_1(a); CLAMP_1(b); CLAMP_1(c)
#define CLAMP_PRIMS_01(a,b,c) CLAMP_01(a); CLAMP_01(b); CLAMP_01(c)
#define SCALE_PRIMS_01(s,a,b,c) MAX_OF_3(s,a,b,c); \
if ((s) > FD6_1) { \
CLAMP_PRIMS_0(a,b,c); \
(a) = DivFD6((a), (s)); \
(b) = DivFD6((b), (s)); \
(c) = DivFD6((c), (s)); \
}
FD6 LogFilterMax = 0;
#define LOG_FILTER_RATIO 7
#define PRIM_LOG_RATIO(p) Log(FD6xL((p), LOG_FILTER_RATIO) + FD6_1)
#define PRIM_CONTRAST(p,adj) (p)=MulFD6((p), (adj).Contrast)
#define PRIM_BRIGHTNESS(p,adj) (p)+=((adj).Brightness)
#define PRIM_COLORFULNESS(a,b,adj) (a)=MulFD6((a),(adj).Color); \
(b)=MulFD6((b),(adj).Color)
#define PRIM_TINT(a,b,t,adj) (t)=(a); \
(a)=MulFD6((a),(adj).TintCosAngle) - \
MulFD6((b),(adj).TintSinAngle); \
(b)=MulFD6((t),(adj).TintSinAngle) + \
MulFD6((b),(adj).TintCosAngle)
#define PRIM_LOG_FILTER(p) (p)=DivFD6(PRIM_LOG_RATIO(p), LogFilterMax)
#define PRIM_BW_ADJ(p,adj) (p)=DivFD6((p)-(adj).MinL, (adj).RangeL)
#define COMP_CA(pca1,pca2) CompareMemory((LPBYTE)(pca1), \
(LPBYTE)(pca2), \
sizeof(HTCOLORADJUSTMENT))
#define ADJ_CA(a,min,max) if (a < min) { a = min; } else \
if (a > max) { a = max; }
#define ADJ_CHECKSUM(c, f) (c) = ComputeChecksum((LPBYTE)&(PrimAdj.f), \
(c), \
sizeof(PrimAdj.f))
#define PRIM_SUBADJ(p,g) (p)=Power((p),(g))
#define NO_NEGATIVE_RGB_SCALE 1
#if NO_NEGATIVE_RGB_SCALE
#define SCALE_PRIM_RGB(pPrim,py) ScaleRGB((pPrim))
#else
#define SCALE_PRIM_RGB(pPrim,py) ScaleRGB((pPrim), (py))
#endif
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// The following macros used in Color space transform functions, these macros
// are used to compute CIELAB X/Xw, Y/Yw, Z/Zw when its values is less
// than 0.008856
//
// 1/3
// fX = (X/RefXw) - (16/116) (X/RefXw) > 0.008856
// fX = 7.787 x (X/RefXw) (X/RefXw) <= 0.008856
//
// 1/3
// fY = (Y/RefYw) - (16/116) (Y/RefYw) > 0.008856
// fY = 7.787 x (Y/RefYw) (Y/RefYw) <= 0.008856
//
// 1/3
// fZ = (Z/RefZw) - (16/116) (Z/RefZw) > 0.008856
// fZ = 7.787 x (Z/RefZw) (Z/RefZw) <= 0.008856
//
//
// 1/3
// Thresholds at 0.008856 - (16/116) = 0.068962
// 7.787 x 0.008856 = 0.068962
//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define NORM_XYZ(xyz, w) (FD6)(((w)==FD6_1) ? (xyz) : DivFD6((xyz), (w)))
#define fXYZFromXYZ(f,n,w) (f) = ((((f)=NORM_XYZ((n),(w))) >= FD6_p008856) ? \
(CubeRoot((f))) : \
(MulFD6((f), FD6_7p787) + FD6_16Div116))
#define XYZFromfXYZ(n,f,w) (n)=((f)>(FD6)206893) ? \
(Cube((f))) : \
(DivFD6((f) - FD6_16Div116, FD6_7p787)); \
if ((w)!=FD6_1) { (n)=MulFD6((n),(w)); }
//
// Following #defines are used in ComputeColorSpaceXForm, XFormRGB_XYZ_UCS()
// and XFormUCS_XYZ_RGB() functions for easy referenced.
//
#define CSX_AUw(XForm) XForm.AUw
#define CSX_BVw(XForm) XForm.BVw
#define CSX_RefXw(XForm) XForm.WhiteXYZ.X
#define CSX_RefYw(XForm) FD6_1
#define CSX_RefZw(XForm) XForm.WhiteXYZ.Z
#define iAw CSX_AUw(DevClrAdj.PrimAdj.rgbCSXForm)
#define iBw CSX_BVw(DevClrAdj.PrimAdj.rgbCSXForm)
#define iUw CSX_AUw(DevClrAdj.PrimAdj.rgbCSXForm)
#define iVw CSX_BVw(DevClrAdj.PrimAdj.rgbCSXForm)
#define iRefXw CSX_RefXw(DevClrAdj.PrimAdj.rgbCSXForm)
#define iRefYw CSX_RefYw(DevClrAdj.PrimAdj.rgbCSXForm)
#define iRefZw CSX_RefZw(DevClrAdj.PrimAdj.rgbCSXForm)
#define oAw CSX_AUw(DevCSXForm)
#define oBw CSX_BVw(DevCSXForm)
#define oUw CSX_AUw(DevCSXForm)
#define oVw CSX_BVw(DevCSXForm)
#define oRefXw CSX_RefXw(DevCSXForm)
#define oRefYw CSX_RefYw(DevCSXForm)
#define oRefZw CSX_RefZw(DevCSXForm)
CIExy StdIlluminant[ILLUMINANT_MAX_INDEX + 1] = {
{ (FD6)333333, (FD6)333333 }, // EQU
{ (FD6)447573, (FD6)407440 }, // A
{ (FD6)348904, (FD6)352001 }, // B
{ (FD6)310061, (FD6)316150 }, // C
{ (FD6)345669, (FD6)358496 }, // D50
{ (FD6)332424, (FD6)347426 }, // D55
{ (FD6)312727, (FD6)329023 }, // D65
{ (FD6)299021, (FD6)314852 }, // D75
{ (FD6)372069, (FD6)375119 } // F2
};
//
// Standard Illuminant Coordinates and its tristimulus values
//
// Illuminant x y X Y Z
//------------ ---------- ---------- --------- --------- ---------
// EQU 0.333333 0.333333 100.000 100.000 100.000
// A 0.447573 0.407440 109.850 100.000 35.585
// B 0.348904 0.352001 99.120 100.000 84.970
// C 0.310061 0.316150 98.074 100.000 118.232
// D50 0.345669 0.358496 96.422 100.000 82.521
// D55 0.332424 0.347426 95.682 100.000 92.149
// D65 0.312727 0.329023 95.047 100.000 108.883
// D75 0.299021 0.314852 94.972 100.000 122.638
// F2 0.372069 0.375119 99.187 100.000 67.395
// F7 0.312852 0.329165 95.044 100.000 108.755
// F11 0.380521 0.376881 100.966 100.000 64.370
//-----------------------------------------------------------------
//
HTPRIMOFFSET HTPrimOffsetTable[PRIMARY_ORDER_MAX + 1] = {
{ PRIMARY_ORDER_123, 0, 1, 2 }, // RGB
{ PRIMARY_ORDER_132, 0, 2, 1 }, // RBG
{ PRIMARY_ORDER_213, 1, 0, 2 }, // GRB
{ PRIMARY_ORDER_231, 2, 0, 1 }, // GBR
{ PRIMARY_ORDER_321, 2, 1, 0 }, // BGR
{ PRIMARY_ORDER_312, 1, 2, 0 } // BRG
};
RGBORDER RGBOrderTable[PRIMARY_ORDER_MAX + 1] = {
{ PRIMARY_ORDER_RGB, { 0, 1, 2 } },
{ PRIMARY_ORDER_RBG, { 0, 2, 1 } },
{ PRIMARY_ORDER_GRB, { 1, 0, 2 } },
{ PRIMARY_ORDER_GBR, { 1, 2, 0 } },
{ PRIMARY_ORDER_BGR, { 2, 1, 0 } },
{ PRIMARY_ORDER_BRG, { 2, 0, 1 } }
};
#define SRC_BF_HT_MONO 0
#define SRC_BF_HT_RGB 1
#define SRC_TABLE_BYTE 2
#define SRC_TABLE_WORD 3
#define SRC_TABLE_DWORD 4
#if DBG
LPBYTE pCBFLUTName[] = { "CBFLI_16_MONO",
"CBFLI_24_MONO",
"CBFLI_32_MONO",
"CBFLI_16_COLOR",
"CBFLI_24_COLOR",
"CBFLI_32_COLOR" };
LPBYTE pSrcPrimTypeName[] = { "SRC_BF_HT_MONO",
"SRC_BF_HT_RGB",
"SRC_TABLE_BYTE",
"SRC_TABLE_WORD",
"SRC_TABLE_DWORD" };
LPBYTE pDbgCSName[] = { "LUV", "LAB" };
LPBYTE pDbgCMIName[] = { "TABLE:MONO", "TABLE:COLOR",
"HT555:MONO", "HT555:COLOR" };
#endif
FD6
ColorAdjustPrim(
FD6 Prim,
FD6 Gamma,
PRIMADJ *pPrimAdj
)
/*++
Routine Description:
This function doing GAMMA Correction, Black white reference clipping,
Contrast adjustment, Brightness Adjustment, LOG filter and Negative
processing
Arguments:
Prim - Prim value to be adjusted
Gamma - Gamma
pPrimAdj - Pointer to the PRIMADJ structure
Return Value:
FD6 the new prim after adjusted
Author:
14-Mar-1995 Tue 16:03:00 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
DWORD Flags;
if (Flags = pPrimAdj->Flags & (DCA_HAS_SRC_GAMMA |
DCA_HAS_BW_REF_ADJ |
DCA_HAS_CONTRAST_ADJ |
DCA_HAS_BRIGHTNESS_ADJ |
DCA_LOG_FILTER |
DCA_NEGATIVE)) {
if (Flags & DCA_HAS_SRC_GAMMA) {
Prim = Power(Prim, Gamma);
}
if (Flags & DCA_HAS_BW_REF_ADJ) {
PRIM_BW_ADJ(Prim, *pPrimAdj);
}
if (Flags & DCA_HAS_CONTRAST_ADJ) {
PRIM_CONTRAST(Prim, (*pPrimAdj));
}
if (Flags & DCA_HAS_BRIGHTNESS_ADJ) {
PRIM_BRIGHTNESS(Prim, (*pPrimAdj));
}
if (Flags & DCA_LOG_FILTER) {
PRIM_LOG_FILTER(Prim);
}
if (Flags & DCA_NEGATIVE) {
Prim = FD6_1 - Prim;
}
//
// Now clamp the result bwtween 0.0 to 1.0 and save it back
//
CLAMP_01(Prim);
}
return(Prim);
}
DWORD
ColorAdjust3Prims(
PFD6 pPrims,
PRIMADJ *pPrimAdj
)
/*++
Routine Description:
This function doing GAMMA Correction, Black white reference clipping,
Contrast adjustment, Brightness Adjustment, LOG filter and Negative
processing
Arguments:
pPrims - Pointer to a maximum of 3 PRIMS in FD6 format
CountPrims - Count of total Prims to be process
pPrimAdj - Pointer to the PRIMADJ structure
Return Value:
DWORD - Flags processed
Author:
14-Mar-1995 Tue 16:03:00 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
DWORD Flags;
if (Flags = pPrimAdj->Flags & (DCA_HAS_SRC_GAMMA |
DCA_HAS_BW_REF_ADJ |
DCA_HAS_CONTRAST_ADJ |
DCA_HAS_BRIGHTNESS_ADJ |
DCA_LOG_FILTER |
DCA_NEGATIVE)) {
PFD6 pRGBGamma = (PFD6)&(pPrimAdj->RGBGamma);
FD6 PrimR;
FD6 PrimG;
FD6 PrimB;
if (Flags & DCA_HAS_SRC_GAMMA) {
PrimR = Power(pPrims[0], pPrimAdj->RGBGamma.R);
PrimG = Power(pPrims[1], pPrimAdj->RGBGamma.G);
PrimB = Power(pPrims[2], pPrimAdj->RGBGamma.B);
} else {
PrimR = pPrims[0];
PrimG = pPrims[1];
PrimB = pPrims[2];
}
if (Flags & DCA_HAS_BW_REF_ADJ) {
PRIM_BW_ADJ(PrimR, *pPrimAdj);
PRIM_BW_ADJ(PrimG, *pPrimAdj);
PRIM_BW_ADJ(PrimB, *pPrimAdj);
}
if (Flags & DCA_HAS_CONTRAST_ADJ) {
PRIM_CONTRAST(PrimR, (*pPrimAdj));
PRIM_CONTRAST(PrimG, (*pPrimAdj));
PRIM_CONTRAST(PrimB, (*pPrimAdj));
}
if (Flags & DCA_HAS_BRIGHTNESS_ADJ) {
PRIM_BRIGHTNESS(PrimR, (*pPrimAdj));
PRIM_BRIGHTNESS(PrimG, (*pPrimAdj));
PRIM_BRIGHTNESS(PrimB, (*pPrimAdj));
}
if (Flags & DCA_LOG_FILTER) {
PRIM_LOG_FILTER(PrimR);
PRIM_LOG_FILTER(PrimG);
PRIM_LOG_FILTER(PrimB);
}
if (Flags & DCA_NEGATIVE) {
PrimR = FD6_1 - PrimR;
PrimG = FD6_1 - PrimG;
PrimB = FD6_1 - PrimB;
}
CLAMP_01(PrimR);
CLAMP_01(PrimG);
CLAMP_01(PrimB);
pPrims[0] = PrimR;
pPrims[1] = PrimG;
pPrims[2] = PrimB;
}
return(Flags);
}
DWORD
ColorAdjustPrimCheckum(
PDEVCLRADJ pDevClrAdj,
DWORD *pChecksum
)
/*++
Routine Description:
This function compute the checksum for the PRIMADJ based on the flags
can be adjusted by the ColorAdjust3Prims() and ColorAdjustPrim()
Arguments:
pDevClrAdj - Pointer to the DEVCLRADJ data structure which 'ca' structure
will be reset after this function for the PrimAdj
pChecksum - Pointer to DWORD for Initial checksum and at return it will
contains new checksum
Return Value:
DWORD The Old PrimAdj flags which adjustet by this function
Author:
14-Mar-1995 Tue 17:07:11 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PRIMADJ PrimAdj = pDevClrAdj->PrimAdj;
DWORD Checksum = *pChecksum;
PrimAdj.Flags &= (DCA_HAS_SRC_GAMMA |
DCA_HAS_BW_REF_ADJ |
DCA_HAS_CONTRAST_ADJ |
DCA_HAS_BRIGHTNESS_ADJ |
DCA_LOG_FILTER |
DCA_NEGATIVE);
pDevClrAdj->PrimAdj.Flags &= ~(DCA_HAS_SRC_GAMMA |
DCA_HAS_BW_REF_ADJ |
DCA_HAS_CONTRAST_ADJ |
DCA_HAS_BRIGHTNESS_ADJ |
DCA_LOG_FILTER |
DCA_NEGATIVE);
if (!(PrimAdj.Flags & DCA_HAS_SRC_GAMMA)) {
PrimAdj.RGBGamma.R =
PrimAdj.RGBGamma.G =
PrimAdj.RGBGamma.B = FD6_0;
}
if (!(PrimAdj.Flags & DCA_HAS_BW_REF_ADJ)) {
PrimAdj.MinL =
PrimAdj.RangeL = FD6_0;
}
if (!(PrimAdj.Flags & DCA_HAS_CONTRAST_ADJ)) {
PrimAdj.Contrast = FD6_0;
}
if (!(PrimAdj.Flags & DCA_HAS_BRIGHTNESS_ADJ)) {
PrimAdj.Brightness = FD6_0;
}
ADJ_CHECKSUM(Checksum, Flags);
ADJ_CHECKSUM(Checksum, RGBGamma);
ADJ_CHECKSUM(Checksum, MinL);
ADJ_CHECKSUM(Checksum, RangeL);
ADJ_CHECKSUM(Checksum, Contrast);
ADJ_CHECKSUM(Checksum, Brightness);
*pChecksum = Checksum;
pDevClrAdj->ca.caFlags &= ~(CLRADJF_LOG_FILTER |
CLRADJF_NEGATIVE);
pDevClrAdj->ca.caRedGamma =
pDevClrAdj->ca.caGreenGamma =
pDevClrAdj->ca.caBlueGamma =
pDevClrAdj->ca.caReferenceBlack =
pDevClrAdj->ca.caReferenceWhite =
pDevClrAdj->ca.caContrast =
pDevClrAdj->ca.caBrightness = 0;
return(PrimAdj.Flags);
}
VOID
TintAngle(
LONG TintAdjust,
LONG AngleStep,
PFD6 pSin,
PFD6 pCos
)
/*++
Routine Description:
This function return a sin/cos number for the tint adjust, these returned
numbers are used to rotate the color space.
Arguments:
TintAdjust - Range from -100 to 100
AngleStep - Range from 1 to 10
pSin - Pointer to a FD6 number to store the SIN result
pCos - Pointer to a FD6 number to store the COS result
Return Value:
no return value, but the result is stored in pSin/pCos
Author:
13-Mar-1992 Fri 15:58:30 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LONG Major;
LONG Minor;
BOOL PosSin;
BOOL PosCos = TRUE;
FD6 Sin;
FD6 Cos;
if (PosSin = (BOOL)(TintAdjust <= 0)) {
if (!(TintAdjust = (LONG)-TintAdjust)) {
*pSin = *pCos = (FD6)0;
return;
}
}
if (TintAdjust > 100) {
TintAdjust = 100;
}
if ((AngleStep < 1) || (AngleStep > 10)) {
AngleStep = 10;
}
if ((TintAdjust *= AngleStep) >= 900) {
TintAdjust = 1800L - TintAdjust;
PosCos = FALSE;
}
//
// Compute the Sin portion
//
Major = TintAdjust / 10L;
Minor = TintAdjust % 10L;
Sin = SinNumber[Major];
if (Minor) {
Sin += (FD6)((((LONG)(SinNumber[Major+1] - Sin) * Minor) + 5L) / 10L);
}
*pSin = (PosSin) ? Sin : -Sin;
//
// Compute the cosine portion
//
if (Minor) {
Minor = 10 - Minor;
++Major;
}
Major = 90 - Major;
Cos = SinNumber[Major];
if (Minor) {
Cos += (FD6)((((LONG)(SinNumber[Major+1] - Cos) * Minor) + 5L) / 10L);
}
*pCos = (PosCos) ? Cos : -Cos;
}
PDEVICECOLORINFO
HTENTRY
pDCIAdjClr(
PDEVICEHALFTONEINFO pDeviceHalftoneInfo,
PHTCOLORADJUSTMENT pHTColorAdjustment,
PDEVCLRADJ pDevClrAdj,
WORD ForceFlags
)
/*++
Routine Description:
This function allowed the caller to changed the overall color adjustment
for all the pictures rendered
Arguments:
pDeviceHalftoneInfo - Pointer to the DEVICEHALFTONEINFO data structure
which returned from the HT_CreateDeviceHalftoneInfo.
pHTColorAdjustment - Pointer to the HTCOLORADJUSTMENT data structure, if
this pointer is NULL then a default is applied.
pDevClrAdj - Pointer to the DEVCLRADJ data structure where the
computed results will be stored, if this pointer is
NULL then no color adjustment is done.
if pSrcSI and pDevClrAdj are not NULL then
pDevClrAdj->Flags must contains the BBPFlags;
ForceFlags - Force flags to make color changed.
Return Value:
PDEVICECOLORINFO, if return is NULL then a invalid pDeviceHalftoneInfo
pointer is passed.
Author:
29-May-1991 Wed 09:11:31 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PDEVICECOLORINFO pDCI;
if ((!pDeviceHalftoneInfo) ||
(PHT_DHI_DCI_OF(HalftoneDLLID) != HALFTONE_DLL_ID)) {
return(NULL);
}
pDCI = PDHI_TO_PDCI(pDeviceHalftoneInfo);
//
// Only if caller required color adjustments computations, then we will
// compute for it.
//
if (pDevClrAdj) {
HTCOLORADJUSTMENT ca;
HTCOLORADJUSTMENT caCached;
PRIMADJ PrimAdj;
//=====================================================================
// We must make sure only one thread using this info.
//=====================================================================
ACQUIRE_HTMUTEX(pDCI->HTMutex);
ca = (pHTColorAdjustment) ? *pHTColorAdjustment :
pDeviceHalftoneInfo->HTColorAdjustment;
if ((ca.caSize != sizeof(HTCOLORADJUSTMENT)) ||
(ca.caFlags & ~(CLRADJF_FLAGS_MASK))) {
ca = DefaultCA;
}
caCached = pDCI->ca;
PrimAdj = pDCI->PrimAdj;
RELEASE_HTMUTEX(pDCI->HTMutex);
//
// Now validate all color adjustments
//
ca.caFlags &= CLRADJF_FLAGS_MASK;
if (ca.caIlluminantIndex > ILLUMINANT_MAX_INDEX) {
ca.caIlluminantIndex = DefaultCA.caIlluminantIndex;
}
ADJ_CA(ca.caRedGamma, RGB_GAMMA_MIN, RGB_GAMMA_MAX);
ADJ_CA(ca.caGreenGamma, RGB_GAMMA_MIN, RGB_GAMMA_MAX);
ADJ_CA(ca.caBlueGamma, RGB_GAMMA_MIN, RGB_GAMMA_MAX);
ADJ_CA(ca.caReferenceBlack, 0, REFERENCE_BLACK_MAX);
ADJ_CA(ca.caReferenceWhite, REFERENCE_WHITE_MIN, 10000);
ADJ_CA(ca.caContrast, MIN_COLOR_ADJ, MAX_COLOR_ADJ);
ADJ_CA(ca.caBrightness, MIN_COLOR_ADJ, MAX_COLOR_ADJ);
ADJ_CA(ca.caColorfulness, MIN_COLOR_ADJ, MAX_COLOR_ADJ);
ADJ_CA(ca.caRedGreenTint, MIN_COLOR_ADJ, MAX_COLOR_ADJ);
if ((ForceFlags & ADJ_FORCE_MONO) ||
(ca.caColorfulness == MIN_COLOR_ADJ)) {
ca.caColorfulness = MIN_COLOR_ADJ;
ca.caRedGreenTint = 0;
}
if (ForceFlags & ADJ_FORCE_NEGATIVE) {
ca.caFlags |= CLRADJF_NEGATIVE;
}
if (pDCI->Flags & DCIF_ADDITIVE_PRIMS) {
ForceFlags &= ~(ADJ_FORCE_SUB_COLOR | ADJ_FORCE_BRUSH);
}
ca.caSize = (WORD)(ForceFlags & (ADJ_FORCE_ADDITIVE_PRIMS |
ADJ_FORCE_SUB_COLOR |
ADJ_FORCE_BRUSH));
if (!COMP_CA(&ca, &caCached)) {
DBGP_IF(DBGP_HCA,
DBGP("---- New Color Adjustments ----");
DBGP("Flags = %08x" ARGDW(ca.caFlags));
DBGP("Illum = %d" ARGW(ca.caIlluminantIndex));
DBGP("R_Power = %u" ARGI(ca.caRedGamma));
DBGP("G_Power = %u" ARGI(ca.caGreenGamma));
DBGP("B_Power = %u" ARGI(ca.caBlueGamma));
DBGP("BlackRef = %u" ARGW(ca.caReferenceBlack));
DBGP("WhiteRef = %u" ARGW(ca.caReferenceWhite));
DBGP("Contrast = %d" ARGI(ca.caContrast));
DBGP("Bright = %d" ARGI(ca.caBrightness));
DBGP("Colorful = %d" ARGI(ca.caColorfulness));
DBGP("RG_Tint = %d" ARGI(ca.caRedGreenTint));
DBGP("ForceAdj = %04lx" ARGDW(ForceFlags)));
if (ForceFlags & ADJ_FORCE_ADDITIVE_PRIMS) {
PrimAdj.Flags = DCA_USE_ADDITIVE_PRIMS;
DBGP_IF(DBGP_HCA, DBGP("---DCA_USE_ADDITIVE_PRIMS---"));
} else {
PrimAdj.Flags = 0;
}
if (ForceFlags & ADJ_FORCE_SUB_COLOR) {
if (pDCI->Flags & DCIF_HAS_DEV_GAMMA) {
PrimAdj.Flags |= DCA_DO_SUB_ADJ;
DBGP_IF(DBGP_SUB_ADJ,
DBGP("--- ADJ_FORCE_SUB_COLOR --- SubGamma=%s"
ARGFD6(pDCI->ClrXFormBlock.DevRGBGamma, 1, 6)));
} else {
DBGP_IF(DBGP_SUB_ADJ,
DBGP("--- ADJ_FORCE_SUB_COLOR --- NO SubGamma=1.0"));
}
}
if (ForceFlags & ADJ_FORCE_BRUSH) {
PrimAdj.Flags |= DCA_IS_BRUSH;
}
if (ca.caFlags & CLRADJF_LOG_FILTER) {
if (!LogFilterMax) {
LogFilterMax = PRIM_LOG_RATIO(FD6_1);
}
PrimAdj.Flags |= DCA_LOG_FILTER;
DBGP_IF(DBGP_HCA, DBGP("---DCA_LOG_FILTER---"));
}
if (ca.caFlags & CLRADJF_NEGATIVE) {
PrimAdj.Flags |= DCA_NEGATIVE;
DBGP_IF(DBGP_HCA, DBGP("---DCA_NEGATIVE---"));
}
if (ca.caColorfulness == MIN_COLOR_ADJ) {
PrimAdj.Flags |= DCA_MONO_ONLY;
DBGP_IF(DBGP_HCA, DBGP("---DCA_MONO_ONLY---"));
}
if (ca.caIlluminantIndex != caCached.caIlluminantIndex) {
//
// Illuminant has been changed, re-compute the color space
// transform and destroy the cached color mapping if one exists.
//
DBGP_IF(DBGP_CCT,
DBGP("*** Re-Compute Illuminant [%u] for DEVICE"
ARGU(ca.caIlluminantIndex)));
ComputeColorSpaceXForm(&(pDCI->ClrXFormBlock.rgbCIEPrims),
&(PrimAdj.rgbCSXForm),
pDCI->ClrXFormBlock.ColorSpace,
ca.caIlluminantIndex,
FALSE);
}
if ((ca.caRedGamma != UDECI4_1) ||
(ca.caGreenGamma != UDECI4_1) ||
(ca.caBlueGamma != UDECI4_1)) {
DBGP_IF(DBGP_HCA, DBGP("---DCA_HAS_SRC_GAMMA---"));
PrimAdj.RGBGamma.R = UDECI4ToFD6(ca.caRedGamma);
PrimAdj.RGBGamma.G = UDECI4ToFD6(ca.caGreenGamma);
PrimAdj.RGBGamma.B = UDECI4ToFD6(ca.caBlueGamma);
PrimAdj.Flags |= DCA_HAS_SRC_GAMMA;
} else {
PrimAdj.RGBGamma.R =
PrimAdj.RGBGamma.G =
PrimAdj.RGBGamma.B = FD6_0;
}
if ((ca.caReferenceBlack != UDECI4_0) ||
(ca.caReferenceWhite != UDECI4_1)) {
PrimAdj.MinL = UDECI4ToFD6(ca.caReferenceBlack);
PrimAdj.RangeL = UDECI4ToFD6(ca.caReferenceWhite -
ca.caReferenceBlack);
PrimAdj.Flags |= DCA_HAS_BW_REF_ADJ;
DBGP_IF(DBGP_HCA, DBGP("---DCA_HAS_BW_REF_ADJ---"));
}
if (ca.caContrast) {
PrimAdj.Contrast = JND_ADJ((FD6)1015000, ca.caContrast);
PrimAdj.Flags |= DCA_HAS_CONTRAST_ADJ;
DBGP_IF(DBGP_HCA, DBGP("---DCA_HAS_CONTRAST_ADJ---"));
}
if (ca.caBrightness) {
PrimAdj.Brightness = FD6xL((FD6)3750, ca.caBrightness);
PrimAdj.Flags |= DCA_HAS_BRIGHTNESS_ADJ;
DBGP_IF(DBGP_HCA, DBGP("---DCA_HAS_BRIGHTNESS_ADJ---"));
}
//
// Colorfulness, RedGreenTint, and DYE_CORRECTIONS only valid and
// necessary if it a color device output
//
if (!(PrimAdj.Flags & DCA_MONO_ONLY)) {
if (ca.caColorfulness) {
PrimAdj.Color = (FD6)(((LONG)ca.caColorfulness +
(LONG)MAX_COLOR_ADJ) * 10000L);
PrimAdj.Flags |= DCA_HAS_COLOR_ADJ;
DBGP_IF(DBGP_HCA, DBGP("---DCA_HAS_COLOR_ADJ---"));
}
if (ca.caRedGreenTint) {
TintAngle((LONG)ca.caRedGreenTint,
(LONG)6,
(PFD6)&(PrimAdj.TintSinAngle),
(PFD6)&(PrimAdj.TintCosAngle));
PrimAdj.Flags |= DCA_HAS_TINT_ADJ;
DBGP_IF(DBGP_HCA, DBGP("---DCA_HAS_TINT_ADJ---"));
}
if (pDCI->Flags & DCIF_NEED_DYES_CORRECTION) {
PrimAdj.Flags |= DCA_NEED_DYES_CORRECTION;
DBGP_IF(DBGP_HCA, DBGP("---DCA_NEED_DYES_CORRECTION---"));
if (pDCI->Flags & DCIF_HAS_BLACK_DYE) {
PrimAdj.Flags |= DCA_HAS_BLACK_DYE;
DBGP_IF(DBGP_HCA, DBGP("---DCA_HAS_BLACK_DYE---"));
}
}
}
DBGP_IF(DBGP_CCT, DBGP("**** Save caCahced/PrimAdj back to pDCI"));
ACQUIRE_HTMUTEX(pDCI->HTMutex);
pDCI->ca = ca;
pDCI->PrimAdj = PrimAdj;
RELEASE_HTMUTEX(pDCI->HTMutex);
} else {
DBGP_IF(DBGP_CCT, DBGP("* Use cached HTCOLORADJUSTMENT *"));
}
pDevClrAdj->ca = ca;
pDevClrAdj->PrimAdj = PrimAdj;
pDevClrAdj->pClrXFormBlock = &(pDCI->ClrXFormBlock);
pDevClrAdj->pCRTXLevel255 = &(pDCI->CRTX[CRTX_LEVEL_255]);
pDevClrAdj->pCRTXLevel31 = &(pDCI->CRTX[CRTX_LEVEL_31]);
}
return(pDCI);
}
VOID
HTENTRY
ComputeColorSpaceXForm(
PCIEPRIMS pCIEPrims,
PCOLORSPACEXFORM pCSXForm,
UINT ColorSpace,
UINT IlluminantIndex,
BOOL InverseXForm
)
/*++
Routine Description:
This function take device's R/G/B/W CIE coordinate (x,y) and compute
3 x 3 transform matrix, it assume the primaries are additively.
Calcualte the 3x3 CIE matrix and its inversion (matrix) based on the
C.I.E. CHROMATICITY x, y coordinates or RGB and WHITE alignment.
this function produces the CIE XYZ matrix and/or its inversion for trnaform
between RGB primary colors and CIE color spaces, the transforms are
-1
[ X ] = [ Xr Xg Xb ] [ R ] [ R ] = [ Xr Xg Xb ] [ X ]
[ Y ] = [ Yr Yg Yb ] [ G ] and [ G ] [ Yr Yg Yb ] [ Y ]
[ Z ] = [ Zr Zg Zb ] [ B ] [ B ] [ Zr Zg Zb ] [ Z ]
Arguments:
pCIEPrims - Pointer to CIEPRIMS data structure, the CIEPRIMS data
must already validated.
pCSXForm - Pointer to the location to stored the transfrom
ColorSpace - CIELUV or CIELAB
IlluminantIndex - Standard illuminant index if DEVICE_DEFAULT then
pCIEPrims->w is used
InverseXForm - True if inversed transform will be stored in the
pCSXForm->M3x3.
Return Value:
VOID
Author:
11-Oct-1991 Fri 14:19:59 created -by- Daniel Chou (danielc)
Revision History:
20-Apr-1993 Tue 03:08:15 updated -by- Daniel Chou (danielc)
re-write so that xform will be correct when device default is used.
--*/
{
MATRIX3x3 Matrix3x3;
FD6XYZ WhiteXYZ;
MULDIVPAIR MDPairs[5];
FD6 DiffRGB;
FD6 RedXYZScale;
FD6 GreenXYZScale;
FD6 BlueXYZScale;
FD6 AUw;
FD6 BVw;
FD6 xr;
FD6 yr;
FD6 xg;
FD6 yg;
FD6 xb;
FD6 yb;
FD6 xw;
FD6 yw;
FD6 Yw;
xr = pCIEPrims->r.x;
yr = pCIEPrims->r.y;
xg = pCIEPrims->g.x;
yg = pCIEPrims->g.y;
xb = pCIEPrims->b.x;
yb = pCIEPrims->b.y;
if (IlluminantIndex > ILLUMINANT_MAX_INDEX) {
xw = pCIEPrims->w.x;
yw = pCIEPrims->w.y;
} else {
if (!IlluminantIndex) {
IlluminantIndex = (ColorSpace == CIELUV_1976) ? ILLUMINANT_D65 :
ILLUMINANT_D50;
}
xw = StdIlluminant[IlluminantIndex].x;
yw = StdIlluminant[IlluminantIndex].y;
}
Yw = pCIEPrims->Yw;
DBGP_IF(DBGP_CIEMATRIX,
DBGP("** CIEINFO: [xw, yw, Yw] = [%s, %s, %s]"
ARGFD6l(xw) ARGFD6l(yw) ARGFD6l(Yw));
DBGP("[xR yR] = [%s %s]" ARGFD6l(xr) ARGFD6l(yr));
DBGP("[xG yG] = [%s %s]" ARGFD6l(xg) ARGFD6l(yg));
DBGP("[xB yB] = [%s %s]" ARGFD6l(xb) ARGFD6l(yb));
DBGP("***********************************************");
);
//
// Normalized to have C.I.E. Y equal to 1.0
//
MAKE_MULDIV_INFO(MDPairs, 3, MULDIV_HAS_DIVISOR);
MAKE_MULDIV_DVSR(MDPairs, Yw);
MAKE_MULDIV_PAIR(MDPairs, 1, xr, yg - yb);
MAKE_MULDIV_PAIR(MDPairs, 2, xg, yb - yr);
MAKE_MULDIV_PAIR(MDPairs, 3, xb, yr - yg);
DiffRGB = MulFD6(yw, MulDivFD6Pairs(MDPairs));
//
// Compute Scaling factors for each color
//
MAKE_MULDIV_INFO(MDPairs, 4, MULDIV_HAS_DIVISOR);
MAKE_MULDIV_DVSR(MDPairs, DiffRGB);
MAKE_MULDIV_PAIR(MDPairs, 1, xw, yg - yb);
MAKE_MULDIV_PAIR(MDPairs, 2, -yw, xg - xb);
MAKE_MULDIV_PAIR(MDPairs, 3, xg, yb );
MAKE_MULDIV_PAIR(MDPairs, 4, -xb, yg );
RedXYZScale = MulDivFD6Pairs(MDPairs);
MAKE_MULDIV_PAIR(MDPairs, 1, xw, yb - yr);
MAKE_MULDIV_PAIR(MDPairs, 2, -yw, xb - xr);
MAKE_MULDIV_PAIR(MDPairs, 3, -xr, yb );
MAKE_MULDIV_PAIR(MDPairs, 4, xb, yr );
GreenXYZScale = MulDivFD6Pairs(MDPairs);
MAKE_MULDIV_PAIR(MDPairs, 1, xw, yr - yg);
MAKE_MULDIV_PAIR(MDPairs, 2, -yw, xr - xg);
MAKE_MULDIV_PAIR(MDPairs, 3, xr, yg );
MAKE_MULDIV_PAIR(MDPairs, 4, -xg, yr );
BlueXYZScale = MulDivFD6Pairs(MDPairs);
//
// Now scale the RGB coordinate by it ratio, notice that C.I.E z value.
// equal to (1.0 - x - y)
//
// Make sure Yr + Yg + Yb = 1.0, this may happened when ruound off
// durning the computation, we will add the difference (at most it will
// be 0.000002) to the Yg since this is brightnest color
//
CIE_Xr(Matrix3x3) = MulFD6(xr, RedXYZScale);
CIE_Xg(Matrix3x3) = MulFD6(xg, GreenXYZScale);
CIE_Xb(Matrix3x3) = MulFD6(xb, BlueXYZScale);
pCSXForm->Yrgb.R =
CIE_Yr(Matrix3x3) = MulFD6(yr, RedXYZScale);
pCSXForm->Yrgb.G =
CIE_Yg(Matrix3x3) = MulFD6(yg, GreenXYZScale);
pCSXForm->Yrgb.B =
CIE_Yb(Matrix3x3) = MulFD6(yb, BlueXYZScale);
CIE_Zr(Matrix3x3) = MulFD6(FD6_1 - xr - yr, RedXYZScale);
CIE_Zg(Matrix3x3) = MulFD6(FD6_1 - xg - yg, GreenXYZScale);
CIE_Zb(Matrix3x3) = MulFD6(FD6_1 - xb - yb, BlueXYZScale);
WhiteXYZ.X = CIE_Xr(Matrix3x3) + CIE_Xg(Matrix3x3) + CIE_Xb(Matrix3x3);
WhiteXYZ.Y = CIE_Yr(Matrix3x3) + CIE_Yg(Matrix3x3) + CIE_Yb(Matrix3x3);
WhiteXYZ.Z = CIE_Zr(Matrix3x3) + CIE_Zg(Matrix3x3) + CIE_Zb(Matrix3x3);
//
// If request a 3 x 3 transform matrix then save the result back
//
DBGP_IF(DBGP_CIEMATRIX,
DBGP("== RGB -> XYZ 3x3 Matrix ==== White = (%s, %s) =="
ARGFD6s(xw) ARGFD6s(yw));
DBGP("[Xr Xg Xb] = [%s %s %s]" ARGFD6l(CIE_Xr(Matrix3x3))
ARGFD6l(CIE_Xg(Matrix3x3))
ARGFD6l(CIE_Xb(Matrix3x3)));
DBGP("[Yr Yg Yb] = [%s %s %s]" ARGFD6l(CIE_Yr(Matrix3x3))
ARGFD6l(CIE_Yg(Matrix3x3))
ARGFD6l(CIE_Yb(Matrix3x3)));
DBGP("[Zr Zg Zb] = [%s %s %s]" ARGFD6l(CIE_Zr(Matrix3x3))
ARGFD6l(CIE_Zg(Matrix3x3))
ARGFD6l(CIE_Zb(Matrix3x3)));
DBGP("===============================================");
);
DBGP_IF(DBGP_CIEMATRIX,
DBGP("RGB->XYZ: [Xw=%s, Yw=%s, Zw=%s]"
ARGFD6l(WhiteXYZ.X)
ARGFD6l(WhiteXYZ.Y)
ARGFD6l(WhiteXYZ.Z)));
if (InverseXForm) {
pCSXForm->M3x3 = Matrix3x3;
ComputeInverseMatrix3x3(&(pCSXForm->M3x3), &Matrix3x3);
DBGP_IF(DBGP_CIEMATRIX,
DBGP("======== XYZ -> RGB INVERSE 3x3 Matrix ========");
DBGP(" -1");
DBGP("[Xr Xg Xb] = [%s %s %s]" ARGFD6l(CIE_Xr(Matrix3x3))
ARGFD6l(CIE_Xg(Matrix3x3))
ARGFD6l(CIE_Xb(Matrix3x3)));
DBGP("[Yr Yg Yb] = [%s %s %s]"
ARGFD6l(CIE_Yr(Matrix3x3))
ARGFD6l(CIE_Yg(Matrix3x3))
ARGFD6l(CIE_Yb(Matrix3x3)));
DBGP("[Zr Zg Zb] = [%s %s %s]"
ARGFD6l(CIE_Zr(Matrix3x3))
ARGFD6l(CIE_Zg(Matrix3x3))
ARGFD6l(CIE_Zb(Matrix3x3)));
DBGP("===============================================");
);
}
if (WhiteXYZ.Y != NORMALIZED_WHITE) {
if (WhiteXYZ.Y) {
WhiteXYZ.X = DivFD6(WhiteXYZ.X, WhiteXYZ.Y);
WhiteXYZ.Z = DivFD6(WhiteXYZ.Z, WhiteXYZ.Y);
} else {
WhiteXYZ.X =
WhiteXYZ.Z = FD6_0;
}
WhiteXYZ.Y = NORMALIZED_WHITE;
}
switch(ColorSpace) {
case CIELUV_1976:
//
// U' = 4X / (X + 15Y + 3Z)
// V' = 9Y / (X + 15Y + 3Z)
//
// U* = 13 x L x (U' - Uw)
// V* = 13 x L x (V' - Vw)
//
//
DiffRGB = WhiteXYZ.X + FD6xL(WhiteXYZ.Y, 15) + FD6xL(WhiteXYZ.Z, 3);
AUw = DivFD6(FD6xL(WhiteXYZ.X, 4), DiffRGB);
BVw = DivFD6(FD6xL(WhiteXYZ.Y, 9), DiffRGB);
break;
case CIELAB_1976:
default:
//
// CIELAB 1976 L*A*B*
//
// A* = 500 x (fX - fY)
// B* = 200 x (fY - fZ)
//
// 1/3
// fX = (X/Xw) (X/Xw) > 0.008856
// fX = 7.787 x (X/Xw) + (16/116) (X/Xw) <= 0.008856
//
// 1/3
// fY = (Y/Yw) (Y/Yw) > 0.008856
// fY = 7.787 Y (Y/Yw) + (16/116) (Y/Yw) <= 0.008856
//
// 1/3
// fZ = (Z/Zw) (Z/Zw) > 0.008856
// fZ = 7.787 Z (Z/Zw) + (16/116) (Z/Zw) <= 0.008856
//
AUw =
BVw = FD6_0;
break;
}
DBGP_IF(DBGP_CSXFORM,
DBGP("---------- ComputeColorSpaceXForm --------------");
DBGP(" ColorSpace = %s" ARG(pDbgCSName[ColorSpace]));
DBGP(" Xw = %s" ARGFD6s(WhiteXYZ.X));
DBGP(" Yw = %s" ARGFD6s(WhiteXYZ.Y));
DBGP(" Zw = %s" ARGFD6s(WhiteXYZ.Z));
DBGP(" AUw = %s" ARGFD6s(AUw));
DBGP(" BVw = %s" ARGFD6s(BVw));
DBGP("------------------------------------------------");
);
pCSXForm->M3x3 = Matrix3x3;
pCSXForm->WhiteXYZ = WhiteXYZ;
pCSXForm->AUw = AUw;
pCSXForm->BVw = BVw;
pCSXForm->xW = xw;
pCSXForm->yW = yw;
}
PCACHERGBTOXYZ
HTENTRY
CacheRGBToXYZ(
PDEVICECOLORINFO pDCI,
PCACHERGBTOXYZ pCRTX,
PFD6XYZ pFD6XYZ,
LPDWORD pNewChecksum,
PDEVCLRADJ pDevClrAdj
)
/*++
Routine Description:
This function cached the RGB color input to XYZ
Arguments:
pCRTX - Pointer to the CACHERGBTOXYZ
pFD6XYZ - Pointer to the local cached RGB->XYZ table (will be updated)
pNewChecksum- Pointer to the new checksum computed
pDevClrAdj - Pointer to DEVCLRADJ,
Return Value:
if a cahced is copied to the pFD6XYZ then NULL will be returned, otherwise
the cache table is computed on the pFD6XYZ and pCRTX returned
TRUE if cached XYZ info is generate, false otherwise, only possible failure
is that memory allocation failed.
Author:
08-May-1992 Fri 13:21:03 created -by- Daniel Chou (danielc)
Revision History:
09-Mar-1995 Thu 10:50:13 updated -by- Daniel Chou (danielc)
DO NOT TURN OFF DCA_NEGATIVE in this function
--*/
{
PMATRIX3x3 pRGBToXYZ;
PRIMADJ *pPrimAdj;
PFD6 pRGBGamma;
FD6 PrimPower;
FD6 Gamma;
FD6 rgbX;
FD6 rgbY;
FD6 rgbZ;
FD6 PrimInc;
FD6 PrimCur;
UINT PrimMax;
DWORD Checksum;
INT PrimLoop;
INT RGBIndex;
DWORD Flags;
//
// Turn off the one we did not need any checksum for
//
pPrimAdj = &(pDevClrAdj->PrimAdj);
pRGBToXYZ = &(pPrimAdj->rgbCSXForm.M3x3);
pRGBGamma = (PFD6)&(pPrimAdj->RGBGamma);
Checksum = ComputeChecksum((LPBYTE)pRGBToXYZ, 'CXYZ', sizeof(MATRIX3x3));
Flags = ColorAdjustPrimCheckum(pDevClrAdj, &Checksum);
ACQUIRE_HTMUTEX(pDCI->HTMutex);
if ((pCRTX->pFD6XYZ) &&
(pCRTX->Checksum == Checksum)) {
CopyMemory(pFD6XYZ, pCRTX->pFD6XYZ, pCRTX->SizeCRTX);
RELEASE_HTMUTEX(pDCI->HTMutex);
DBGP_IF(DBGP_BFINFO,
DBGP("*** Use %u bytes CACHED RGB->XYZ Table ***"
ARGU(pCRTX->SizeCRTX)));
return(NULL);
}
*pNewChecksum = Checksum;
RELEASE_HTMUTEX(pDCI->HTMutex);
DBGP_IF(DBGP_CCT, DBGP("** Re-Compute %ld bytes RGB->XYZ xform table **"
ARGDW(pCRTX->SizeCRTX)));
pPrimAdj->Flags |= Flags;
PrimMax = (UINT)pCRTX->PrimMax;
PrimInc = DivFD6(1, PrimMax);
for (RGBIndex = 0; RGBIndex < 3; RGBIndex++) {
rgbX = pRGBToXYZ->m[X_INDEX][RGBIndex];
rgbY = pRGBToXYZ->m[Y_INDEX][RGBIndex];
rgbZ = pRGBToXYZ->m[Z_INDEX][RGBIndex];
Gamma = *pRGBGamma++;
DBGP_IF(DBGP_CACHED_GAMMA,
DBGP("CachedRGBToXYZ %u:%u, Gamma=%s, XYZ=%s:%s:%s"
ARGU(RGBIndex)
ARGU(PrimMax)
ARGFD6(Gamma, 1, 6)
ARGFD6(rgbX, 2, 6)
ARGFD6(rgbY, 2, 6)
ARGFD6(rgbZ, 2, 6)));
PrimCur = FD6_0;
PrimLoop = (INT)(PrimMax + 1);
while (PrimLoop--) {
PrimPower = (Flags) ? ColorAdjustPrim(PrimCur, Gamma, pPrimAdj) :
PrimCur;
pFD6XYZ->X = MulFD6(rgbX, PrimPower);
pFD6XYZ->Y = MulFD6(rgbY, PrimPower);
pFD6XYZ->Z = MulFD6(rgbZ, PrimPower);
PrimCur += PrimInc;
++pFD6XYZ;
#if 0
DBGP_IF(DBGP_CACHED_GAMMA,
DBGP("(%u:%3u): %s --> %s"
ARGU(RGBIndex)
ARGU(PrimMax - PrimLoop)
ARGFD6(PrimCur, 1, 6)
ARGFD6(PrimPower, 1, 6)));
#endif
}
}
pPrimAdj->Flags &= ~Flags;
return(pCRTX);
}
#if 0
VOID
XFormRGBToXYZ(
PFD6PRIM123 pPrims,
PFD6XYZ *pXYZTable,
PMATRIX3x3 pXFormMatrix,
FD6 PrimMax,
FD6 DevRefY,
PRGBGAMMA pRGBGamma,
UINT CountPrim123,
UINT PrimAdjFlags
)
{
FD6PRIM123 Prims;
if (pXYZTable) {
PFD6XYZ pR_XYZ = pXYZTable[0];
PFD6XYZ pG_XYZ = pXYZTable[1];
PFD6XYZ pB_XYZ = pXYZTable[2];
if (PrimAdjFlags & DCA_MONO_ONLY) {
while (CountPrim123--) {
pPrims->p1 = pR_XYZ[pPrims->p1].Y +
pG_XYZ[pPrims->p2].Y +
pB_XYZ[pPrims->p3].Y;
++pPrims;
}
} else {
while (CountPrim123--) {
Prims = *pPrims;
pPrims->p1 = pR_XYZ[Prims.p1].X +
pG_XYZ[Prims.p2].X +
pB_XYZ[Prims.p3].X;
pPrims->p2 = pR_XYZ[Prims.p1].Y +
pG_XYZ[Prims.p2].Y +
pB_XYZ[Prims.p3].Y;
pPrims->p3 = pR_XYZ[Prims.p1].Z +
pG_XYZ[Prims.p2].Z +
pB_XYZ[Prims.p3].Z;
++pPrims;
}
}
} else {
RGBGAMMA RGBGamma;
MATRIX3x3 XFormMatrix = *pXFormMatrix;
MULDIVPAIR MDPairs[4];
FD6PRIM123 xyz;
FD6 NegAdd;
if (pRGBGamma) {
RGBGamma = *pRGBGamma;
} else {
RGBGamma.R =
RGBGamma.G =
RGBGamma.B = FD6_1;
}
if (!PrimMax) {
PrimMax = FD6_1;
}
if (PrimAdjFlags & DCA_NEGATIVE) {
NegAdd = FD6_1;
PrimMax = -PrimMax;
} else {
NegAdd = FD6_0;
}
//
// Real time computation
//
MAKE_MULDIV_SIZE(MDPairs, 3);
MAKE_MULDIV_DVSR(MDPairs, DevRefY);
while (CountPrim123--) {
Prims.p1 = NegAdd + Power(DivFD6(pPrims->p1, PrimMax), RGBGamma.R);
Prims.p2 = NegAdd + Power(DivFD6(pPrims->p2, PrimMax), RGBGamma.G);
Prims.p3 = NegAdd + Power(DivFD6(pPrims->p3, PrimMax), RGBGamma.B);
//
// Do the Y first
//
MAKE_MULDIV_FLAG(MDPairs, MULDIV_HAS_DIVISOR);
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Yr(XFormMatrix), Prims.p1);
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Yg(XFormMatrix), Prims.p2);
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Yb(XFormMatrix), Prims.p3);
xyz.p2 = MulDivFD6Pairs(MDPairs);
if (PrimAdjFlags & DCA_MONO_ONLY) {
xyz.p1 =
xyz.p3 = xyz.p2;
} else {
MAKE_MULDIV_FLAG(MDPairs, MULDIV_NO_DIVISOR);
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Xr(XFormMatrix), Prims.p1);
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Xg(XFormMatrix), Prims.p2);
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Xb(XFormMatrix), Prims.p3);
xyz.p1 = MulDivFD6Pairs(MDPairs);
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Zr(XFormMatrix), Prims.p1);
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Zg(XFormMatrix), Prims.p2);
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Zb(XFormMatrix), Prims.p3);
xyz.p3 = MulDivFD6Pairs(MDPairs);
}
*pPrims++ = xyz;
}
}
}
VOID
XFormXYZToXYZ(
PFD6PRIM123 pPrims,
PFD6XYZ *pXYZTable,
PMATRIX3x3 pXFormMatrix,
FD6 PrimMax,
FD6 DevRefY,
PRGBGAMMA pRGBGamma,
UINT CountPrim123,
UINT PrimAdjFlags
)
{
FD6XYZ White;
if (!PrimMax) {
PrimMax = FD6_1;
}
if (PrimAdjFlags & DCA_NEGATIVE) {
PrimMax = -PrimMax;
White.X = pRGBGamma->R;
White.Y = pRGBGamma->G;
White.Z = pRGBGamma->B;
} else {
White.X =
White.Y =
White.Z = FD6_0;
}
if (PrimAdjFlags & DCA_MONO_ONLY) {
while (CountPrim123--) {
pPrims->p1 =
pPrims->p2 =
pPrims->p3 = White.Y + DivFD6(pPrims->p2, PrimMax);
++pPrims;
}
} else {
while (CountPrim123--) {
pPrims->p1 = White.X + DivFD6(pPrims->p1, PrimMax);
pPrims->p1 = White.X + DivFD6(pPrims->p2, PrimMax);
pPrims->p3 = White.Z + DivFD6(pPrims->p3, PrimMax);
++pPrims;
}
}
}
#endif
VOID
HTENTRY
ComputeMonoLUT(
PDEVICECOLORINFO pDCI,
PCACHEBFLUT pCBFLUT,
PBFINFO pBFInfo,
LPWORD pLUT,
PDEVCLRADJ pDevClrAdj
)
/*++
Routine Description:
This function compute a RGB to Monochrome *L translation table.
Arguments:
pCBFLUT - Pointer to CACHEBFLUT data structure.
pBFInfo - Pointer to the BFINFO data structure which already computed
pLUT - Pointer to array of WORD which mapping table will be stored
pDevClrAdj - Pointer to DEVCLRADJ, the DCA_NEGATIVE and DCA_HAS_SRC_GAMMA
flags in pDevClrAdj->PrimAdj.Flags will always be turn off
at return.
Return Value:
VOID
Author:
05-Mar-1993 Fri 17:37:12 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LPWORD pIdxTable;
LPWORD pTmpIdx;
PMATRIX3x3 pRGBToXYZ = &(pDevClrAdj->PrimAdj.rgbCSXForm.M3x3);
BFINFO BFInfo = *pBFInfo;
RGBORDER RGBOrder;
FD6 RGBGamma[3];
FD6 Gamma;
FD6 PrimPower;
FD6 PrimInc;
DWORD Checksum;
DWORD Flags;
WORD LastIdx;
INT Index;
UINT PowerLoop;
UINT BitCount;
UINT XX0BitCount;
UINT RepXX0;
UINT XX0CopyLoop;
UINT PrimIdx;
UINT DupLoop;
UINT DupSize;
UINT Yi;
UINT Yrgb[3];
if ((Flags = pDevClrAdj->PrimAdj.Flags) & DCA_HAS_SRC_GAMMA) {
RGBGamma[0] = pDevClrAdj->PrimAdj.RGBGamma.R;
RGBGamma[1] = pDevClrAdj->PrimAdj.RGBGamma.G;
RGBGamma[2] = pDevClrAdj->PrimAdj.RGBGamma.B;
} else {
RGBGamma[0] =
RGBGamma[1] =
RGBGamma[2] = FD6_1;
}
pDevClrAdj->ca.caFlags &= ~(CLRADJF_NEGATIVE);
pDevClrAdj->ca.caRedGamma =
pDevClrAdj->ca.caGreenGamma =
pDevClrAdj->ca.caBlueGamma =
pDevClrAdj->ca.caIlluminantIndex = 0xFFFF;
pDevClrAdj->PrimAdj.Flags &= ~(DCA_NEGATIVE | DCA_HAS_SRC_GAMMA);
Checksum = (Flags & DCA_NEGATIVE) ? 'NLUT' : 'PLUT';
Checksum = ComputeChecksum((LPBYTE)pRGBToXYZ, Checksum, sizeof(MATRIX3x3));
Checksum = ComputeChecksum((LPBYTE)&RGBGamma, Checksum, sizeof(RGBGamma));
if (BFInfo.BitmapFormat == BMF_24BPP) {
//
// For 24bpp MONO our table will be
//
// wIdx[0][256] - 1st byte of RGBTRIPLE
// wIdx[1][256] - 2nd byte of RGBTRIPLE
// wIdx[2][256] - 3rd byte of RGBTRIPLE
//
RGBOrder.Index = BFInfo.RGBOrder.Index;
RGBOrder.Order[0] = BFInfo.RGBOrder.Order[2];
RGBOrder.Order[1] = BFInfo.RGBOrder.Order[1];
RGBOrder.Order[2] = BFInfo.RGBOrder.Order[0];
} else {
RGBOrder = BFInfo.RGBOrder;
Checksum = ComputeChecksum((LPBYTE)&(BFInfo.BitsRGB[0]),
Checksum,
sizeof(BFInfo.BitsRGB));
}
if ((!pCBFLUT->pLUT) || (pCBFLUT->Checksum != Checksum)) {
DBGP_IF(DBGP_CCT,
DBGP("** Re-Compute %ld bytes MONO BFInfo pLUT **"
ARGDW(BFInfo.SizeLUT)));
if (!pCBFLUT->pLUT) {
if (!(pCBFLUT->pLUT =
(LPBYTE)HTLocalAlloc((DWORD)PDCI_TO_PDHI(pDCI),
"MONO-LUT",
NONZEROLPTR,
BFInfo.SizeLUT))) {
DBGP_IF(DBGP_CCT,
DBGP("Allocate %ld bytes of MONO CBFLUT pLUT failed, Compute locally"
ARGDW(BFInfo.SizeLUT)));
}
}
pCBFLUT->Checksum = Checksum;
pCBFLUT->RGBOrderIndex = BFInfo.RGBOrder.Index;
if (!(pIdxTable = (LPWORD)pCBFLUT->pLUT)) {
pIdxTable = pLUT;
}
CopyMemory(pIdxTable, &(BFInfo.GrayShr[0]), SIZE_LUT_RSHIFT);
(LPBYTE)pIdxTable += SIZE_LUT_RSHIFT;
//
// Find out what percentage for each of RGB primary
//
Yi = (UINT)((Yrgb[0] = (UINT)MulFD6(pRGBToXYZ->m[Y_INDEX][R_INDEX],
COUNT_RGB_YTABLE - 1)) +
(Yrgb[1] = (UINT)MulFD6(pRGBToXYZ->m[Y_INDEX][G_INDEX],
COUNT_RGB_YTABLE - 1)) +
(Yrgb[2] = (UINT)MulFD6(pRGBToXYZ->m[Y_INDEX][B_INDEX],
COUNT_RGB_YTABLE - 1)));
if ((Yi -= (COUNT_RGB_YTABLE - 1)) > 0) {
--Yrgb[1];
if (--Yi > 0) {
--Yrgb[0];
}
if (--Yi > 0) {
--Yrgb[2];
}
}
//
// Checking the gamma first, we will make it 1.0 if it is equal to 0.0,
// also make so the RGB bits count will never greater than the one we
// cached.
//
for (Index = 2; Index >= 0; Index--) {
PrimIdx = (UINT)RGBOrder.Order[Index];
if ((BitCount = (UINT)BFInfo.BitCount[PrimIdx]) > BF_GRAY_BITS) {
BitCount = BF_GRAY_BITS;
}
if (BitCount) {
//
// If bitcount is zero then the remainding will be 0
//
Gamma = RGBGamma[PrimIdx];
if (BFInfo.Flags & BFIF_GRAY_XX0) {
XX0BitCount = BFInfo.RGB1stBit;
} else {
XX0BitCount = 0;
}
PowerLoop = (UINT)(1 << BitCount);
XX0CopyLoop = (UINT)((1 << XX0BitCount) - 1);
if ((DupLoop = (UINT)(BitCount + XX0BitCount)) < BF_GRAY_BITS) {
DupSize = (UINT)(sizeof(WORD) * (1 << DupLoop));
DupLoop = (UINT)((1 << (BF_GRAY_BITS - DupLoop)) - 1);
} else {
DupLoop = 0;
}
PrimInc = DivFD6(1, PowerLoop - 1);
Yi = Yrgb[PrimIdx];
pTmpIdx = pIdxTable;
if (Flags & DCA_NEGATIVE) {
PrimPower = FD6_1;
PrimInc = -PrimInc;
} else {
PrimPower = FD6_0;
}
DBGP_IF(DBGP_BFINFO,
DBGP("%u - [%u], Size=%u, G=%s +[%s], Yi=%4u, Dup: XX0=%ld, [%ld @%ld]"
ARGU(Index)
ARGU(PrimIdx)
ARGU(PowerLoop)
ARGFD6(Gamma, 1, 4)
ARGFD6(PrimInc, 1, 6)
ARGU(Yi)
ARGDW(XX0CopyLoop)
ARGDW(DupLoop)
ARGDW(DupSize)));
while (--PowerLoop) {
*pTmpIdx++ = (WORD)MulFD6(Power(PrimPower, Gamma), Yi);
PrimPower += PrimInc;
DBGP_IF(DBGP_BFINFO_TABLE,
DBGP("%3u = %4u : %s"
ARGU(PowerLoop)
ARGU(*(pTmpIdx - 1))
ARGFD6((PrimPower - PrimInc), 1, 6)));
if (XX0CopyLoop) {
LastIdx = *(pTmpIdx - 1);
RepXX0 = XX0CopyLoop;
while (RepXX0--) {
*pTmpIdx++ = LastIdx;
}
}
}
*pTmpIdx++ =
LastIdx = (WORD)((Flags & DCA_NEGATIVE) ? 0 : Yi);
while (XX0CopyLoop--) {
*pTmpIdx++ = LastIdx;
}
while (DupLoop--) {
CopyMemory(pTmpIdx, pIdxTable, DupSize);
(LPBYTE)pTmpIdx += DupSize;
(LPBYTE)pIdxTable += DupSize;
}
pIdxTable = pTmpIdx; // this is the next Y table
} else {
//
// Set every entry's Yi to the same as the first one
//
DupLoop = BF_GRAY_TABLE_COUNT;
Yi = (Flags & DCA_NEGATIVE) ? Yrgb[PrimIdx] : 0;
while (DupLoop--) {
*pIdxTable++ = Yi;
}
}
}
}
//
// Now Copy the cache to local instance memory
//
if (pCBFLUT->pLUT) {
if ((BFInfo.BitmapFormat == BMF_24BPP) &&
(pCBFLUT->RGBOrderIndex != BFInfo.RGBOrder.Index)) {
LPBYTE pOrder;
DBGP_IF(DBGP_CCT, DBGP("** Copy & Ordered CACHED MONO 24-bpp pLUT **"));
//
// We are 24bpp and RGB order is different, so just copy the
// the right order down to local copy
//
ZeroMemory(pLUT, SIZE_LUT_RSHIFT);
RGBOrder = RGBOrderTable[pCBFLUT->RGBOrderIndex];
pIdxTable = (LPWORD)(pCBFLUT->pLUT + SIZE_LUT_RSHIFT);
(LPBYTE)pLUT += SIZE_LUT_RSHIFT;
pOrder = &(BFInfo.RGBOrder.Order[0]);
DupLoop = 3;
while (DupLoop--) {
if (*pOrder == RGBOrder.Order[0]) {
CopyMemory(pLUT, pIdxTable, LUTSIZE_PER_CLR);
} else if (*pOrder == RGBOrder.Order[1]) {
CopyMemory(pLUT,
pIdxTable + (LUT_COUNT_PER_CLR * 1),
LUTSIZE_PER_CLR);
} else {
CopyMemory(pLUT,
pIdxTable + (LUT_COUNT_PER_CLR * 2),
LUTSIZE_PER_CLR);
}
pOrder++;
pLUT += LUT_COUNT_PER_CLR;
}
} else {
DBGP_IF(DBGP_CCT, DBGP(">>>>> Copy CACHED MONO pLUT"));
CopyMemory(pLUT, pCBFLUT->pLUT, BFInfo.SizeLUT);
}
}
}
VOID
HTENTRY
ComputeColorLUT(
PDEVICECOLORINFO pDCI,
PCACHEBFLUT pCBFLUT,
PBFINFO pBFInfo,
LPWORD pLUT,
PDEVCLRADJ pDevClrAdj
)
/*++
Routine Description:
This function compute the bit fields RGB --> HT555 indices translation
Arguments:
pCBFLUT - Pointer to CACHEBFLUT data structure.
pBFInfo - Ponter to the BFINFO data structure, the *pBFInfo must
already compute and validate by ValidateRGBBitFields()
function.
pLUT - Pointer to array of WORD to store color translation indices,
the size of enough.
pDevClrAdj - Pointer to DEVCLRADJ, the DCA_HAS_SRC_GAMMA flags in
pDevClrAdj->PrimAdj.Flags will always be turn off at return.
Return Value:
VOID
Author:
04-Mar-1993 Thu 14:52:44 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LPBYTE pPrims;
LPWORD pIdxY;
BFINFO BFInfo = *pBFInfo;
FD6 RGBGamma[3];
DWORD Checksum;
DWORD MaskR;
DWORD MaskG;
DWORD MaskB;
DW2W4B MaskRGB;
DW2W4B BitsR;
DW2W4B BitsG;
DW2W4B BitsB;
DWORD Flags;
INT YIdxAdd;
INT ShiftR;
INT ShiftG;
INT ShiftB;
INT BitLoop;
INT ByteLoop;
INT DupLoop;
WORD YAdd;
WORD YCur;
if (BFInfo.BitmapFormat == BMF_24BPP) {
if ((Flags = pDevClrAdj->PrimAdj.Flags) & DCA_HAS_SRC_GAMMA) {
RGBGamma[0] = pDevClrAdj->PrimAdj.RGBGamma.R;
RGBGamma[1] = pDevClrAdj->PrimAdj.RGBGamma.G;
RGBGamma[2] = pDevClrAdj->PrimAdj.RGBGamma.B;
} else {
RGBGamma[0] =
RGBGamma[1] =
RGBGamma[2] = FD6_1;
}
pDevClrAdj->PrimAdj.Flags &= ~(DCA_HAS_SRC_GAMMA | DCA_NEGATIVE);
pDevClrAdj->ca.caFlags &= ~CLRADJF_NEGATIVE;
pDevClrAdj->ca.caRedGamma =
pDevClrAdj->ca.caGreenGamma =
pDevClrAdj->ca.caBlueGamma = 0xFFFF;
Checksum = ComputeChecksum((LPBYTE)&RGBGamma,
(Flags & DCA_NEGATIVE) + 'HT24',
sizeof(RGBGamma));
} else {
Checksum = ComputeChecksum((LPBYTE)&BFInfo, 'CLUT', sizeof(BFINFO));
}
if ((!pCBFLUT->pLUT) || (pCBFLUT->Checksum != Checksum)) {
DBGP_IF(DBGP_CCT, DBGP("** Re-Compute %ld bytes COLOR BFInfo pLUT **"
ARGDW(BFInfo.SizeLUT)));
if (!pCBFLUT->pLUT) {
if (!(pCBFLUT->pLUT =
(LPBYTE)HTLocalAlloc((DWORD)PDCI_TO_PDHI(pDCI),
"COLOR-LUT",
NONZEROLPTR,
BFInfo.SizeLUT))) {
DBGP_IF(DBGP_CCT,
DBGP("Allocate %ld bytes of COLOR CBFLUT pLUT failed, Compute locally"
ARGDW(BFInfo.SizeLUT)));
}
}
pCBFLUT->Checksum = Checksum;
pCBFLUT->RGBOrderIndex = BFInfo.RGBOrder.Index;
if (!(pIdxY = (LPWORD)pCBFLUT->pLUT)) {
pIdxY = pLUT;
}
if (BFInfo.BitmapFormat == BMF_24BPP) {
FD6 Gamma;
static WORD RGBAdd[3] = { (WORD)(1 << HT_RGB_R_BITSTART),
(WORD)(1 << HT_RGB_G_BITSTART),
(WORD)(1 << HT_RGB_B_BITSTART) };
pPrims = &(RGBOrderTable[pCBFLUT->RGBOrderIndex].Order[0]);
ByteLoop = 3;
YIdxAdd = (Flags & DCA_NEGATIVE) ? -1 : 1;
DBGP_IF(DBGP_BFINFO,
DBGP("24-bit Table:s = [%u], pIdxY=%08lx, End=%08lx"
ARGU(ByteLoop)
ARGDW(pIdxY) ARGDW((LPBYTE)pIdxY + BFInfo.SizeLUT)));
while (ByteLoop--) {
FD6 NextY;
INT i;
INT LastDup;
INT CurDup;
INT DupTot;
DupTot = 0;
LastDup = 0;
YAdd = RGBAdd[*pPrims];
Gamma = RGBGamma[*pPrims];
YCur = 0;
BitLoop = (INT)HT_RGB_MAX_COUNT;
DBGP_IF(DBGP_CCT,
DBGP("ByteLoop=%ld, BitLoop=%ld, Gamma=%s, YAdd=%04lx"
ARGDW(ByteLoop)
ARGDW(BitLoop)
ARGFD6(Gamma, 1, 6)
ARGDW(YAdd)));
DBGP_IF(DBGP_CCT,
DBGP("pIdx=%08lx, New=%08lx"
ARGDW(pIdxY) ARGDW(pIdxY + (256 - 1))));
if (Flags & DCA_NEGATIVE) {
pIdxY += (256 - 1);
}
for (i = 1; i <= BitLoop; i++) {
NextY = AntiLog(DivFD6(Log(DivFD6((FD6)i, (FD6)BitLoop)),
Gamma));
CurDup = (INT)MulFD6(NextY, 256);
DupLoop = CurDup - LastDup;
LastDup = CurDup;
DupTot += DupLoop;
DBGP_IF(DBGP_BFINFO_TABLE,
DBGP("[%ld] - %2ld: NextY=%s, CurDup=%3ld, DupLoop=%3ld, DupTot=%3ld, YCur=%ld"
ARGDW(ByteLoop)
ARGDW(i)
ARGFD6(NextY, 1, 6)
ARGDW(CurDup)
ARGDW(DupLoop)
ARGDW(DupTot)
ARGDW(YCur)));
while (DupLoop--) {
*pIdxY = YCur;
pIdxY += YIdxAdd;
}
YCur += YAdd;
}
ASSERT(DupTot == 256);
DBGP_IF(DBGP_CCT,
DBGP(" pIdx=%08lx, New=%08lx"
ARGDW(pIdxY) ARGDW(pIdxY + (256 + 1))));
if (Flags & DCA_NEGATIVE) {
pIdxY += (256 + 1);
}
++pPrims;
}
} else {
if (BFInfo.BitmapFormat == BMF_16BPP) {
ByteLoop = 2;
BitsR.w[0] = (WORD)(BFInfo.BitsRGB[0] & 0xffff);
BitsG.w[0] = (WORD)(BFInfo.BitsRGB[1] & 0xffff);
BitsB.w[0] = (WORD)(BFInfo.BitsRGB[2] & 0xffff);
BitsR.w[1] =
BitsG.w[1] =
BitsB.w[1] = 0;
} else {
//
// 32-bit version
//
ByteLoop = 4;
BitsR.dw = BFInfo.BitsRGB[0];
BitsG.dw = BFInfo.BitsRGB[1];
BitsB.dw = BFInfo.BitsRGB[2];
}
//
// Now find out how to to shift for the HT555 table
//
ShiftR = (INT)(((INT)BFInfo.BitCount[0] - (INT)HT_RGB_BITCOUNT) +
((INT)BFInfo.BitStart[0] - (INT)HT_RGB_R_BITSTART));
ShiftG = (INT)(((INT)BFInfo.BitCount[1] - (INT)HT_RGB_BITCOUNT) +
((INT)BFInfo.BitStart[1] - (INT)HT_RGB_G_BITSTART));
ShiftB = (INT)(((INT)BFInfo.BitCount[2] - (INT)HT_RGB_BITCOUNT) +
((INT)BFInfo.BitStart[2] - (INT)HT_RGB_B_BITSTART));
pPrims = (LPBYTE)&(MaskRGB.b[0]);
DBGP_IF(DBGP_BFINFO,
DBGP("HT555 Shifts = [%u] %d:%d:%d"
ARGU(ByteLoop) ARGI(ShiftR) ARGI(ShiftG) ARGI(ShiftB)));
while (ByteLoop--) {
MaskRGB.dw = 0;
BitLoop = 256;
while (BitLoop--) {
if (MaskR = (MaskRGB.dw & BitsR.dw)) {
MaskR = (DWORD)(((ShiftR < 0) ? (MaskR << -ShiftR) :
(MaskR >> ShiftR)) &
HT_RGB_R_BITMASK);
}
if (MaskG = (MaskRGB.dw & BitsG.dw)) {
MaskG = (DWORD)(((ShiftG < 0) ? (MaskG << -ShiftG) :
(MaskG >> ShiftG)) &
HT_RGB_G_BITMASK);
}
if (MaskB = (MaskRGB.dw & BitsB.dw)) {
MaskB = (DWORD)(((ShiftB < 0) ? (MaskB << -ShiftB) :
(MaskB >> ShiftB)) &
HT_RGB_B_BITMASK);
}
DBGP_IF(DBGP_BFINFO_TABLE,
DBGP("%2u:%3u [%08lx] = %04x [%04x | %04x | %04x]"
ARGU(ByteLoop)
ARGU(255 - BitLoop)
ARGDW(MaskRGB.dw)
ARGU(MaskR | MaskG | MaskB)
ARGU(MaskR)
ARGU(MaskG)
ARGU(MaskB)));
*pIdxY++ = (WORD)(MaskR | MaskG | MaskB);
++(*pPrims);
}
++pPrims;
}
}
}
if (pCBFLUT->pLUT) {
if ((BFInfo.BitmapFormat == BMF_24BPP) &&
(pCBFLUT->RGBOrderIndex != BFInfo.RGBOrder.Index)) {
RGBORDER RGBOrder;
DBGP_IF(DBGP_CCT, DBGP("** Copy & Ordered CACHED 24-bpp COLOR pLUT **"));
//
// We are 24bpp and RGB order is different, so just copy the
// the right order down to local copy
//
RGBOrder = RGBOrderTable[pCBFLUT->RGBOrderIndex];
pPrims = &(BFInfo.RGBOrder.Order[0]);
DupLoop = 3;
while (DupLoop--) {
if (*pPrims == RGBOrder.Order[0]) {
CopyMemory(pLUT, pCBFLUT->pLUT, LUTSIZE_PER_CLR);
} else if (*pPrims == RGBOrder.Order[1]) {
CopyMemory(pLUT,
pCBFLUT->pLUT + (LUTSIZE_PER_CLR * 1),
LUTSIZE_PER_CLR);
} else {
CopyMemory(pLUT,
pCBFLUT->pLUT + (LUTSIZE_PER_CLR * 2),
LUTSIZE_PER_CLR);
}
++pPrims;
pLUT += LUT_COUNT_PER_CLR;
}
} else {
DBGP_IF(DBGP_CCT, DBGP(">>>>>> Copy CACHED COLOR pLUT"));
CopyMemory(pLUT, pCBFLUT->pLUT, BFInfo.SizeLUT);
}
}
}
#if NO_NEGATIVE_RGB_SCALE
VOID
HTENTRY
ScaleRGB(
PFD6 pRGB
)
/*++
Routine Description:
This function scale out of range RGB back into range and taking the
lumminance of the color into consideration.
if any of RGB is less then 0.0 then it will first clamp that to 0.0 and
it only scale if any of RGB is greater then 1.0
Arguments:
pRGB - Pointer to RGB (FD6) prims to be adjust
Return Value:
VOID
Author:
08-Mar-1995 Wed 19:19:33 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PFD6 pRGBTmp;
FD6 MaxClr;
INT Idx;
DEFDBGVAR(FD6, RGBOld[3])
DEFDBGVAR(BOOL, Negative = FALSE)
Idx = 3;
pRGBTmp = pRGB;
MaxClr = FD6_1;
while (Idx--) {
FD6 CurClr;
//
// Firstable Clamp the negative component
//
if ((CurClr = *pRGBTmp) < FD6_0) {
*pRGBTmp = FD6_0;
SETDBGVAR(Negative, TRUE);
} else if (CurClr > MaxClr) {
MaxClr = CurClr;
}
++pRGBTmp;
SETDBGVAR(RGBOld[Idx], CurClr);
}
if (MaxClr > FD6_1) {
//
// Now Scale it
//
*pRGB++ = DivFD6(*pRGB, MaxClr);
*pRGB++ = DivFD6(*pRGB, MaxClr);
*pRGB = DivFD6(*pRGB, MaxClr);
DBGP_IF(DBGP_SCALE_RGB,
DBGP("ScaleRGB: %s:%s:%s -> %s:%s:%s, Max=%s%s"
ARGFD6(RGBOld[2], 1, 6)
ARGFD6(RGBOld[1], 1, 6)
ARGFD6(RGBOld[0], 1, 6)
ARGFD6(*(pRGB - 2), 1, 6)
ARGFD6(*(pRGB - 1), 1, 6)
ARGFD6(*(pRGB ), 1, 6)
ARGFD6(MaxClr, 1, 6)
ARG((Negative) ? "*NEG CLAMP*" : "")));
} else {
DBGP_IF(DBGP_SCALE_RGB,
{
if (Negative) {
DBGP("*NEG CLAMP ONLY* ScaleRGB: %s:%s:%s -> %s:%s:%s"
ARGFD6(RGBOld[2], 1, 6)
ARGFD6(RGBOld[1], 1, 6)
ARGFD6(RGBOld[0], 1, 6)
ARGFD6(*(pRGB ), 1, 6)
ARGFD6(*(pRGB + 1), 1, 6)
ARGFD6(*(pRGB + 2), 1, 6));
}
}
)
}
}
#else
VOID
HTENTRY
ScaleRGB(
PFD6 pRGB,
PFD6 pYrgb
)
/*++
Routine Description:
This function scale out of range RGB back into range and taking the
lumminance of the color into consideration.
if any of RGB is less then 0.0 then it will first clamp that to 0.0 and
it only scale if any of RGB is greater then 1.0
Arguments:
pRGB - Pointer to RGB (FD6) prims to be adjust
pYrgb - Pinter to the Luminance (FD6) of the RGB, if NULL then it is not
used in the computation
Return Value:
VOID
Author:
08-Mar-1995 Wed 19:19:33 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
FD6 MaxClr = FD6_1;
FD6 MinClr = FD6_10;
FD6 RGBNew[3];
FD6 RGBOld[3];
if ((RGBOld[0] = pRGB[0]) > (RGBOld[1] = pRGB[1])) {
MaxClr = RGBOld[0];
MinClr = RGBOld[1];
} else {
MaxClr = RGBOld[1];
MinClr = RGBOld[0];
}
if ((RGBOld[2] = pRGB[2]) > MaxClr) {
MaxClr = RGBOld[2];
}
if (RGBOld[2] < MinClr) {
MinClr = RGBOld[2];
}
if ((MaxClr <= FD6_1) && (MinClr >= FD6_0)) {
return;
}
if (MinClr >= FD6_1) {
DBGP_IF((DBGP_SCALE_RGB | DBGP_SCALE_RGB),
DBGP("** RGB %s:%s:%s is too LIGHT make it WHITE"
ARGFD6(RGBOld[0], 1, 6)
ARGFD6(RGBOld[1], 1, 6)
ARGFD6(RGBOld[2], 1, 6)));
pRGB[0] =
pRGB[1] =
pRGB[2] = FD6_1;
return;
}
if (MaxClr <= FD6_0) {
DBGP_IF((DBGP_SCALE_RGB | DBGP_SCALE_RGB),
DBGP("** RGB %s:%s:%s is too DARK make it BLACK"
ARGFD6(RGBOld[0], 1, 6)
ARGFD6(RGBOld[1], 1, 6)
ARGFD6(RGBOld[2], 1, 6)));
pRGB[0] =
pRGB[1] =
pRGB[2] = FD6_0;
return;
}
if (MaxClr < FD6_1) {
MaxClr = FD6_1;
}
if (MinClr > FD6_0) {
MinClr = FD6_0;
}
MaxClr -= MinClr;
RGBNew[0] = DivFD6(RGBOld[0] - MinClr, MaxClr);
RGBNew[1] = DivFD6(RGBOld[1] - MinClr, MaxClr);
RGBNew[2] = DivFD6(RGBOld[2] - MinClr, MaxClr);
DBGP_IF(DBGP_SCALE_RGB,
DBGP("ScaleRGB: %s:%s:%s -> %s:%s:%s, (%s/%s, %s)"
ARGFD6(RGBOld[0], 1, 6)
ARGFD6(RGBOld[1], 1, 6)
ARGFD6(RGBOld[2], 1, 6)
ARGFD6(RGBNew[0], 1, 6)
ARGFD6(RGBNew[1], 1, 6)
ARGFD6(RGBNew[2], 1, 6)
ARGFD6(MinClr, 1, 6)
ARGFD6(MaxClr + MinClr, 1, 6)
ARGFD6(MaxClr, 1, 6)));
if (pYrgb) {
FD6 OldY;
if ((OldY = MulFD6(RGBOld[0], pYrgb[0]) +
MulFD6(RGBOld[1], pYrgb[1]) +
MulFD6(RGBOld[2], pYrgb[2])) <= FD6_0) {
DBGP_IF(DBGP_SHOWXFORM_RGB,
DBGP("OldY <= 0.0 (%s), Ignore and NO Y Scale"
ARGFD6(OldY, 2, 6)));
} else if (OldY >= FD6_1) {
DBGP_IF(DBGP_SHOWXFORM_RGB,
DBGP("OldY >= 1.0 (%s), Ignore and NO Y Scale"
ARGFD6(OldY, 2, 6)));
} else {
FD6 NewY;
FD6 CurRatio;
FD6 MaxRatio;
NewY = MulFD6(RGBNew[0], pYrgb[0]) +
MulFD6(RGBNew[1], pYrgb[1]) +
MulFD6(RGBNew[2], pYrgb[2]);
DBGP_IF(DBGP_SHOWXFORM_RGB,
DBGP("RGBOld=%s:%s:%s [Y=%s] --> New=%s:%s:%s [Y=%s]"
ARGFD6(pRGB[0], 1, 6)
ARGFD6(pRGB[1], 1, 6)
ARGFD6(pRGB[2], 1, 6)
ARGFD6(OldY, 1, 6)
ARGFD6(RGBNew[0], 1, 6)
ARGFD6(RGBNew[1], 1, 6)
ARGFD6(RGBNew[2], 1, 6)
ARGFD6(NewY, 1, 6)));
if (OldY != NewY) {
MaxClr = (RGBNew[0] > RGBNew[1]) ? RGBNew[0] : RGBNew[1];
if (RGBNew[2] > MaxClr) {
MaxClr = RGBNew[2];
}
MaxRatio = DivFD6(FD6_1, MaxClr);
CurRatio = DivFD6(OldY, NewY);
if (CurRatio > MaxRatio) {
CurRatio = MaxRatio;
}
RGBNew[0] = MulFD6(RGBNew[0], CurRatio);
RGBNew[1] = MulFD6(RGBNew[1], CurRatio);
RGBNew[2] = MulFD6(RGBNew[2], CurRatio);
DBGP_IF(DBGP_SHOWXFORM_RGB,
DBGP("CurRatio%s, MaxRatio=%s, MaxClr=%s"
ARGFD6(CurRatio, 1, 6)
ARGFD6(MaxRatio, 1, 6)
ARGFD6(MaxClr, 1, 6)));
}
}
}
//
// Save back and return
//
pRGB[0] = RGBNew[0];
pRGB[1] = RGBNew[1];
pRGB[2] = RGBNew[2];
}
#endif
LONG
HTENTRY
ColorTriadSrcToDev(
PDEVICECOLORINFO pDCI,
CTSTD_UNION CTSTDUnion,
LPWORD pAbort,
PCOLORTRIAD pSrcClrTriad,
LPVOID pDevColorTable,
PDEVCLRADJ pDevClrAdj
)
/*++
Routine Description:
This functions set up all the DECI4 value in PRIMRGB, PRIMCMY with
PowerGamma, Brightness, Contrast adjustment and optionally to transform
to C.I.E. color space and/or do the Colorfulness adjustment.
Arguments:
RGBToPrim - RGBTOPRIM data structure, it contans the data to
instruct how source/destination RGB convesions should
be computed.
rgbMax - Input RGB value's maximum intensity, it used to
normalized input RGB value if they are not normalized.
ColorCount - count of input RGB values (pointed by pSrcRGB) to be
computed.
pSrcRGB - Pointer to the source RGB color values array, the size
of each RGB entry is specified in RGBTOPRIM data
structure, and count of this array is specified by the
ColorCount.
pDevPrim - Pointer to the device primaries array, the size of each
entry is specified in RGBTOPRIM data structure, and count
of this array is specified by the ColorCount.
pDevClrAdj - Pointer to the pre-computed DEVCLRADJ data structure.
Return Value:
Return value boolean.
TRUE: If the final color is NON-WHITE
FALSE: if the final color is WHITE
Author:
30-Jan-1991 Wed 13:31:58 created -by- Daniel Chou (danielc)
Revision History:
06-Feb-1992 Thu 21:39:46 updated -by- Daniel Chou (danielc)
Rewrite!
02-Feb-1994 Wed 17:33:55 updated -by- Daniel Chou (danielc)
Remove unreferenced/unused variable L
10-May-1994 Tue 11:24:16 updated -by- Daniel Chou (danielc)
Bug# 13329, Memory Leak, Free Up pR_XYZ which I fogot to free it after
allocated it.
--*/
{
PFD6 pPrimA;
PFD6 pPrimB;
PFD6 pPrimC;
LPBYTE pSrcPrims;
LPBYTE pDevPrims;
PCACHERGBTOXYZ pCRTX;
PFD6XYZ pR_XYZ = NULL;
PFD6XYZ pG_XYZ;
PFD6XYZ pB_XYZ;
PFD6 pPrims;
COLORTRIAD SrcClrTriad = *pSrcClrTriad;
DEVCLRADJ DevClrAdj = *pDevClrAdj;
COLORSPACEXFORM DevCSXForm;
MATRIX3x3 CMYDyeMasks;
PREGRESS pRegress;
DWORD Loop;
DWORD CRTXChecksum;
FD6 DevRefY;
FD6 Prim[3];
FD6 X;
FD6 Y;
FD6 Z;
FD6 AU;
FD6 BV;
FD6 U1;
FD6 V1;
FD6 X15Y3Z;
FD6 L13;
FD6 fX;
FD6 fY;
FD6 fZ;
FD6 p0;
FD6 p1;
FD6 p2;
FD6 C;
FD6 W;
FD6 VGA16_80h;
FD6 VGA16_c0h;
FD6 DevRGBGamma;
FD6 DevClrMax;
FD6 MinFD6Clr;
FD6 AutoPrims[3];
MULDIVPAIR MDPairs[4];
MULDIVPAIR AUMDPairs[3];
MULDIVPAIR BVMDPairs[3];
PRIMCOLOR PrimColor;
HTPRIMOFFSET HTPrimOffset;
INT SrcPrimType;
INT DevBytesPerPrimary;
INT DevBytesPerEntry;
INT OffsetPrim1;
INT OffsetPrim2;
INT OffsetPrim3;
INT TempI;
INT TempJ;
INT TempK;
UINT ColorSpace;
BOOL NegatePrims;
BOOL SkipLAB;
BOOL MonoPrim;
WORD RegressFlags;
BYTE RCube;
BYTE GCube;
BYTE BCube;
BYTE RIdx;
BYTE GIdx;
BYTE BIdx;
BYTE H_WIdx;
BYTE L_WIdx;
BYTE H_PIdx;
BYTE L_PIdx;
BYTE H_MIdx;
BYTE L_MIdx;
BYTE WRange;
BYTE CRange;
BYTE CHRange;
BYTE CLRange;
DEFDBGVAR(WORD, ClrNo)
DEFDBGVAR(BYTE, dbgR)
DEFDBGVAR(BYTE, dbgG)
DEFDBGVAR(BYTE, dbgB)
SETDBGVAR(ClrNo, 0);
//
// Two possible cases:
//
// A: The transform is used for color adjustment only, this is for
// HT_AdjustColorTable API call
//
// B: The halftone is taking places, the final output will be either
// Prim1/2 or Prim1/2/3 and each primary must 1 byte long.
//
pRegress = (DevClrAdj.PrimAdj.Flags & DCA_IS_BRUSH) ?
&(DevClrAdj.pClrXFormBlock->RegressBrush) :
&(DevClrAdj.pClrXFormBlock->Regress);
RegressFlags = pRegress->Flags;
DevClrMax = (FD6)pRegress->DataCount;
DevRGBGamma = DevClrAdj.pClrXFormBlock->DevRGBGamma;
ZeroMemory(&PrimColor, sizeof(PRIMCOLOR));
if (pDevColorTable) {
DevBytesPerEntry = (INT)sizeof(PRIMCOLOR);
DevBytesPerPrimary = 1;
switch(CTSTDUnion.b.BMFDest) {
case BMF_1BPP:
DevBytesPerEntry = (INT)sizeof(PRIMMONO);
CTSTDUnion.b.DestOrder = PRIMARY_ORDER_123; // in order
DevClrAdj.PrimAdj.Flags |= DCA_MONO_ONLY;
break;
case BMF_1BPP_3PLANES:
case BMF_4BPP:
break;
case BMF_4BPP_VGA16:
CTSTDUnion.b.DestOrder = PRIMARY_ORDER_BGR;
VGA16_80h = DevClrAdj.pClrXFormBlock->VGA16_80h;
VGA16_c0h = DevClrAdj.pClrXFormBlock->VGA16_c0h;
DBGP_IF(DBGP_PRIMARY_ORDER,
DBGP("VGA16 Gamma Correction: 80h=%s, c0h=%s"
ARGFD6(VGA16_80h, 1, 6)
ARGFD6(VGA16_c0h, 1, 6)));
break;
case BMF_8BPP_VGA256:
CTSTDUnion.b.DestOrder = PRIMARY_ORDER_BGR;
break;
case BMF_16BPP_555:
break;
}
} else {
if (SrcClrTriad.Type != COLOR_TYPE_RGB) {
return(HTERR_INVALID_COLOR_TYPE);
}
CTSTDUnion.b.BMFDest = BMF_8BPP;
DevClrAdj.PrimAdj.Flags &= (WORD)~DCA_NEED_DYES_CORRECTION;
pDevColorTable = SrcClrTriad.pColorTable;
CTSTDUnion.b.DestOrder = SrcClrTriad.PrimaryOrder;
DevClrMax = (FD6)SrcClrTriad.PrimaryValueMax;
DevBytesPerEntry = (INT)SrcClrTriad.BytesPerEntry;
DevBytesPerPrimary = (INT)SrcClrTriad.BytesPerPrimary;
}
//
// If the total color table entries is less than MIN_CCT_COLORS then
// we just compute the color directly
//
pCRTX = (SrcClrTriad.ColorTableEntries > MIN_CCT_COLORS) ?
DevClrAdj.pCRTXLevel255 : NULL;
if (DevClrAdj.PrimAdj.Flags & DCA_MONO_ONLY) {
//
// No dye correction for the monochrome
//
DevClrAdj.PrimAdj.Flags &= ~DCA_NEED_DYES_CORRECTION;
}
if (DevClrAdj.PrimAdj.Flags & DCA_NEED_DYES_CORRECTION) {
CMYDyeMasks = DevClrAdj.pClrXFormBlock->CMYDyeMasks;
}
if (DevClrAdj.PrimAdj.Flags & DCA_IS_BRUSH) {
DevRefY = FD6_1;
} else {
DevRefY = DevClrAdj.pClrXFormBlock->DevCIEPrims.Yw;
}
//
// Check how to handle the final primary
//
if (RegressFlags & REGF_Y2X_IS_DENSITY) {
NegatePrims = (BOOL)(DevClrAdj.PrimAdj.Flags & DCA_USE_ADDITIVE_PRIMS);
} else {
NegatePrims = !(BOOL)(DevClrAdj.PrimAdj.Flags & DCA_USE_ADDITIVE_PRIMS);
}
MinFD6Clr = FD6DivL(FD6_1, (LONG)DevClrMax << 1);
DBGP_IF(DBGP_CCT,
DBGP("Flags=%08lx, DestFormat=%u, DevClrMax=%d, DevRGBGamma=%s"
ARGDW(DevClrAdj.PrimAdj.Flags)
ARGU(CTSTDUnion.b.BMFDest)
ARGDW(DevClrMax)
ARGFD6(DevRGBGamma, 1, 6)));
//
// Compute how to get source Prims
//
pSrcPrims = (LPBYTE)SrcClrTriad.pColorTable;
pDevPrims = (LPBYTE)pDevColorTable;
//
// Compute how to set destination Prims
//
HTPrimOffset = HTPrimOffsetTable[CTSTDUnion.b.DestOrder];
OffsetPrim1 = (INT)HTPrimOffset.Offset1 * DevBytesPerPrimary;
OffsetPrim2 = (INT)HTPrimOffset.Offset2 * DevBytesPerPrimary;
OffsetPrim3 = (INT)HTPrimOffset.Offset3 * DevBytesPerPrimary;
DBGP_IF(DBGP_PRIMARY_ORDER,
DBGP(" DEST PrimaryOrder: %u [%u] - %u:%u:%u = %2u:%2u:%2u"
ARGU(CTSTDUnion.b.DestOrder)
ARGU(HTPrimOffset.Order)
ARGU(HTPrimOffset.Offset1)
ARGU(HTPrimOffset.Offset2)
ARGU(HTPrimOffset.Offset3)
ARGU(OffsetPrim1)
ARGU(OffsetPrim2)
ARGU(OffsetPrim3)));
//
// Compute how to get source Prims
//
HTPrimOffset = HTPrimOffsetTable[SrcClrTriad.PrimaryOrder];
pPrimA = &Prim[HTPrimOffset.Offset1];
pPrimB = &Prim[HTPrimOffset.Offset2];
pPrimC = &Prim[HTPrimOffset.Offset3];
DBGP_IF(DBGP_PRIMARY_ORDER,
DBGP("SOURCE PrimaryOrder: %u [%u] - %u:%u:%u"
ARGU(SrcClrTriad.PrimaryOrder)
ARGU(HTPrimOffset.Order)
ARGU(HTPrimOffset.Offset1)
ARGU(HTPrimOffset.Offset2)
ARGU(HTPrimOffset.Offset3)));
//
// Now compute the cache info
//
if (SrcClrTriad.Type == COLOR_TYPE_YIQ) {
//
// Set New transform matrix and set the color table type back to
// RGB for easy coding
//
ConcatTwoMatrix3x3(&YIQToRGB,
&(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
&(DevClrAdj.PrimAdj.rgbCSXForm.M3x3));
DevClrAdj.PrimAdj.Flags &= (WORD)~DCA_HAS_SRC_GAMMA; // no gamma
SrcClrTriad.Type = COLOR_TYPE_RGB;
pCRTX = NULL;
}
switch(SrcClrTriad.BytesPerPrimary) {
case 0:
SrcClrTriad.BytesPerEntry = 0; // stay there!!
if (DevClrAdj.PrimAdj.Flags & DCA_MONO_ONLY) {
SrcPrimType = SRC_BF_HT_MONO;
SrcClrTriad.PrimaryValueMax = (FD6)(COUNT_RGB_YTABLE - 1);
pCRTX = NULL;
} else {
SrcPrimType = SRC_BF_HT_RGB;
SrcClrTriad.PrimaryValueMax = HT_RGB_MAX_MASK;
pCRTX = DevClrAdj.pCRTXLevel31;
}
break;
case 1:
SrcPrimType = SRC_TABLE_BYTE;
break;
case 2:
SrcPrimType = SRC_TABLE_WORD;
break;
case 4:
SrcPrimType = SRC_TABLE_DWORD;
break;
default:
return(INTERR_INVALID_SRCRGB_SIZE);
}
ColorSpace = (UINT)DevClrAdj.pClrXFormBlock->ColorSpace;
DevCSXForm = DevClrAdj.pClrXFormBlock->DevCSXForm;
if (((ColorSpace == CIELUV_1976) &&
((DevClrAdj.PrimAdj.rgbCSXForm.xW != DevCSXForm.xW) ||
(DevClrAdj.PrimAdj.rgbCSXForm.yW != DevCSXForm.yW))) ||
(DevClrAdj.PrimAdj.Flags & (DCA_HAS_COLOR_ADJ |
DCA_HAS_TINT_ADJ |
DCA_MONO_ONLY))) {
if (!(SkipLAB = (BOOL)(DevClrAdj.PrimAdj.Flags & DCA_MONO_ONLY))) {
TempI = 1;
TempJ = (ColorSpace == CIELUV_1976) ? MULDIV_HAS_DIVISOR :
MULDIV_NO_DIVISOR;
C = FD6_1;
if (DevClrAdj.PrimAdj.Flags & DCA_HAS_COLOR_ADJ) {
AU =
BV = DevClrAdj.PrimAdj.Color;
} else {
AU =
BV = FD6_1;
}
if (DevClrAdj.PrimAdj.Flags & DCA_HAS_TINT_ADJ) {
if (ColorSpace == CIELAB_1976) {
AU = FD6xL(AU, 500);
BV = FD6xL(BV, 200);
}
TempI = 2;
TempJ = MULDIV_HAS_DIVISOR;
C = DevClrAdj.PrimAdj.TintSinAngle;
AUMDPairs[2].Pair1.Mul = MulFD6(BV, -C);
BVMDPairs[2].Pair1.Mul = MulFD6(AU, C);
C = DevClrAdj.PrimAdj.TintCosAngle;
MAKE_MULDIV_DVSR(AUMDPairs, (FD6)500000000);
MAKE_MULDIV_DVSR(BVMDPairs, (FD6)200000000);
}
AUMDPairs[1].Pair1.Mul = MulFD6(AU, C);
BVMDPairs[1].Pair1.Mul = MulFD6(BV, C);
MAKE_MULDIV_INFO(AUMDPairs, TempI, TempJ);
MAKE_MULDIV_INFO(BVMDPairs, TempI, TempJ);
}
} else {
//
// Since we skip LAB, we will merge transforms RGB->XYZ and XYZ->RGB
// to form a transformation of RGB->RGB
//
SkipLAB = TRUE;
p0 = DivFD6(oRefXw, iRefXw);
CIE_Xr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) =
MulFD6(CIE_Xr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3), p0);
CIE_Xg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) =
MulFD6(CIE_Xg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3), p0);
CIE_Xb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) =
MulFD6(CIE_Xb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3), p0);
p0 = DivFD6(oRefZw, iRefZw);
CIE_Zr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) =
MulFD6(CIE_Zr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3), p0);
CIE_Zg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) =
MulFD6(CIE_Zg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3), p0);
CIE_Zb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) =
MulFD6(CIE_Zb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3), p0);
ConcatTwoMatrix3x3(&(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
&(DevClrAdj.pClrXFormBlock->DevCSXForm.M3x3),
&(DevClrAdj.PrimAdj.rgbCSXForm.M3x3));
DevClrAdj.PrimAdj.rgbCSXForm.WhiteXYZ.X =
CIE_Xr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) +
CIE_Xg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) +
CIE_Xb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3);
DevClrAdj.PrimAdj.rgbCSXForm.WhiteXYZ.Y =
CIE_Yr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) +
CIE_Yg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) +
CIE_Yb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3);
DevClrAdj.PrimAdj.rgbCSXForm.WhiteXYZ.Z =
CIE_Zr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) +
CIE_Zg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3) +
CIE_Zb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3);
}
DBGP_IF(DBGP_SCALE_RGB,
DBGP("Yrgb = %s:%s:%s"
ARGFD6(DevCSXForm.Yrgb.R, 1, 6)
ARGFD6(DevCSXForm.Yrgb.G, 1, 6)
ARGFD6(DevCSXForm.Yrgb.B, 1, 6)));
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP("iUVw = %s,%s, iRefXYZ = %s, %s, %s"
ARGFD6(iUw, 1, 6)
ARGFD6(iVw, 1, 6)
ARGFD6(iRefXw, 1, 6)
ARGFD6(iRefYw, 1, 6)
ARGFD6(iRefZw, 1, 6)));
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP("oUVw = %s,%s, oRefXYZ = %s, %s, %s"
ARGFD6(oUw, 1, 6)
ARGFD6(oVw, 1, 6)
ARGFD6(oRefXw, 1, 6)
ARGFD6(oRefYw, 1, 6)
ARGFD6(oRefZw, 1, 6)));
if (pCRTX) {
DBGP_IF(DBGP_CCT,
DBGP("*** Allocate %u bytes RGB->XYZ xform table ***"
ARGU(pCRTX->SizeCRTX)));
if (pR_XYZ = (PFD6XYZ)HTLocalAlloc((DWORD)PDCI_TO_PDHI(pDCI),
"R_XYZ",
NONZEROLPTR,
pCRTX->SizeCRTX)) {
Loop = (DWORD)(pCRTX->PrimMax + 1);
pCRTX = CacheRGBToXYZ(pDCI,
pCRTX,
pR_XYZ,
&CRTXChecksum,
&DevClrAdj);
pG_XYZ = pR_XYZ + Loop;
pB_XYZ = pG_XYZ + Loop;
SrcClrTriad.PrimaryValueMax = 0;
DBGP_IF(DBGP_CCT, DBGP("*** Has RGB->XYZ xform table ***"));
} else {
DBGP_IF(DBGP_CCT, DBGP("Allocate RGB->XYZ xform table failed !!"));
}
}
if (SrcClrTriad.PrimaryValueMax == (LONG)FD6_1) {
SrcClrTriad.PrimaryValueMax = 0;
}
//
// Starting the big Loop, reset AutoCur = AutoMax so it recycle back to
// 0:0:0
//
MAKE_MULDIV_SIZE(MDPairs, 3);
MAKE_MULDIV_FLAG(MDPairs, MULDIV_NO_DIVISOR);
AutoPrims[0] =
AutoPrims[1] =
AutoPrims[2] = FD6_0;
Loop = SrcClrTriad.ColorTableEntries;
DBGP_IF(DBGP_CCT,
DBGP("Compute %ld COLOR of %s type [%08lx]"
ARGDW(Loop)
ARG(pSrcPrimTypeName[SrcPrimType])
ARGDW(pSrcPrims)));
while (Loop--) {
switch(SrcPrimType) {
case SRC_BF_HT_MONO:
Prim[0] =
Prim[1] =
Prim[2] = AutoPrims[0];
if (++AutoPrims[0] > (FD6)COUNT_RGB_YTABLE) {
DBGP_IF(DBGP_CCT,
DBGP("Extra %ld ColorTableEntries: COPY WHITE"
ARGDW(Loop+1)));
do {
CopyMemory(pDevPrims,
pDevPrims - DevBytesPerEntry,
DevBytesPerEntry);
pDevPrims += DevBytesPerEntry;
} while (Loop--);
Loop = 0;
continue; // exit now
}
break;
case SRC_BF_HT_RGB:
//
// This format always in BGR order
//
Prim[0] = AutoPrims[0]; // R
Prim[1] = AutoPrims[1]; // G
Prim[2] = AutoPrims[2]; // B
if (++AutoPrims[0] > (FD6)HT_RGB_MAX_MASK) {
AutoPrims[0] = FD6_0;
if (++AutoPrims[1] > (FD6)HT_RGB_MAX_MASK) {
AutoPrims[1] = FD6_0;
if (++AutoPrims[2] > (FD6)HT_RGB_MAX_MASK) {
AutoPrims[2] = FD6_0;
}
}
}
DBGP_IF(DBGP_SHOWXFORM_ALL, DBGP("HT555: Prim[3]= %2ld:%2ld:%2ld, Auto[3]=%2ld:%2ld:%2ld [%ld]"
ARGDW(Prim[2])
ARGDW(Prim[1])
ARGDW(Prim[0])
ARGDW(AutoPrims[2])
ARGDW(AutoPrims[1])
ARGDW(AutoPrims[0])
ARGDW(HT_RGB_MAX_MASK)));
break;
case SRC_TABLE_BYTE:
*pPrimA = (FD6)(*(LPBYTE)(pSrcPrims ));
*pPrimB = (FD6)(*(LPBYTE)(pSrcPrims + (sizeof(BYTE) * 1)));
*pPrimC = (FD6)(*(LPBYTE)(pSrcPrims + (sizeof(BYTE) * 2)));
break;
case SRC_TABLE_WORD:
*pPrimA = (FD6)(*(LPSHORT)(pSrcPrims ));
*pPrimB = (FD6)(*(LPSHORT)(pSrcPrims + (sizeof(SHORT) * 1)));
*pPrimC = (FD6)(*(LPSHORT)(pSrcPrims + (sizeof(SHORT) * 2)));
break;
case SRC_TABLE_DWORD:
*pPrimA = (FD6)(*(PFD6)(pSrcPrims ));
*pPrimB = (FD6)(*(PFD6)(pSrcPrims + (sizeof(FD6) * 1)));
*pPrimC = (FD6)(*(PFD6)(pSrcPrims + (sizeof(FD6) * 2)));
break;
}
pSrcPrims += SrcClrTriad.BytesPerEntry;
SETDBGVAR(dbgR, (BYTE)Prim[0]);
SETDBGVAR(dbgG, (BYTE)Prim[1]);
SETDBGVAR(dbgB, (BYTE)Prim[2]);
if (CTSTDUnion.b.Flags & CTSTDF_CHKNONWHITE) {
CTSTDUnion.b.Flags &= ~CTSTDF_P012_MASK;
if ((!Prim[0]) || (Prim[0] == SrcClrTriad.PrimaryValueMax)) {
if (Prim[0]) {
CTSTDUnion.b.Flags |= CTSTDF_P0_PRIM;
}
} else {
CTSTDUnion.b.Flags |= CTSTDF_NON_PRIM;
}
if ((!Prim[1]) || (Prim[1] == SrcClrTriad.PrimaryValueMax)) {
if (Prim[1]) {
CTSTDUnion.b.Flags |= CTSTDF_P1_PRIM;
}
} else {
CTSTDUnion.b.Flags |= CTSTDF_NON_PRIM;
}
if ((!Prim[2]) || (Prim[2] == SrcClrTriad.PrimaryValueMax)) {
if (Prim[2]) {
CTSTDUnion.b.Flags |= CTSTDF_P2_PRIM;
}
} else {
CTSTDUnion.b.Flags |= CTSTDF_NON_PRIM;
}
if (Prim[0] != SrcClrTriad.PrimaryValueMax) {
CTSTDUnion.b.Flags |= CTSTDF_P0NW;
}
if (Prim[1] != SrcClrTriad.PrimaryValueMax) {
CTSTDUnion.b.Flags |= CTSTDF_P1NW;
}
if (Prim[2] != SrcClrTriad.PrimaryValueMax) {
CTSTDUnion.b.Flags |= CTSTDF_P2NW;
}
}
//
// 2: Transform from RGB (gamma correction) -> XYZ -> L*A*B* or L*U*V*
//
MonoPrim = (BOOL)(DevClrAdj.PrimAdj.Flags & DCA_MONO_ONLY);
if (SrcClrTriad.Type == COLOR_TYPE_RGB) {
if (pR_XYZ) {
Y = pR_XYZ[Prim[0]].Y +
pG_XYZ[Prim[1]].Y +
pB_XYZ[Prim[2]].Y;
} else {
if (SrcClrTriad.PrimaryValueMax) {
Prim[0] = DivFD6(Prim[0], SrcClrTriad.PrimaryValueMax);
Prim[1] = DivFD6(Prim[1], SrcClrTriad.PrimaryValueMax);
Prim[2] = DivFD6(Prim[2], SrcClrTriad.PrimaryValueMax);
}
if (DevClrAdj.PrimAdj.Flags & DCA_HAS_SRC_GAMMA) {
Prim[0] = Power(Prim[0], DevClrAdj.PrimAdj.RGBGamma.R);
Prim[1] = Power(Prim[1], DevClrAdj.PrimAdj.RGBGamma.G);
Prim[2] = Power(Prim[2], DevClrAdj.PrimAdj.RGBGamma.B);
}
if (DevClrAdj.PrimAdj.Flags & DCA_HAS_BW_REF_ADJ) {
PRIM_BW_ADJ(Prim[0], DevClrAdj.PrimAdj);
if (!MonoPrim) {
PRIM_BW_ADJ(Prim[1], DevClrAdj.PrimAdj);
PRIM_BW_ADJ(Prim[2], DevClrAdj.PrimAdj);
}
}
if (DevClrAdj.PrimAdj.Flags & DCA_HAS_CONTRAST_ADJ) {
PRIM_CONTRAST(Prim[0], DevClrAdj.PrimAdj);
if (!MonoPrim) {
PRIM_CONTRAST(Prim[1], DevClrAdj.PrimAdj);
PRIM_CONTRAST(Prim[2], DevClrAdj.PrimAdj);
}
}
if (DevClrAdj.PrimAdj.Flags & DCA_HAS_BRIGHTNESS_ADJ) {
PRIM_BRIGHTNESS(Prim[0], DevClrAdj.PrimAdj);
if (!MonoPrim) {
PRIM_BRIGHTNESS(Prim[1], DevClrAdj.PrimAdj);
PRIM_BRIGHTNESS(Prim[2], DevClrAdj.PrimAdj);
}
}
if (DevClrAdj.PrimAdj.Flags & DCA_LOG_FILTER) {
PRIM_LOG_FILTER(Prim[0]);
if (!MonoPrim) {
PRIM_LOG_FILTER(Prim[1]);
PRIM_LOG_FILTER(Prim[2]);
}
}
CLAMP_01(Prim[0]);
if (!MonoPrim) {
CLAMP_01(Prim[1]);
CLAMP_01(Prim[2]);
}
//
// Compute CIE L from CIE Y tristimulus value
//
// L* = (1.16 x f(Y/Yw)) - 0.16
//
// 1/3
// f(Y/Yw) = (Y/Yw) (Y/Yw) > 0.008856
// f(Y/Yw) = 9.033 x (Y/Yw) (Y/Yw) <= 0.008856
//
//
// Our L* is range from 0.0 to 1.0, not 0.0 to 100.0
//
MAKE_MULDIV_PAIR(MDPairs, 1,
CIE_Yr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
Prim[0]);
MAKE_MULDIV_PAIR(MDPairs, 2,
CIE_Yg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
Prim[1]);
MAKE_MULDIV_PAIR(MDPairs, 3,
CIE_Yb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
Prim[2]);
Y = MulDivFD6Pairs(MDPairs);
}
} else {
Y = (SrcClrTriad.PrimaryValueMax) ?
DivFD6(Prim[1], SrcClrTriad.PrimaryValueMax) : Prim[1];
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP(" NON_RGB: Y=%s" ARGFD6(Y, 1, 6)));
}
if (DevClrAdj.PrimAdj.Flags & DCA_NEGATIVE) {
Y = DevClrAdj.PrimAdj.rgbCSXForm.WhiteXYZ.Y - Y;
}
if (!MonoPrim) {
// If we only doing monochrome, then we only need Y/L pair only,
// else convert it to the XYZ/LAB/LUV
//
if (SrcClrTriad.Type == COLOR_TYPE_RGB) {
if (pR_XYZ) {
X = pR_XYZ[Prim[0]].X +
pG_XYZ[Prim[1]].X +
pB_XYZ[Prim[2]].X;
Z = pR_XYZ[Prim[0]].Z +
pG_XYZ[Prim[1]].Z +
pB_XYZ[Prim[2]].Z;
} else {
MAKE_MULDIV_FLAG(MDPairs, MULDIV_NO_DIVISOR);
MAKE_MULDIV_PAIR(MDPairs, 1,
CIE_Xr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
Prim[0]);
MAKE_MULDIV_PAIR(MDPairs, 2,
CIE_Xg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
Prim[1]);
MAKE_MULDIV_PAIR(MDPairs, 3,
CIE_Xb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
Prim[2]);
X = MulDivFD6Pairs(MDPairs);
MAKE_MULDIV_PAIR(MDPairs, 1,
CIE_Zr(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
Prim[0]);
MAKE_MULDIV_PAIR(MDPairs, 2,
CIE_Zg(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
Prim[1]);
MAKE_MULDIV_PAIR(MDPairs, 3,
CIE_Zb(DevClrAdj.PrimAdj.rgbCSXForm.M3x3),
Prim[2]);
Z = MulDivFD6Pairs(MDPairs);
}
} else {
if (SrcClrTriad.PrimaryValueMax) {
X = DivFD6(Prim[0], SrcClrTriad.PrimaryValueMax);
Z = DivFD6(Prim[2], SrcClrTriad.PrimaryValueMax);
} else {
X = Prim[0];
Z = Prim[2];
}
}
if (DevClrAdj.PrimAdj.Flags & DCA_NEGATIVE) {
X = DevClrAdj.PrimAdj.rgbCSXForm.WhiteXYZ.X - X;
Z = DevClrAdj.PrimAdj.rgbCSXForm.WhiteXYZ.Z - Z;
}
if (SkipLAB) {
Prim[0] = X;
Prim[1] = Y;
Prim[2] = Z;
} else if (Y <= FD6_0) {
MonoPrim = TRUE;
Y = FD6_0;
} else if (Y >= FD6_1) {
MonoPrim = TRUE;
Y = FD6_1;
} else {
switch(ColorSpace) {
case CIELUV_1976:
//
// U' = 4X / (X + 15Y + 3Z)
// V' = 9Y / (X + 15Y + 3Z)
//
// U* = 13 x L x (U' - Uw)
// V* = 13 x L x (V' - Vw)
//
X15Y3Z = X + FD6xL(Y, 15) + FD6xL(Z, 3);
U1 = DivFD6(FD6xL(X, 4), X15Y3Z) - iUw;
V1 = DivFD6(FD6xL(Y, 9), X15Y3Z) - iVw;
L13 = FD6xL(CIE_I2L(Y), 13);
AU = MulFD6(L13, U1);
BV = MulFD6(L13, V1);
#if 0
if ((AU >= (FD6)-100) && (AU <= (FD6)100) &&
(BV >= (FD6)-100) && (BV <= (FD6)100)) {
MonoPrim = TRUE;
} else {
MAKE_MULDIV_DVSR(AUMDPairs, L13);
MAKE_MULDIV_DVSR(BVMDPairs, L13);
}
#else
MAKE_MULDIV_DVSR(AUMDPairs, L13);
MAKE_MULDIV_DVSR(BVMDPairs, L13);
#endif
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP(" << UV1: %s:%s [%s:%s], X15Y3Z=%s"
ARGFD6(U1, 2, 6)
ARGFD6(V1, 2, 6)
ARGFD6(U1 + iUw, 2, 6)
ARGFD6(V1 + iVw, 2, 6)
ARGFD6(X15Y3Z, 2, 6)));
break;
case CIELAB_1976:
default:
//
// CIELAB 1976 L*A*B*
//
// A* = 500 x (fX - fY)
// B* = 200 x (fY - fZ)
//
// 1/3
// fX = (X/Xw) (X/Xw) > 0.008856
// fX = 7.787 x (X/Xw) + (16/116) (X/Xw) <= 0.008856
//
// 1/3
// fY = (Y/Yw) (Y/Yw) > 0.008856
// fY = 7.787 Y (Y/Yw) + (16/116) (Y/Yw) <= 0.008856
//
// 1/3
// fZ = (Z/Zw) (Z/Zw) > 0.008856
// fZ = 7.787 Z (Z/Zw) + (16/116) (Z/Zw) <= 0.008856
//
fXYZFromXYZ(fX, X, iRefXw);
fXYZFromXYZ(fY, Y, FD6_1);
fXYZFromXYZ(fZ, Z, iRefZw);
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP(" >> fXYZ: %s:%s:%s"
ARGFD6(fX, 2, 6)
ARGFD6(fY, 2, 6)
ARGFD6(fZ, 2, 6)));
AU = fX - fY;
BV = fY - fZ;
//
// DO NOT Translate it now
//
if ((AU >= (FD6)-20) && (AU <= (FD6)20) &&
(BV >= (FD6)-20) && (BV <= (FD6)20)) {
DBGP_IF(DBGP_MONO_PRIM,
DBGP("*** MONO PRIMS: %s:%s:%s --> Y=%s, RefY=%s --> %s"
ARGFD6(DivFD6(dbgR, 255), 1, 6)
ARGFD6(DivFD6(dbgG, 255), 1, 6)
ARGFD6(DivFD6(dbgB, 255), 1, 6)
ARGFD6(Y, 1, 6)
ARGFD6(DevRefY, 1, 6)
ARGFD6(DivFD6(Y, DevRefY), 1, 6)));
//
// MonoPrim = TRUE;
//
}
break;
}
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP(" XYZ->%s: %s:%s:%s >> L:%s:%s"
ARG(pDbgCSName[ColorSpace])
ARGFD6(X, 2, 6)
ARGFD6(Y, 1, 6)
ARGFD6(Z, 2, 6)
ARGFD6(AU, 4, 6)
ARGFD6(BV, 4, 6)));
if (!MonoPrim) {
//
// 5: Do any Color Adjustments (in LAB/LUV)
//
AUMDPairs[1].Pair2 =
BVMDPairs[2].Pair2 = AU;
AUMDPairs[2].Pair2 =
BVMDPairs[1].Pair2 = BV;
AU = MulDivFD6Pairs(AUMDPairs);
BV = MulDivFD6Pairs(BVMDPairs);
#if 0
if (DevClrAdj.PrimAdj.Flags & DCA_HAS_COLOR_ADJ) {
PRIM_COLORFULNESS(AU, BV, DevClrAdj.PrimAdj);
}
if (DevClrAdj.PrimAdj.Flags & DCA_HAS_TINT_ADJ) {
PRIM_TINT(AU, BV, p0, DevClrAdj.PrimAdj);
}
#endif
//
// 6: Transform From LAB/LUV->XYZ->RGB with possible gamma
// correction
//
// L* = (1.16 x f(Y/Yw)) - 0.16
//
// 1/3
// f(Y/Yw) = (Y/Yw) (Y/Yw) > 0.008856
// f(Y/Yw) = 9.033 x (Y/Yw) (Y/Yw) <= 0.008856
//
switch(ColorSpace) {
case CIELUV_1976:
//
// U' = 4X / (X + 15Y + 3Z)
// V' = 9Y / (X + 15Y + 3Z)
//
// U* = 13 x L x (U' - Uw)
// V* = 13 x L x (V' - Vw)
//
if (((V1 = BV + oVw) < FD6_0) ||
((X15Y3Z = DivFD6(FD6xL(Y, 9), V1)) < FD6_0)) {
X15Y3Z = (FD6)2147000000;
}
if ((U1 = AU + oUw) < FD6_0) {
X =
U1 = FD6_0;
} else {
X = FD6DivL(MulFD6(X15Y3Z, U1), 4);
}
Z = FD6DivL(X15Y3Z - X - FD6xL(Y, 15), 3);
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP(" >> UV1: %s:%s [%s:%s], X15Y3Z=%s"
ARGFD6(U1 - oUw, 2, 6)
ARGFD6(V1 - oVw, 2, 6)
ARGFD6(U1, 2, 6)
ARGFD6(V1, 2, 6)
ARGFD6(X15Y3Z, 2, 6)));
break;
case CIELAB_1976:
default:
//
// CIELAB 1976 L*A*B*
//
// A* = 500 x (fX - fY)
// B* = 200 x (fY - fZ)
//
// 1/3
// fX = (X/Xw) (X/Xw) > 0.008856
// fX = 7.787 x (X/Xw) + (16/116) (X/Xw) <= 0.008856
//
// 1/3
// fY = (Y/Yw) (Y/Yw) > 0.008856
// fY = 7.787 Y (Y/Yw) + (16/116) (Y/Yw) <= 0.008856
//
// 1/3
// fZ = (Z/Zw) (Z/Zw) > 0.008856
// fZ = 7.787 Z (Z/Zw) + (16/116) (Z/Zw) <= 0.008856
//
// fX = FD6DivL(AU, 500) + fY;
// fZ = fY - FD6DivL(BV, 200);
fX = AU + fY;
fZ = fY - BV;
XYZFromfXYZ(X, fX, oRefXw);
XYZFromfXYZ(Z, fZ, oRefZw);
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP(" << fXYZ: %s:%s:%s"
ARGFD6(fX, 2, 6)
ARGFD6(fY, 2, 6)
ARGFD6(fZ, 2, 6)));
break;
}
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP(" %s->XYZ: %s:%s:%s << L:%s:%s"
ARG(pDbgCSName[ColorSpace])
ARGFD6(X, 2, 6)
ARGFD6(Y, 1, 6)
ARGFD6(Z, 2, 6)
ARGFD6(AU, 4, 6)
ARGFD6(BV, 4, 6)));
MAKE_MULDIV_FLAG(MDPairs, MULDIV_NO_DIVISOR);
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Xr(DevCSXForm.M3x3), X);
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Xg(DevCSXForm.M3x3), Y);
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Xb(DevCSXForm.M3x3), Z);
Prim[0] = MulDivFD6Pairs(MDPairs);
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Yr(DevCSXForm.M3x3), X);
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Yg(DevCSXForm.M3x3), Y);
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Yb(DevCSXForm.M3x3), Z);
Prim[1] = MulDivFD6Pairs(MDPairs);
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Zr(DevCSXForm.M3x3), X);
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Zg(DevCSXForm.M3x3), Y);
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Zb(DevCSXForm.M3x3), Z);
Prim[2] = MulDivFD6Pairs(MDPairs);
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP(" XYZ->RGB: %s:%s:%s >> %s:%s:%s"
ARGFD6(X, 2, 6)
ARGFD6(Y, 1, 6)
ARGFD6(Z, 2, 6)
ARGFD6(Prim[0], 1, 6)
ARGFD6(Prim[1], 1, 6)
ARGFD6(Prim[2], 1, 6)));
}
}
}
if (MonoPrim) {
Prim[0] =
Prim[1] =
Prim[2] = DivFD6(Y, DevRefY);
}
//
// Make sure everthing is in the range
//
SCALE_PRIM_RGB(Prim, NULL);
if (DevClrAdj.PrimAdj.Flags & DCA_DO_SUB_ADJ) {
PRIM_SUBADJ(Prim[0], DevRGBGamma);
if (!MonoPrim) {
PRIM_SUBADJ(Prim[1], DevRGBGamma);
PRIM_SUBADJ(Prim[2], DevRGBGamma);
}
}
//
// 7: Dye correction if necessary
//
if ((!MonoPrim) &&
(DevClrAdj.PrimAdj.Flags & DCA_NEED_DYES_CORRECTION)) {
if (DevClrAdj.PrimAdj.Flags & DCA_HAS_BLACK_DYE) {
MAX_OF_3(W, Prim[0], Prim[1], Prim[2]);
} else {
W = FD6_1;
}
p0 = W - Prim[0];
p1 = W - Prim[1];
p2 = W - Prim[2];
DBGP_IF(DBGP_DYE_CORRECT,
DBGP(" DYE_CORRECT: %s:%s:%s, W=%s --> %s:%s:%s"
ARGFD6(Prim[0], 2, 6)
ARGFD6(Prim[1], 2, 6)
ARGFD6(Prim[2], 2, 6)
ARGFD6(W, 1, 6)
ARGFD6(p0, 2, 6)
ARGFD6(p1, 2, 6)
ARGFD6(p2, 2, 6)));
MAKE_MULDIV_FLAG(MDPairs, MULDIV_NO_DIVISOR);
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Xr(CMYDyeMasks), p0);
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Xg(CMYDyeMasks), p1);
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Xb(CMYDyeMasks), p2);
Prim[0] = W - MulDivFD6Pairs(MDPairs);
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Yr(CMYDyeMasks), p0);
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Yg(CMYDyeMasks), p1);
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Yb(CMYDyeMasks), p2);
Prim[1] = W - MulDivFD6Pairs(MDPairs);
MAKE_MULDIV_PAIR(MDPairs, 1, CIE_Zr(CMYDyeMasks), p0);
MAKE_MULDIV_PAIR(MDPairs, 2, CIE_Zg(CMYDyeMasks), p1);
MAKE_MULDIV_PAIR(MDPairs, 3, CIE_Zb(CMYDyeMasks), p2);
Prim[2] = W - MulDivFD6Pairs(MDPairs);
DBGP_IF(DBGP_DYE_CORRECT,
DBGP(" DYE_CORRECT: %s:%s:%s << %s:%s:%s"
ARGFD6(Prim[0], 2, 6)
ARGFD6(Prim[1], 2, 6)
ARGFD6(Prim[2], 2, 6)
ARGFD6(p0, 2, 6)
ARGFD6(p1, 2, 6)
ARGFD6(p2, 2, 6)));
SCALE_PRIM_RGB(Prim, (PFD6)&(DevCSXForm.Yrgb));
}
//*******************************************************************
//
// 8: Compute Final Device DYE through regression and Primary/Halftone
// Cell number computation, The Primaries (ie. Prim[]) are in
// ADDITIVE FORMAT
//
//*******************************************************************
if (!MonoPrim) {
MonoPrim = (BOOL)((Prim[0] == Prim[1]) && (Prim[0] == Prim[2]));
}
RegressXFromY(Prim, pRegress, (MonoPrim) ? 1 : 3);
if (MonoPrim) {
Prim[1] =
Prim[2] = Prim[0];
} else if ((CTSTDUnion.b.Flags & CTSTDF_CHKNONWHITE) &&
(!(CTSTDUnion.b.Flags & CTSTDF_NON_PRIM))) {
//
// Make it density for device prim ONLY, CYAN, MEGENTA, YELLOW
// that is. (Prim[0]=CYAN, Prim[1]=Megenta, Prim[2]=Yellow)
//
CRange = CTSTDUnion.b.Flags & CTSTDF_P012_PRIM;
if (RegressFlags & REGF_Y2X_IS_DENSITY) {
CRange ^= CTSTDF_P012_PRIM;
}
//
// We only care about Index 1, 2, 4 (DENSITY)
//
// 0=K, 1=R, 2=G, 3=Y, 4=B, 5=M, 6=C, 7=W
//
switch (CRange) {
case 3: // Y
case 5: // M
case 6: // C
DBGP_IF(DBGP_CHKNONWHITE,
DBGP("*** NonWhite, PURE Prim Color=%u" ARGU(CRange)));
Prim[0] = (CRange & CTSTDF_P0_PRIM) ? FD6_1 : FD6_0;
Prim[1] = (CRange & CTSTDF_P1_PRIM) ? FD6_1 : FD6_0;
Prim[2] = (CRange & CTSTDF_P2_PRIM) ? FD6_1 : FD6_0;
if (RegressFlags & REGF_Y2X_IS_DENSITY) {
Prim[0] = FD6_1 - Prim[0];
Prim[1] = FD6_1 - Prim[1];
Prim[2] = FD6_1 - Prim[2];
}
break;
default:
DBGP_IF(DBGP_CHKNONWHITE,
DBGP("*** NonWhite, IGNORED Prim Color=%u" ARGU(CRange)));
break;
}
//
// We have prim color, so always turn this offf
//
CTSTDUnion.b.Flags &= ~CTSTDF_P012NW;
}
if ((CTSTDUnion.b.Flags & CTSTDF_CHKNONWHITE) &&
(CTSTDUnion.b.Flags & CTSTDF_P012NW)) {
if (RegressFlags & REGF_Y2X_IS_DENSITY) {
if ((Prim[0] <= MinFD6Clr) &&
(Prim[1] <= MinFD6Clr) &&
(Prim[2] <= MinFD6Clr)) {
if (CTSTDUnion.b.Flags & CTSTDF_P0NW) {
Prim[0] = MinFD6Clr;
}
if (CTSTDUnion.b.Flags & CTSTDF_P1NW) {
Prim[1] = MinFD6Clr;
}
if (CTSTDUnion.b.Flags & CTSTDF_P2NW) {
Prim[2] = MinFD6Clr;
}
DBGP_IF(DBGP_CHKNONWHITE,
DBGP("NonWhite->White = DENSITY %s:%s:%s"
ARGFD6(Prim[0], 2, 6)
ARGFD6(Prim[1], 2, 6)
ARGFD6(Prim[2], 2, 6)));
}
} else {
MinFD6Clr = FD6_1 - MinFD6Clr;
if ((Prim[0] > MinFD6Clr) &&
(Prim[1] > MinFD6Clr) &&
(Prim[2] > MinFD6Clr)) {
if (CTSTDUnion.b.Flags & CTSTDF_P0NW) {
Prim[0] = MinFD6Clr;
}
if (CTSTDUnion.b.Flags & CTSTDF_P1NW) {
Prim[1] = MinFD6Clr;
}
if (CTSTDUnion.b.Flags & CTSTDF_P2NW) {
Prim[2] = MinFD6Clr;
}
DBGP_IF(DBGP_CHKNONWHITE,
DBGP("NonWhite->White = INTENSITY %s:%s:%s"
ARGFD6(Prim[0], 2, 6)
ARGFD6(Prim[1], 2, 6)
ARGFD6(Prim[2], 2, 6)));
}
MinFD6Clr = FD6_1 - MinFD6Clr;
}
}
if (NegatePrims) {
Prim[0] = FD6_1 - Prim[0];
Prim[1] = FD6_1 - Prim[1];
Prim[2] = FD6_1 - Prim[2];
}
DBGP_IF(DBGP_SHOWXFORM_ALL,
DBGP(" REGRESS: %s:%s:%s"
ARGFD6(Prim[0], 2, 6)
ARGFD6(Prim[1], 2, 6)
ARGFD6(Prim[2], 2, 6)));
switch(CTSTDUnion.b.BMFDest) {
case BMF_1BPP:
PrimColor.Prim1 = (BYTE)SCALE_FD6(Prim[0], DevClrMax);
*(((PPRIMMONO)pDevPrims)++) = *(PPRIMMONO)&PrimColor;
break;
case BMF_4BPP_VGA16:
//
// 0, 0, 0, 0000 0 Black
// 0, ,0, 0x80 0001 1 Dark Red
// 0, 0x80,0, 0010 2 Dark Green
// 0, ,0x80,0x80 0011 3 Dark Yellow
// 0x80 0, 0, 0100 4 Dark Blue
// 0x80,0, 0x80 0101 5 Dark Magenta
// 0x80 0x80,0, 0110 6 Dark Cyan
// 0x80,0x80,0x80 0111 7 Gray 50%
//
// 0xC0,0xC0,0xC0 1000 8 Gray 75%
// 0, ,0, 0xFF 1001 9 Red
// 0, 0xFF,0, 1010 10 Green
// 0, ,0xFF,0xFF 1011 11 Yellow
// 0xFF 0, 0, 1100 12 Blue
// 0xFF,0, 0xFF 1101 13 Magenta
// 0xFF 0xFF,0, 1110 14 Cyan
// 0xFF,0xFF,0xFF 1111 15 White
//
//----------------------------------------------------------------
//
// The VGA16 standard color table is not adjustable, the gamma
// cannot be re-program, so we will use VGA16_80h, VGA16_c0h
// two gamma corrected values to scale the final intensities.
//
// These two value are derived from the DevicePowerGamma specified
// in the HTINITINFO data structure.
//
//----------------------------------------------------------------
// Possible combinations
//
// Red Group
//
// 1. [K] R [W] - [0000] 0001 [1111]
// 2. [K] R Y [W] - [0000] 0001 0011 [1111]
// 3. [K] R M [W] - [0000] 0001 0101 [1111]
//
// Green Group
//
// 1. [K] G [W] - [0000] 0010 [1111]
// 2. [K] G Y [W] - [0000] 0010 0011 [1111]
// 3. [K] G C [W] - [0000] 0010 0110 [1111]
//
//
// Blue Group
//
// 1. [K] B [W] - [0000] 0100 [1111]
// 2. [K] B M [W] - [0000] 0100 0101 [1111]
// 3. [K] B C [W] - [0000] 0100 0110 [1111]
//
// Gray Group
//
// 1. K M1 - 0000 0111
// 2. M1 M2 - 0111 1000
// 3. M2 W - 1000 1111
//
//
// PrimColor.Prim1 = W/M1/M2 Threshold
// PrimColor.Prim2 = K/M1/M2 Threshold
// PrimColor.Prim3 = IC/IM/IY Threshold
// PrimColor.Prim4 = C/ M/ Y Threshold
// PrimColor.w2b.bPrim[0] = IR/IG/IB Threshold
// PrimColor.w2b.bPrim[1] = VGA16ColorIndex[ColorIdx]
//
if (MonoPrim) {
//
// The monochrome index is located start from
// VGA16ColorIndex[0] with 0x00, 0x77, 0x77, 0x88, 0x88, 0xff
// 6 bytes, for PrimColor we only use Prim1/2 and set the rest
// of them to 0xff, so it only compare Prim2
//
if ((W = Prim[0]) >= VGA16_c0h) {
PrimColor.Prim1 = 5;
PrimColor.Prim2 = GET_VGA16MONO_c0h(Prim[0], DevClrMax);
} else if (Prim[0] >= VGA16_80h) {
PrimColor.Prim1 = 3;
PrimColor.Prim2 = GET_VGA16MONO_80h(Prim[0], DevClrMax);
} else {
PrimColor.Prim1 = 1;
PrimColor.Prim2 = GET_VGA16MONO_00h(Prim[0], DevClrMax);
}
PrimColor.Prim3 =
PrimColor.Prim4 =
PrimColor.w2b.bPrim[0] =
PrimColor.w2b.bPrim[1] = 0xff;
} else {
p0 = Prim[0];
p1 = Prim[1];
p2 = Prim[2];
RIdx = 0;
GIdx = 1;
BIdx = 2;
if (p0 < p1) {
SWAP(RIdx, GIdx, RCube);
SWAP(p0, p1, W);
}
if (p0 < p2) {
SWAP(RIdx, BIdx, RCube);
SWAP(p0, p2, W);
}
if (p1 < p2) {
SWAP(GIdx, BIdx, RCube);
SWAP(p1, p2, W);
}
//
// TempI: VGA16ColorIndex[] Color Mix starting index
// TempJ: White MIX offset, add ONE to skip first MONO group
//
TempI = (INT)((RIdx << 2) + ((GIdx > BIdx) ? 2 : 0));
if ((C = p0) >= VGA16_80h) {
++TempI;
W = C;
C = RATIO_SCALE(C, VGA16_80h, VGA16_ffh);
if (W >= VGA16_c0h) {
TempJ = 2;
W = RATIO_SCALE(W, VGA16_c0h, VGA16_ffh);
} else {
TempJ = 1;
W = RATIO_SCALE(W, VGA16_80h, VGA16_c0h);
}
} else {
TempJ = 0;
W =
C = RATIO_SCALE(C, VGA16_00h, VGA16_80h);
}
Z = DivFD6(p1 - p2, p0 - p2);
WRange = (BYTE)SCALE_FD6(DivFD6(p2, p0), DevClrMax);
CRange = DevClrMax - WRange;
CHRange = (BYTE)SCALE_FD6(C, CRange);
CLRange = CRange - CHRange;
H_WIdx = (BYTE)SCALE_FD6(W, WRange);
L_WIdx = WRange - H_WIdx;
H_MIdx = (BYTE)SCALE_FD6(Z, CHRange);
H_PIdx = CHRange - H_MIdx;
L_MIdx = (BYTE)SCALE_FD6(Z, CLRange);
L_PIdx = CLRange - L_MIdx;
//
// Add 11 because: add 5 to the end of color group and add
// 6 to skip the first mono group
//
PrimColor.Prim1 = (BYTE)((((TempI * 3) + TempJ) * 6) + 11);
if (TempJ) {
PrimColor.Prim2 = H_WIdx;
PrimColor.Prim3 = PrimColor.Prim2 + L_WIdx;
PrimColor.Prim4 = PrimColor.Prim3 + H_MIdx;
PrimColor.w2b.bPrim[0] = PrimColor.Prim4 + H_PIdx;
PrimColor.w2b.bPrim[1] = PrimColor.w2b.bPrim[0] + L_MIdx;
} else {
PrimColor.Prim2 = H_WIdx;
PrimColor.Prim3 = PrimColor.Prim2 + H_MIdx;
PrimColor.Prim4 = PrimColor.Prim3 + H_PIdx;
PrimColor.w2b.bPrim[0] = PrimColor.Prim4 + L_MIdx;
PrimColor.w2b.bPrim[1] = PrimColor.w2b.bPrim[0] + L_PIdx;
}
}
*(((PPRIMCOLOR)pDevPrims)++) = PrimColor;
break;
case BMF_1BPP_3PLANES:
case BMF_4BPP:
PrimColor.Prim1 =
RCube =
pDevPrims[OffsetPrim1] = (BYTE)SCALE_FD6(Prim[0], DevClrMax);
if (MonoPrim) {
PrimColor.Prim2 =
PrimColor.Prim3 =
pDevPrims[OffsetPrim2] =
pDevPrims[OffsetPrim3] = RCube;
} else {
PrimColor.Prim2 =
pDevPrims[OffsetPrim2] = (BYTE)SCALE_FD6(Prim[1], DevClrMax);
PrimColor.Prim3 =
pDevPrims[OffsetPrim3] = (BYTE)SCALE_FD6(Prim[2], DevClrMax);
}
++((PPRIMCOLOR)pDevPrims);
break;
case BMF_8BPP_VGA256:
//
// The VGA palette has 2 sections
//
// 1. Mixture of RGB steps as 0.0, 0.1 0.325, 0.55, 0.775, 1.0
// 2. Monochrome in 0.05 increment from 0.0 to 1.0
//
if (!MonoPrim) {
VGA256_R_CI(Prim[0], RCube, RIdx, DevClrMax);
VGA256_G_CI(Prim[1], GCube, GIdx, DevClrMax);
VGA256_B_CI(Prim[2], BCube, BIdx, DevClrMax);
if ((RCube == GCube) && (RCube == BCube) &&
( RIdx == GIdx) && ( RIdx == BIdx)) {
MonoPrim = TRUE;
Prim[0] = (FD6)((Prim[0] + Prim[1] + Prim[2]) / 3);
}
}
if (MonoPrim) {
//
// Monochrome case
//
PrimColor.Prim1 =
PrimColor.Prim2 = 0;
CI_VGA256_MONO(Prim[0],
PrimColor.Prim4,
PrimColor.Prim3,
DevClrMax,
TempI,
TempJ,
TempK,
p0,
p1);
} else {
PrimColor.Prim1 = BIdx;
PrimColor.Prim2 = GIdx;
PrimColor.Prim3 = RIdx;
PrimColor.Prim4 = RCube +
VGA256_GCubeIdx[GCube] +
VGA256_BCubeIdx[BCube];
}
*(((PPRIMCOLOR)pDevPrims)++) = PrimColor;
break;
case BMF_16BPP_555:
CI_16BPP_555(Prim[0], RCube, PrimColor.Prim1, DevClrMax,
TempI, TempJ, TempK, p0, p1);
if (MonoPrim) {
GCube =
BCube = RCube;
PrimColor.Prim2 =
PrimColor.Prim3 = PrimColor.Prim1;
} else {
CI_16BPP_555(Prim[1], GCube, PrimColor.Prim2, DevClrMax,
TempI, TempJ, TempK, p0, p1);
CI_16BPP_555(Prim[2], BCube, PrimColor.Prim3, DevClrMax,
TempI, TempJ, TempK, p0, p1);
}
PrimColor.w2b.wPrim = (WORD)((WORD)RCube << 10) |
(WORD)((WORD)GCube << 5) |
(WORD)((WORD)BCube );
*(((PPRIMCOLOR)pDevPrims)++) = PrimColor;
break;
default:
p0 = MulFD6(Prim[0], DevClrMax);
p1 = MulFD6(Prim[1], DevClrMax);
p2 = MulFD6(Prim[2], DevClrMax);
switch (DevBytesPerPrimary) {
case 1:
*((LPBYTE)(pDevPrims + OffsetPrim1)) = (BYTE)p0;
*((LPBYTE)(pDevPrims + OffsetPrim2)) = (BYTE)p1;
*((LPBYTE)(pDevPrims + OffsetPrim3)) = (BYTE)p2;
break;
case 2:
*((LPSHORT)(pDevPrims + OffsetPrim1)) = (SHORT)p0;
*((LPSHORT)(pDevPrims + OffsetPrim2)) = (SHORT)p1;
*((LPSHORT)(pDevPrims + OffsetPrim3)) = (SHORT)p2;
break;
case 4:
*((PFD6)(pDevPrims + OffsetPrim1)) = p0;
*((PFD6)(pDevPrims + OffsetPrim2)) = p1;
*((PFD6)(pDevPrims + OffsetPrim3)) = p2;
break;
}
pDevPrims += DevBytesPerEntry;
break;
}
DBGP_IF((DBGP_SHOWXFORM_RGB | DBGP_SHOWXFORM_ALL),
DBGP("%3u=%3u:%3u:%3u > %s:%s:%s > %s:%s:%s > %3u:%3u:%3u:%3u%3u:%3u"
ARGW(ClrNo++)
ARGW(dbgR)
ARGW(dbgG)
ARGW(dbgB)
ARGFD6(DivFD6(dbgR, 255), 1, 3)
ARGFD6(DivFD6(dbgG, 255), 1, 3)
ARGFD6(DivFD6(dbgB, 255), 1, 3)
ARGFD6(Prim[0], 1, 3)
ARGFD6(Prim[1], 1, 3)
ARGFD6(Prim[2], 1, 3)
ARGW(PrimColor.Prim1)
ARGW(PrimColor.Prim2)
ARGW(PrimColor.Prim3)
ARGW(PrimColor.Prim4)
ARGW(PrimColor.w2b.bPrim[0])
ARGW(PrimColor.w2b.bPrim[1])));
if ((pAbort) && (*pAbort)) {
break;
}
}
if (++Loop) {
DBGP("ColorTriadSrcToDev: Halftone Interuptted!");
SrcClrTriad.ColorTableEntries = (DWORD)HTERR_HALFTONE_INTERRUPTTED;
} else if ((pR_XYZ) && (pCRTX)) {
ACQUIRE_HTMUTEX(pDCI->HTMutex);
if (!pCRTX->pFD6XYZ) {
DBGP_IF(DBGP_CCT,
DBGP("CCT: Allocate %ld bytes RGB->XYZ xform cached table"
ARGDW(pCRTX->SizeCRTX)));
if (!(pCRTX->pFD6XYZ =
(PFD6XYZ)HTLocalAlloc((DWORD)PDCI_TO_PDHI(pDCI),
"CRTX-FD6XYZ",
NONZEROLPTR,
pCRTX->SizeCRTX))) {
DBGP_IF(DBGP_CCT,
DBGP("Allocate %ld bytes of RGB->XYZ cached table failed"
ARGDW(pCRTX->SizeCRTX)));
}
}
if (pCRTX->pFD6XYZ) {
DBGP_IF(DBGP_CCT,
DBGP("CCT: *** Save computed RGB->XYZ xform to CACHE ***"));
pCRTX->Checksum = CRTXChecksum;
CopyMemory(pCRTX->pFD6XYZ, pR_XYZ, pCRTX->SizeCRTX);
}
RELEASE_HTMUTEX(pDCI->HTMutex);
}
if (pR_XYZ) {
DBGP_IF(DBGP_CCT,
DBGP("ColorTriadSrcToDev: Free Up pR_XYZ local cached table"));
HTLocalFree((HLOCAL)pR_XYZ);
}
return((LONG)SrcClrTriad.ColorTableEntries);
}
LONG
HTENTRY
CreateDyesColorMappingTable(
PHALFTONERENDER pHR
)
/*++
Routine Description:
this function allocate the memory for the dyes color mapping table depends
on the source surface type information, it then go throug the color table
and calculate dye densities for each RGB color in the color table.
Arguments:
pHalftoneRender - Pointer to the HALFTONERENDER data structure.
Return Value:
a negative return value indicate failue.
HTERR_INVALID_SRC_FORMAT - Invalid source surface format, this
function only recongnized 1/4/8/24 bits
per pel source surfaces.
HTERR_COLORTABLE_TOO_BIG - can not create the color table to map
the colors to the dyes' densities.
HTERR_INSUFFICIENT_MEMORY - not enough memory for the pattern.
HTERR_INTERNAL_ERRORS_START - any other negative number indicate
halftone internal failure.
else - size of the color table entries created.
Author:
29-Jan-1991 Tue 11:13:02 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PDEVICECOLORINFO pDCI;
PDEVCLRADJ pDevClrAdj;
HTSURFACEINFO SrcSI;
LPBYTE pDevPrims;
PCACHEDMAPINFO pCMI;
COLORTRIAD ColorTriad;
CTSTD_UNION CTSTDUnion;
DWORD SizeLUT;
DWORD CCTSize;
DWORD CCTCount;
DWORD CCTChecksum;
LONG Result;
UINT SizePerCCT;
INT CBFLUTIndex;
INT CMIIndex;
BOOL MonoOnly;
BOOL CacheCCT;
SrcSI = *(pHR->HR_Header.pSrcSI);
pDCI = pHR->HR_Header.pDeviceColorInfo;
pDevClrAdj = pHR->HR_Header.pDevClrAdj;
MonoOnly = (BOOL)(pDevClrAdj->PrimAdj.Flags & DCA_MONO_ONLY);
ColorTriad = *(SrcSI.pColorTriad);
CTSTDUnion.b.Flags = 0;
CTSTDUnion.b.SrcOrder = ColorTriad.PrimaryOrder;
CTSTDUnion.b.DestOrder = pHR->HR_Header.pBitbltParams->DestPrimaryOrder;
CTSTDUnion.b.BMFDest = pHR->OutputSI.DestCBParams.SurfaceFormat;
if (CTSTDUnion.b.BMFDest == BMF_1BPP) {
MonoOnly = TRUE;
SizePerCCT = (UINT)sizeof(PRIMMONO);
CTSTDUnion.b.DestOrder = PRIMARY_ORDER_123; // always in order
} else {
if ((CTSTDUnion.b.BMFDest != BMF_1BPP_3PLANES) &&
(CTSTDUnion.b.BMFDest != BMF_4BPP)) {
CTSTDUnion.b.DestOrder = PRIMARY_ORDER_BGR;
}
SizePerCCT = (UINT)sizeof(PRIMCOLOR);
}
if (SrcSI.SurfaceFormat >= BMF_16BPP) {
CTSTDUnion.b.SrcOrder = 0xff;
SizeLUT = (DWORD)pHR->BFInfo.SizeLUT;
if (MonoOnly) {
CMIIndex = CMI_LOOKUP_MONO;
CCTCount = COUNT_RGB_YTABLE + COUNT_EXTRA_W_YTABLE;
switch(SrcSI.SurfaceFormat) {
case BMF_16BPP:
CBFLUTIndex = CBFL_16_MONO;
break;
case BMF_24BPP:
CBFLUTIndex = CBFL_24_MONO;
break;
case BMF_32BPP:
CBFLUTIndex = CBFL_32_MONO;
break;
}
} else {
CMIIndex = CMI_LOOKUP_COLOR;
CCTCount = (DWORD)HT_RGB_CUBE_COUNT;
switch(SrcSI.SurfaceFormat) {
case BMF_16BPP:
CBFLUTIndex = CBFL_16_COLOR;
break;
case BMF_24BPP:
CBFLUTIndex = CBFL_24_COLOR;
break;
case BMF_32BPP:
CBFLUTIndex = CBFL_32_COLOR;
break;
}
}
ColorTriad.Type = COLOR_TYPE_RGB;
ColorTriad.BytesPerPrimary = 0;
ColorTriad.BytesPerEntry = 0;
ColorTriad.PrimaryValueMax = 0;
ColorTriad.ColorTableEntries = CCTCount;
ColorTriad.pColorTable = NULL;
CacheCCT = TRUE;
CCTChecksum = (DWORD)CMIIndex;
} else {
SizeLUT = 0;
CMIIndex = (MonoOnly) ? CMI_TABLE_MONO : CMI_TABLE_COLOR;
if (CacheCCT = (BOOL)(ColorTriad.ColorTableEntries > MIN_CCT_COLORS)) {
CCTChecksum = ComputeChecksum(ColorTriad.pColorTable,
ColorTriad.ColorTableEntries,
ColorTriad.ColorTableEntries *
(DWORD)ColorTriad.BytesPerEntry);
}
//
// For 1/4/8 bits per pel device, we will make sure minimum color
// table size is allocated, we do not want to access to an index number
// and found that we actually do not have table for it.
//
switch(SrcSI.SurfaceFormat) {
case BMF_1BPP:
CCTCount = 2;
break;
case BMF_4BPP:
CCTCount = 16;
break;
case BMF_8BPP:
CCTCount = 256;
break;
default:
CCTCount = ColorTriad.ColorTableEntries;
break;
}
}
//
// We will always allocate the current color mapping table plus the extra
// stack size needed for the processing, and will cahced that table if
// needed
//
pCMI = &(pDCI->CMI[CMIIndex]);
CCTSize = (DWORD)SizePerCCT * (DWORD)CCTCount;
DBGP_IF(DBGP_CCT,
DBGP("Allocate CCT=%ld + LUT=%ld = %ld bytes mapping table"
ARGDW(CCTSize) ARGDW(SizeLUT)
ARGDW(CCTSize + SizeLUT)));
if (!(pDevPrims = (LPBYTE)HTLocalAlloc((DWORD)PDCI_TO_PDHI(pDCI),
"DevPrims",
NONZEROLPTR,
CCTSize + SizeLUT))) {
DBGP_IF(DBGP_CCT,
DBGP("Allocate %ld bytes color mapping table falied"
ARGDW(CCTSize + SizeLUT)));
return((LONG)HTERR_INSUFFICIENT_MEMORY);
}
pHR->InputSI.pPrimMappingTable = (LPVOID)pDevPrims;
//
// Firstable we will try to see if we can get the pLUT if need one
//
if (SizeLUT) {
DBGP_IF(DBGP_BFINFO,
DBGP("Compute CBFLUTIndex = %d [%s]"
ARGI(CBFLUTIndex)
ARG(pCBFLUTName[CBFLUTIndex])));
//
// Make sure these call are semaphore protected
//
ACQUIRE_HTMUTEX(pDCI->HTMutex);
if (MonoOnly) {
ComputeMonoLUT(pDCI,
&(pDCI->CBFLUT[CBFLUTIndex]),
&(pHR->BFInfo),
(LPWORD)pDevPrims,
pDevClrAdj);
} else {
ComputeColorLUT(pDCI,
&(pDCI->CBFLUT[CBFLUTIndex]),
&(pHR->BFInfo),
(LPWORD)pDevPrims,
pDevClrAdj);
}
RELEASE_HTMUTEX(pDCI->HTMutex);
pDevPrims += SizeLUT;
}
//************************************************************************
//* Now figure out if we can get the pMappingTable from the cached table *
//* if not then re-compute it *
//************************************************************************
Result = HTERR_COLORTABLE_TOO_BIG;
if (CacheCCT) {
//
// Find out if we can use the cached table
//
ACQUIRE_HTMUTEX(pDCI->HTMutex);
if ((pCMI->pMappingTable != NULL) &&
(pCMI->CCTSize == CCTSize) &&
(pCMI->CCTChecksum == CCTChecksum) &&
(COMP_CA(&(pCMI->ca), &(pDevClrAdj->ca))) &&
(pCMI->CTSTDUnion.dw == CTSTDUnion.dw)) {
DBGP_IF(DBGP_CCT, DBGP("@@@@@ USED CACHED pMappingTable @@@@@@"));
CopyMemory(pDevPrims, pCMI->pMappingTable, CCTSize);
Result = ColorTriad.ColorTableEntries;
}
RELEASE_HTMUTEX(pDCI->HTMutex);
}
if (Result <= 0) {
//
// Now we must compute the color table again
//
DBGP_IF(DBGP_CCT,
DBGP("@@@ Re-Compute %s Mapping table @@@ (%lu:%lu)"
ARG(pDbgCMIName[CMIIndex])
ARGDW(ColorTriad.ColorTableEntries) ARGDW(CCTSize)));
Result = ColorTriadSrcToDev(pDCI,
CTSTDUnion,
pHR->HR_Header.pBitbltParams->pAbort,
&ColorTriad,
pDevPrims,
pDevClrAdj);
if ((Result == (LONG)ColorTriad.ColorTableEntries) &&
(CacheCCT)) {
//
// If we compute the color and this can be a cached data then try
// to find out if we can save it
//
ACQUIRE_HTMUTEX(pDCI->HTMutex);
if ((pCMI->pMappingTable) &&
(pCMI->CCTSize != CCTSize)) {
DBGP_IF(DBGP_CCT, DBGP("!CCT Size change: FREE Cached Mapping Table!"));
HTLocalFree((HLOCAL)pCMI->pMappingTable);
pCMI->pMappingTable = NULL;
}
if (!pCMI->pMappingTable) {
DBGP_IF(DBGP_CCT,
DBGP("CCT: Allocate %ld bytes Cache MAPPING table"
ARGDW(CCTSize)));
if (!(pCMI->pMappingTable =
(LPBYTE)HTLocalAlloc((DWORD)PDCI_TO_PDHI(pDCI),
"MappingTable",
NONZEROLPTR,
CCTSize))) {
DBGP_IF(DBGP_CCT,
DBGP("CCT: Allocate CACHE table failed, not cached"));
}
}
if (pCMI->pMappingTable) {
//
// We really have memory to save the cached so do it
//
DBGP_IF(DBGP_CCT,
DBGP("CCT: *** Save computed pMappingTable to CACHE ***"));
pCMI->CCTSize = CCTSize;
pCMI->CCTChecksum = CCTChecksum;
pCMI->ca = pDevClrAdj->ca;
pCMI->CTSTDUnion.dw = CTSTDUnion.dw;
CopyMemory(pCMI->pMappingTable, pDevPrims, CCTSize);
}
RELEASE_HTMUTEX(pDCI->HTMutex);
}
}
return(Result);
}