65.9K
CodeProject is changing. Read more.
Home

Image Bit depth conversion from 32 Bit to 8 Bit

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.43/5 (17 votes)

May 21, 2004

CPOL

2 min read

viewsIcon

178652

This article describes about image bit depth conversion from 32 bits to 8 bits.

Introduction

This article describes about image bit depth conversion from 32 bit to 8 bit. There are several methods for conversion. In this article, Indexed color and palette are used.

32 Bit to 8 Bit Conversion

There are several methods to convert to indexed color. Some methods are Dithering, Nearest Color, Adaptive or Optimized or Perceptual Palette, Standard Web Browser Palette etc. Here I am describing about Standard Web Browser Palette.

The Standard Palette (often called Web palette) always contains the same colors for any image. It is sometimes called 6-6-6, because it contains six standard evenly spaced colors for each of Red, Green, and Blue. Those 6x6x6 color combinations create 6x6x6 = 216 standard color combinations, which are used for any image.

The Standard Palette always contains combinations of the following 6 tones for each of the Red, Green, Blue primaries:

The 216 combinations of these 18 colors above (six shades of the three RGB colors, 6x6x6 = 216) produce the Standard web-safe palette. This Standard web-safe palette color shades are shown below:

Sample screenshot

First, we define a standard color table using those 6 colors.

const DWORD STANDARD_PALETTE[] = {00,51,102,153,204,255}
const INT STANDARD_COLOR_SIZE = 6;
const INT STANDARD_PALETTE_VAL_DIF = 51; 
// difference between two consecutive standard color Palette.

For 8 bit conversion, we must create a color table which is called as Palette color map. All possible combinations of Standard palette colors are entries in this table. Palette color map creation is shown below:

DWORD dwColorMapTable[216] = {0};
int  nColorMapIdx = 0;
for (int nBlueIdx = 0; nBlueIdx < STANDARD_COLOR_SIZE; ++nBlueIdx)
{
    for(int nGreenIdx = 0; nGreenIdx < STANDARD_COLOR_SIZE; ++nGreenIdx)
    {
        for(int nRedIdx = 0; nRedIdx < STANDARD_COLOR_SIZE; ++nRedIdx)
        {
            RGBQUAD objColor;
            objColor.rgbRed    = STANDARD_PALETTE[nRedIdx];
            objColor.rgbGreen = STANDARD_PALETTE[nGreenIdx];
            objColor.rgbBlue = STANDARD_PALETTE[nBlueIdx];
            objColor.rgbReserved = 0;
            memcpy(&dwColorMapTable[nColorMapIdx],&objColor,sizeof(RGBQUAD));
            ++nColorMapIdx;
        }
    }
}

After that, we can convert a 32 bit image file to 8 bit image file. For conversion, read each pixel data from input image data. Get Red, Green and Blue values from pixel. With these RGB values, calculate suitable color from STANDARD_PALETTE. Find suitable color from the Palette color map table. Set table map entry index to the output pixel value.

Cstring csInputFileName = "c:\\32BitImage.bmp";
Bitmap InputImage(csInputFileName,FALSE);
INT nImageHeight = InputImage .GetHeight();
INT nImageWidth = InputImage .GetWidth();
INT nPixelSize = nImageHeight * nImageWidth;
BYTE byBitsPerPixel = 32; // Input image Bits per pixel.
BYTE pixels = new BYTE[nPixelSize];
for(UINT nRow = 0; nRow < nImageHeight; ++nRow)
{
    for(UINT nCol = 0; nCol < nImageWidth; ++nCol)
    {
        Color objColorData;
        UINT i8bppPixel = nRow * nImageWidth + nCol;
        // Get pixel data from Input image.
        if(Ok != InputImage GetPixel(nCol,nRow,&objColorData))
        {
            printf("Get Image Pixel Failed.\n")
        }
        // Get RGB value from color data.
        int nRed = objColorData.GetRed();
        int nGreen = objColorData.GetGreen();
        int nBlue = objColorData.GetBlue();
        // Get Index of suitable color data in the palette table.
        UINT uRedValue = GetPixelValue(objColorData.GetRed());
        UINT uGreenValue = GetPixelValue(objColorData.GetGreen());
        UINT uBlueValue = GetPixelValue(objColorData.GetBlue());

        // Calculate Pixel color position
        // in the color map table using RGB values. 
        // Finally set this index in to the pixel data.
        UINT uPalettePos = uBlueValue*36+uGreenValue*6+uRedValue;
        pixels[i8bppPixel] =(BYTE)uPalettePos;
    }
}

GetPixelValue() returns appropriate pixel index value in the Standard Palette table. Implementation is shown below:

UINT GetPixelValue(UINT uPixelValue_i)
{
    UINT uRetValue = 0;
    UINT uPos = uPixelValue_i / PALETTE_VAL_DIF;
    if(0 == uPixelValue_i % PALETTE_VAL_DIF)
    {
        uRetValue = uPixelValue_i/PALETTE_VAL_DIF;
    }
    else
    {
        if(abs(uPixelValue_i - STANDARD_PALETTE [uPos]) > 
           abs(uPixelValue_i - STANDARD_PALETTE [uPos+1]))
        {
            uRetValue = uPos+1;
        }
        else
        {
            uRetValue = uPos;
        }
    }
    return uRetValue;
}

For viewing converted image:

  1. Create an output file.
  2. Write Bitmap header to the output file.
  3. Write pixel data to the output file.
  4. Close output file.

Good luck!