Figure 2: CImage member function SetColorTable

bool
CImage::SetColorTable(const CImageColorTable& clrTbl, bool bRemap)
    {
    _ASSERT(m_hImage);
    _ASSERT(BPP() == 8);

    if (bRemap)
        {
        // go through all pixels and map to new or nearest color
        unsigned int numColors = NumColorEntries();

        // create palette of new color table, so we can use
        // GetNearestPaletteIndex
        CImagePalette newPal;
        if (!newPal.CreatePalette(clrTbl))
            return false;

        // get the current color table
        CImageColorTable oldClrTbl(numColors);
        GetColorTable(oldClrTbl);
        unsigned char* pPixel;
        UINT newIndex;

        // allocate as many structures as there are current colors
        // MapIndex are used for quick lookup for color table
        // entries that have already been converted to new ones by
        // GetNearestPaletteIndex
        MapIndexArray mp_array(numColors);
        for (int y = 0;y < Height();y++)
            {
            pPixel =
                static_cast<unsigned char*>(GetPixelAddress(0,y));
            for (int x = 0;x < Width();x++,pPixel++)
                {
                _ASSERT(0 <= (*pPixel) && (*pPixel) < numColors);
                if (false == mp_array[*pPixel].bMapped)
                    {
                    // color not mapped to new color table
                    mp_array[*pPixel].bMapped = true;
                    newIndex =
                        newPal.GetNearestPaletteIndex(
                            oldClrTbl.color(*pPixel));
                    if (CLR_INVALID == newIndex)
                        return false;
                    mp_array[*pPixel].newIndex =
                        static_cast<unsigned char>(newIndex);
                    }
                // set pixel to new color
                *pPixel = mp_array[*pPixel].newIndex;
                }
            }
        }

    // now all pixels are remapped to new colors,
    // insert new color table
    CImageDC memdc;
    if (!memdc.CreateCompatibleDC())
        return false;
    memdc.SelectBitmap(m_hImage);
    UINT result =
        ::SetDIBColorTable(memdc, 0, clrTbl.size(),
            clrTbl.m_prgb);
    SetNumColorEntries(clrTbl.size());

    return result? true:false;
    }
//End of File