Condividi tramite


Conversione di indici mezzotone a 8 bit a pixel in livelli di input penna

La funzione GenerateInkLevels illustrata di seguito fornisce un esempio di come tradurre gli indici a mezzotone a 8 bit in livelli di input penna. Questi indici sono contenuti in modalità CMY e CMY_INVERTED tavolozze di modalità che la funzione di HT_Get8BPPMaskPalette GDI restituisce nel parametro pPaletteEntry . GenerateInkLevels genera una matrice di 256 elementi di strutture INKLEVELS.

Questa funzione può essere usata per generare una modalità CMY di Windows 2000 o una tabella di traduzione in modalità CMY_INVERTED post-Windows 2000. Questa funzione può essere usata anche per generare una tabella di indice di mapping inverso in modalità CMY 2000 CMY 2000. (CMY332 usa tre bit per ciano e magenta e due bit per giallo). Quando il valore CMYMask si trova nell'intervallo da 3 a 255, il chiamante della funzione può usare questa tabella per eseguire il mapping degli indici di CMY_INVERTED di Windows 2000 a Windows 2000 CMY per i driver attualmente esistenti.

Struttura INKLEVELS

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;

Funzione GenerateInkLevels di esempio

La funzione GenerateInkLevels calcola una tabella di conversione a 8 bit per pixel delle strutture INKLEVELS, in base ai valori nei parametri CMYMask e CMYInverted. Questa funzione genera una tabella di conversione INKLEVELS per un valore CMYMask valido nell'intervallo da 0 a 255.

Quando questa funzione viene chiamata, il parametro pInkLevels deve puntare a una posizione di memoria valida di 256 voci INKLEVELS. Se la funzione restituisce TRUE, pInkLevels può essere usata per convertire gli indici a 8 bit per pixel in livelli di input penna o per eseguire il mapping agli indici CMY332 meno recenti. Se la funzione viene chiamata con CMYMask impostata su un valore non valido (valore compreso tra 3 e 255 in cui uno dei livelli di ciano, magenta o giallo è zero), la funzione restituisce 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);
}