Click here to Skip to main content
15,881,882 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I want to convert 32 bpp bitmap into 8 bpp.

If anyone knows how to do it, plz help.

Thanks in Advance.
Posted
Comments
Herman<T>.Instance 20-Jul-11 7:34am    
first you needed 8bpp to 16 and now 32 to 8.......??
ankur.mu 20-Jul-11 7:37am    
actually when i read the bitmap image from an avi file using memory stream..the avi file is 8bpp but memory stream converts it into 32 bpp & adds random colors to the image. I want to retrive the 8bpp bitmap image in the same color & not with different random colors. Heres the code:





public Bitmap GetBitmap(int position){
if(position > countFrames){
throw new Exception("Invalid frame position: "+position);
}

Avi.AVISTREAMINFO streamInfo = GetStreamInfo(StreamPointer);

//Decompress the frame and return a pointer to the DIB
int dib = Avi.AVIStreamGetFrame(getFrameObject, firstFrame + position);
//Copy the bitmap header into a managed struct
Avi.BITMAPINFOHEADER bih = new Avi.BITMAPINFOHEADER();
bih = (Avi.BITMAPINFOHEADER)Marshal.PtrToStructure(new IntPtr(dib), bih.GetType());

if(bih.biSizeImage < 1){
throw new Exception("Exception in VideoStreamGetFrame");
}

//copy the image

byte[] bitmapData;
int address = dib + Marshal.SizeOf(bih);


Bitmap saveableBitmap;

if (bih.biBitCount < 16)
{
//copy palette and pixels
// Bitmap b = (Bitmap)Image.FromStream(aviStream);
bitmapData = new byte[bih.biSizeImage + Avi.PALETTE_SIZE];


}
else
{
//copy only pixels
bitmapData = new byte[bih.biSizeImage];
}

Marshal.Copy(new IntPtr(address), bitmapData, 0, bitmapData.Length);

//copy bitmap info
byte[] bitmapInfo = new byte[Marshal.SizeOf(bih)];
IntPtr ptr;
ptr = Marshal.AllocHGlobal(bitmapInfo.Length);
Marshal.StructureToPtr(bih, ptr, false);
address = ptr.ToInt32();
Marshal.Copy(new IntPtr(address), bitmapInfo, 0, bitmapInfo.Length);

Marshal.FreeHGlobal(ptr);

//create file header
Avi.BITMAPFILEHEADER bfh = new Avi.BITMAPFILEHEADER();
bfh.bfType = Avi.BMP_MAGIC_COOKIE;
bfh.bfSize = (Int32)(55 + bih.biSizeImage); //size of file as written to disk
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = Marshal.SizeOf(bih) + Marshal.SizeOf(bfh);
if (bih.biBitCount < 16)
{
//There is a palette between header and pixel data
bfh.bfOffBits += Avi.PALETTE_SIZE;
}

//write a bitmap stream
BinaryWriter bw = new BinaryWriter(new MemoryStream());

//write header
bw.Write(bfh.bfType);
bw.Write(bfh.bfSize);
bw.Write(bfh.bfReserved1);
bw.Write(bfh.bfReserved2);
bw.Write(bfh.bfOffBits);
//write bitmap info
bw.Write(bitmapInfo);
//write bitmap data
bw.Write(bitmapData);

Bitmap bmp = (Bitmap)Image.FromStream(bw.BaseStream);
saveableBitmap = new Bitmap(bmp.Width, bmp.Height);
Graphics g = Graphics.FromImage(saveableBitmap);
g.DrawImage(bmp, 0, 0);
g.Dispose();
bmp.Dispose();

bw.Close();

return saveableBitmap;
}




Please help me I am new to C#.

Thanks in Advance.
ankur.mu 20-Jul-11 7:45am    
ok! but when the compiler implicitly converts 8bpp to 32bpp when placing on clipboard or memory stream, why does it add random colors by itself?? Is there a way to avoid that?? THANKS!!

Here is the code to this :


public static Bitmap ColorToGrayscale(Bitmap bmp)
{
int w = bmp.Width,
h = bmp.Height,
r, ic, oc, bmpStride, outputStride, bytesPerPixel;
PixelFormat pfIn = bmp.PixelFormat;
ColorPalette palette;
Bitmap output;
BitmapData bmpData, outputData;

//Create the new bitmap
output = new Bitmap(w, h, PixelFormat.Format8bppIndexed);

//Build a grayscale color Palette
palette = output.Palette;
for (int i = 0; i < 256; i++)
{
Color tmp = Color.FromArgb(255, i, i, i);
palette.Entries[ i ] = Color.FromArgb(255, i, i, i);
}
output.Palette = palette;

//No need to convert formats if already in 8 bit
if (pfIn == PixelFormat.Format8bppIndexed)
{
output = (Bitmap)bmp.Clone();

//Make sure the palette is a grayscale palette and not some other
//8-bit indexed palette
output.Palette = palette;

return output;
}

//Get the number of bytes per pixel
switch (pfIn)
{
case PixelFormat.Format24bppRgb: bytesPerPixel = 3; break;
case PixelFormat.Format32bppArgb: bytesPerPixel = 4; break;
case PixelFormat.Format32bppRgb: bytesPerPixel = 4; break;
default: throw new InvalidOperationException("Image format not supported");
}

//Lock the images
bmpData = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly,
pfIn);
outputData = output.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly,
PixelFormat.Format8bppIndexed);
bmpStride = bmpData.Stride;
outputStride = outputData.Stride;

//Traverse each pixel of the image
unsafe
{
byte* bmpPtr = (byte*)bmpData.Scan0.ToPointer(),
outputPtr = (byte*)outputData.Scan0.ToPointer();

if (bytesPerPixel == 3)
{
//Convert the pixel to it's luminance using the formula:
// L = .299*R + .587*G + .114*B
//Note that ic is the input column and oc is the output column
for (r = 0; r < h; r++)
for (ic = oc = 0; oc < w; ic += 3, ++oc)
outputPtr[r * outputStride + oc] = (byte)(int)
(0.299f * bmpPtr[r * bmpStride + ic] +
0.587f * bmpPtr[r * bmpStride + ic + 1] +
0.114f * bmpPtr[r * bmpStride + ic + 2]);
}
else //bytesPerPixel == 4
{
//Convert the pixel to it's luminance using the formula:
// L = alpha * (.299*R + .587*G + .114*B)
//Note that ic is the input column and oc is the output column
for (r = 0; r < h; r++)
for (ic = oc = 0; oc < w; ic += 4, ++oc)
outputPtr[r * outputStride + oc] = (byte)(int)
((bmpPtr[r * bmpStride + ic] / 255.0f) *
(0.299f * bmpPtr[r * bmpStride + ic + 1] +
0.587f * bmpPtr[r * bmpStride + ic + 2] +
0.114f * bmpPtr[r * bmpStride + ic + 3]));
}
}

//Unlock the images
bmp.UnlockBits(bmpData);
output.UnlockBits(outputData);

return output;
}
 
Share this answer
 
v2
Look for the following search term on google:

convert 32 bpp bitmap into 8 bpp "C#"


Another job well done ;)
 
Share this answer
 
Comments
ankur.mu 20-Jul-11 7:42am    
ok! but when the compiler implicitly converts 8bpp to 32bpp when placing on clipboard or memory stream, why does it add random colors by itself?? Is there a way to avoid that??
THANKS!!
additional for error unsafe code:
Just go to project properties --> build--> check the checkbox "allow unsafe code".
 
Share this answer
 

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900