Click here to Skip to main content
12,065,888 members (26,389 online)
Rate this:
 
Please Sign up or sign in to vote.
See more: C# Image-Processing
I want to convert 32 bpp bitmap into 8 bpp.

If anyone knows how to do it, plz help.

Thanks in Advance.
Posted 20-Jul-11 2:30am
Comments
digimanus 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!!
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 2

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;
}
  Permalink  
v2
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 1

Look for the following search term on google:

convert 32 bpp bitmap into 8 bpp "C#"


Another job well done Wink | ;)
  Permalink  
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!!
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 3

additional for error unsafe code:
Just go to project properties --> build--> check the checkbox "allow unsafe code".
  Permalink  

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

  Print Answers RSS
Top Experts
Last 24hrsThis month


Advertise | Privacy | Mobile
Web04 | 2.8.160207.1 | Last Updated 15 Sep 2014
Copyright © CodeProject, 1999-2016
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100