Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# ImageProcessing
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 at 20-Jul-11 7:34am
   
first you needed 8bpp to 16 and now 32 to 8.......??
ankur.mu at 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 at 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 at 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
0 Sergey Alexandrovich Kryukov 609
1 OriginalGriff 587
2 Maciej Los 325
3 Mathew Soji 195
4 BillWoodruff 190
0 OriginalGriff 7,356
1 Sergey Alexandrovich Kryukov 6,712
2 DamithSL 5,461
3 Manas Bhardwaj 4,916
4 Maciej Los 4,475


Advertise | Privacy | Mobile
Web01 | 2.8.1411023.1 | Last Updated 15 Sep 2014
Copyright © CodeProject, 1999-2014
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