Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The GenerateInkLevels function shown here provides an example of how to translate 8-bit-per-pixel halftone indexes to ink levels. These indexes are contained in CMY mode and CMY_INVERTED mode palettes that GDI's HT_Get8BPPMaskPalette function returns in its pPaletteEntry parameter. GenerateInkLevels generates a 256-element array of INKLEVELS structures.
This function can be used to generate either a Windows 2000 CMY mode or a post-Windows 2000 CMY_INVERTED mode translation table. This function can also be used to generate a Windows 2000 CMY mode CMY332 reverse-mapping index table. (CMY332 uses three bits each for cyan and magenta, and two bits for yellow.) When CMYMask value is in the range 3 to 255, the function's caller can use this table to map post-Windows 2000 CMY_INVERTED indexes to Windows 2000 CMY indexes for currently existing drivers.
INKLEVELS Structure
typedef struct _INKLEVELS {
BYTE Cyan; // Cyan level from 0 to max
BYTE Magenta; // Magenta level from 0 to max
BYTE Yellow; // Yellow level from 0 to max
BYTE CMY332Idx; // Original windows 2000 CMY332 Index
} INKLEVELS, *PINKLEVELS;
Example GenerateInkLevels Function
The GenerateInkLevels function computes an 8-bit-per-pixel translation table of INKLEVELS structures, based on the values in the CMYMask and CMYInverted parameters. This function generates an INKLEVELS translation table for a valid CMYMask value in the range 0 to 255.
When this function is called, the pInkLevels parameter must point to a valid memory location of 256 INKLEVELS entries. If the function returns TRUE, then pInkLevels can be used to translate 8-bit-per-pixel indexes to ink levels, or to map to the older CMY332 indexes. If the function is called with CMYMask set to an invalid value (a value from 3 to 255 in which any of the cyan, magenta, or yellow levels is zero), the function returns FALSE.
BOOL
GenerateInkLevels(
PINKLEVELS pInkLevels, // Pointer to 256 INKLEVELS table
BYTE CMYMask, // CMYMask mode
BOOL CMYInverted // TRUE for CMY_INVERTED mode
)
{
PINKLEVELS pILDup;
PINKLEVELS pILEnd;
INKLEVELS InkLevels;
INT Count;
INT IdxInc;
INT cC; // Number of Cyan levels
INT cM; // Number of Magenta levels
INT cY; // Number of Yellow levels
INT xC; // Max. number Cyan levels
INT xM; // Max. number Magenta levels
INT xY; // Max. number Yellow levels
INT iC;
INT iM;
INT iY;
INT mC;
INT mM;
switch (CMYMask) {
case 0:
cC =
cM =
xC =
xM = 0;
cY =
xY = 255;
break;
case 1:
case 2:
cC =
cM =
cY =
xC =
xM =
xY = 3 + (INT)CMYMask;
break;
default:
cC = (INT)((CMYMask >> 5) & 0x07);
cM = (INT)((CMYMask >> 2) & 0x07);
cY = (INT)( CMYMask & 0x03);
xC = 7;
xM = 7;
xY = 3;
break;
} // end switch statement
Count = (cC + 1) * (cM + 1) * (cY + 1);
if ((Count < 1) || (Count > 256)) {
return(FALSE);
}
InkLevels.Cyan =
InkLevels.Magenta =
InkLevels.Yellow =
InkLevels.CMY332Idx = 0;
mC = (xM + 1) * (xY + 1);
mM = xY + 1;
pILDup = NULL;
if (CMYInverted) {
//
// Move the pInkLevels to the first entry following
// the centered embedded entries.
// Skipped entries are set to white (zero). Because this
// is a CMY_INVERTED mode, entries start from back of the
// table and move toward the beginning of the table.
//
pILEnd = pInkLevels - 1;
IdxInc = ((256 - Count - (Count & 0x01)) / 2);
pInkLevels += 255;
while (IdxInc--) {
*pInkLevels-- = InkLevels;
}
if (Count & 0x01) {
//
// If we have an odd number of entries, we need to
// duplicate the center one for the XOR ROP to
// operate correctly. pILDup will always be index
// 127, and the duplicates are at indexes 127 and 128.
//
pILDup = pInkLevels - (Count / 2) - 1;
}
//
// We are running from the end of table to the beginning,
// because in CMY_INVERTED mode, index 0 is black and
// index 255 is white. Since we generate only Count
// white, black, and colored indexes, and place them at
// the center, we will change xC, xM, xY max. indexes
// to the same as cC, cM and cY
// so we only compute cC*cM*cY entries.
//
IdxInc = -1;
xC = cC;
xM = cM;
xY = cY;
} else {
IdxInc = 1;
pILEnd = pInkLevels + 256;
}
//
// In the following composition of ink levels, the index
// always runs from 0 ink level (white) to maximum ink
// levels (black). With CMY_INVERTED mode, we compose ink
// levels from index 255 to index 0 rather than from index
// 0 to 255.
//
if (CMYMask) {
INT Idx332C;
INT Idx332M;
for (iC = 0, Idx332C = -mC; iC <= xC; iC++) {
if (iC <= cC) {
InkLevels.Cyan = (BYTE)iC;
Idx332C += mC;
}
for (iM = 0, Idx332M = -mM; iM <= xM; iM++) {
if (iM <= cM) {
InkLevels.Magenta = (BYTE)iM;
Idx332M += mM;
}
for (iY = 0; iY <= xY; iY++) {
if (iY <= cY) {
InkLevels.Yellow = (BYTE)iY;
}
InkLevels.CMY332Idx = (BYTE)(Idx332C +
Idx332M) +
InkLevels.Yellow;
*pInkLevels = InkLevels;
if ((pInkLevels += IdxInc) == pILDup) {
*pInkLevels = InkLevels;
pInkLevels += IdxInc;
}
}
}
}
//
// Now, if we need to pad black at the other end of the
// translation table, then do it here. Notice that
// InkLevels are at cC, cM and cY here and CMY332Idx
// is at black.
//
while (pInkLevels != pILEnd) {
*pInkLevels = InkLevels;
pInkLevels += IdxInc;
}
} else {
//
// Gray Scale case
//
for (iC = 0; iC < 256; iC++, pInkLevels += IdxInc) {
pInkLevels->Cyan =
pInkLevels->Magenta =
pInkLevels->Yellow =
pInkLevels->CMY332Idx = (BYTE)iC;
}
}
return(TRUE);
}