Click here to Skip to main content
15,886,110 members
Articles / Desktop Programming / MFC
Article

Image Bit depth conversion from 32 Bit to 8 Bit

Rate me:
Please Sign up or sign in to vote.
3.43/5 (17 votes)
20 May 2004CPOL2 min read 176.6K   35   19
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:

Image 1

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.

C#
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:

C#
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.

C#
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:

C#
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!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer NeST
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionImage Bit depth conversion from 32 Bit to 8 Bit Pin
Member 852860725-Mar-19 23:34
Member 852860725-Mar-19 23:34 
Generalpixel data Pin
sandeeprattu1-Jul-09 21:18
sandeeprattu1-Jul-09 21:18 
Questionconvert 16 bit to 8 bit? Pin
harshi_mm214-Feb-08 0:34
harshi_mm214-Feb-08 0:34 
GeneralConversion of 16 bit to 8 bit or 24 bit Pin
harshi_mm211-Feb-08 22:25
harshi_mm211-Feb-08 22:25 
GeneralConversion from 8-bit to 32-bit Pin
Nilesh Kontamwar17-Jul-07 1:30
Nilesh Kontamwar17-Jul-07 1:30 
GeneralRe: Conversion from 8-bit to 32-bit Pin
Nilesh Kontamwar22-Jul-07 18:08
Nilesh Kontamwar22-Jul-07 18:08 
Generalexception:-array index out of bounds Pin
Platinumhimani27-Nov-06 20:37
Platinumhimani27-Nov-06 20:37 
GeneralRe: exception:-array index out of bounds Pin
Shanu K S29-Nov-06 17:18
Shanu K S29-Nov-06 17:18 
GeneralMissing parts of the code... Pin
IsmailLunat19-Aug-06 3:07
IsmailLunat19-Aug-06 3:07 
GeneralRe: Missing parts of the code... [modified] Pin
npkinh19-Feb-08 15:11
npkinh19-Feb-08 15:11 
GeneralHelp plz.........very urgent Pin
Ashwini Iyengar25-Mar-05 22:07
Ashwini Iyengar25-Mar-05 22:07 
GeneralErm... Pin
Christian Graus3-Mar-05 13:41
protectorChristian Graus3-Mar-05 13:41 
GeneralRe: Erm... Pin
Teashirt219-Oct-07 9:50
Teashirt219-Oct-07 9:50 
GeneralCreating Image Pin
seasons1593-Mar-05 12:35
seasons1593-Mar-05 12:35 
Generalnon-aligned DWORD image width Pin
thollande28-Jul-04 23:15
thollande28-Jul-04 23:15 
I have used the code the convert images to 8 bits color depth. It works
pretty well except that I experienced few problems when the image width is not DWORD aligned. I also experienced that the resulting image was upside down. I fixed it and this is my version of the code. I hope it will help
someone experiencing the same problems :

int nDWordAlignedWidth = nImageWidth;<br />
if (nDWordAlignedWidth % sizeof(DWORD) != 0) {<br />
  // the image width is not a multiple of 4<br />
  nDWordAlignedWidth  += sizeof(DWORD) - nDWordAlignedWidth % sizeof(DWORD);<br />
}<br />
<br />
for (int nRow = 0; nRow < nImageHeight; nRow++) {<br />
   for (int  nCol = 0; nCol < nImageWidth; nCol++) {<br />
       unsigned long i8bppPixel = nRow * (unsigned long) nDWordAlignedWidth + nCol;<br />
	// Get pixel data from Input image.<br />
	COLORREF objColorData = ::GetPixel(hdc, nCol, ((nImageHeight - 1) - nRow));

Then the rest of my code is really similar to ShanuKS code. Thanks to him.
GeneralRe: non-aligned DWORD image width Pin
npkinh19-Feb-08 15:25
npkinh19-Feb-08 15:25 
Generalsample screen shot Pin
RabidCow21-May-04 12:18
RabidCow21-May-04 12:18 
GeneralRe: sample screen shot Pin
Shanu K S23-May-04 18:43
Shanu K S23-May-04 18:43 
GeneralCQuantizer Pin
Kochise21-May-04 4:05
Kochise21-May-04 4:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.