Answered by:
Loading image from 32 bits bitmap file

Question
-
I have a 32 bits bitmap file containing solid and transparent pixels, and I would like to load it into C# while preserving the data on the alpha channel.
I've tried using Bitmap.FromFile (filename), Bitmap.FromFile(filename, false), Image.FromFile(filename), Image.FromFile(false), and new Bitmap(filename), and none of them work. The loaded image contains solid pixel where it should have been transparent, and the PixelFormat of the resulting image is RGB32 instead of ARGB32.
I've also tried:
Image im = Image.FromFile (filename);
Bitmap bmp = new Bitmap (im.Width, im.Height, PixelFormat.Format32bppArgb);
Graphics.FromImage(bmp).DrawImage(im, 0, 0);
This also leaves me with an Image of solid pixels.
What can I do?
Alex,
Alex,Monday, March 16, 2009 9:13 PM
Answers
-
byte[] B = File.ReadAllBytes("C:\\Temp\\Test.bmp"); GCHandle GCH = GCHandle.Alloc(B, GCHandleType.Pinned); IntPtr Scan0 = (IntPtr)((int)(GCH.AddrOfPinnedObject()) + 54); int W = Marshal.ReadInt32(Scan0, -36); int H = Marshal.ReadInt32(Scan0, -32); Bitmap Bmp = new Bitmap(W, H, 4 * W, PixelFormat.Format32bppArgb, Scan0); Bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); GCH.Free(); Friday, March 20, 2009 9:52 AM
All replies
-
Whenever I used Bitmap.FromFile on an image file that had an alpha channel, it preserved the transparency and the PixelFormat was "Format32bppArgb". I don't recall having your problem.
Can you give us a link to your file?
Fernando.
/* No comments */Monday, March 16, 2009 9:20 PM -
You can find the bitmap in question at http://csclub.uwaterloo.ca/~mtsay/test1.bmp
The white background is supposed to be transparent.
Alex,
Alex,Tuesday, March 17, 2009 1:17 PM -
Still haven't found a solution, however, I tried something interesting that may shed some light on the issue:
{
Image a = Image.FromFile("test1.png");
a.Save("test1.bmp", ImageFormat.Bmp);
// some time later to avoid IOException
Image b = Image.FromFile("test1.bmp");
}
test1.png contains transparent pixels, a.PixelFormat showed Format32bppArgb.
However, b.PixelFormat showed Format32bppRgb. In addition, opening test1.bmp in other program shows that test1.bmp is saved in 32-bit bitmap format and the transparency is indeed preserved.
So the conclusion I've arrived at is that Image.FromFile (or the 4 other equivalent methods above) opens 32-bit bitmap in Format32bppRgb by default. Now the question is whether I can force GDI+ to load it in different format somehow?
Alex,Wednesday, March 18, 2009 3:39 PM -
According to MSDN:
"The Image class does not support alpha transparency in bitmaps. To enable alpha transparency, use PNG images with 32 bits per pixel."
Image.FromFile method
It does support alpla for png and tiffs.
If you have no choice other than using bmp, the only workaround a can think of is reading the bitmapdata manually and setting the pixels through LockBits.
/* No comments */Wednesday, March 18, 2009 3:54 PM -
Use Bitmap.MakeTransparent.
Bitmap b = Image.FromFile("test1.bmp");
b.MakeTransparent();Wednesday, March 18, 2009 4:23 PM -
JohnWein said:
Use Bitmap.MakeTransparent.
Bitmap b = Image.FromFile("test1.bmp");
b.MakeTransparent();
Doesn't work. This method makes the default color, solid white in this case, transparent.
Alex,Wednesday, March 18, 2009 5:20 PM -
The same image file is intended to be used with Direct Editing Services so I'm forced to stay with 32-bit bitmap with transparency. In the end, I end up parsing the data manually.
Alex,Wednesday, March 18, 2009 5:29 PM -
byte[] B = File.ReadAllBytes("C:\\Temp\\Test.bmp"); GCHandle GCH = GCHandle.Alloc(B, GCHandleType.Pinned); IntPtr Scan0 = (IntPtr)((int)(GCH.AddrOfPinnedObject()) + 54); int W = Marshal.ReadInt32(Scan0, -36); int H = Marshal.ReadInt32(Scan0, -32); Bitmap Bmp = new Bitmap(W, H, 4 * W, PixelFormat.Format32bppArgb, Scan0); Bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); GCH.Free(); Friday, March 20, 2009 9:52 AM -
Hi,
As I learnt from your post , you are trying to get the pixel value of a 32bits argb image file.
Please try the code below :
Bitmap bmp = new Bitmap("c:\\argb.png"); // Lock the bitmap's bits. Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); System.Drawing.Imaging.BitmapData bmpbmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // Get the address of the first line. IntPtr ptr = bmpData.Scan0; // Declare an array to hold the bytes of the bitmap. int bytes = bmpData.Stride * bmp.Height; byte[] rgbValues = new byte[bytes]; // Copy the RGB values into the array. System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
The array rgbValues will hold the data .
Best regards,
Harry
http://cfx.codeplex.com where you can find samples you are looking forFriday, March 20, 2009 12:03 PM -
Harry Zhu:
Your code doesn't preserve the alpha channel. Why the OP has abandoned the thread is unknown.Monday, March 23, 2009 12:34 PM -
Hi JohnWein,
I try the code in my post with a 32argb image, and got 4 bytes of a pixel . I think the first byte of them is the alpha byte.
Could you please explain why the code dose not preserve the alpha channel?
Best regards,
Harry
http://cfx.codeplex.com where you can find samples you are looking forMonday, March 23, 2009 12:44 PM -
That's the whole point of this thread. When you load a bitmap as you have done, all the alpha channel information is lost. All the alpha bytes are 255.Monday, March 23, 2009 1:07 PM
-
JohnWein: I end up doing more or less of what you have posted above: read in all bytes, extracts image dimension and scanline, and use that same bitmap constructor; and it has been working fine.
Harry Zhu: Your code relies on the bitmap constructor to parse the file. It works fine on a variety of file formats but not 32-bit bitmaps ( .bmp ). If you try drawing that bitmap over another image background then you'll see that the alpha channel of the bitmap is completely disregarded.
Alex,Monday, March 23, 2009 1:09 PM -
Hi,
The code works here , also I can modify the Alpha value in the code :
if (bmp.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) { for (int counter = 3; counter < rgbValues.Length; counter += 4) rgbValues[counter] = 100; }
Then I save the image to another file . The next time I read the new file and get the alpha value which have been changed to 100.
Anyway, I am glad you have found the solution.
Harry
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.Monday, March 23, 2009 1:22 PM -
Harry Zhu: Your code above showed you were loading a PNG ("C:\\argb.png") instead of a 32-bit bitmap. Are you saying your code works for a 32-bit bitmap such as the link I posted above?
Alex,Monday, March 23, 2009 3:44 PM -
Hi,
You may try to load other kind of file ,like jpeg ,bmp..., I think they will work as well.
Harry
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.Tuesday, March 24, 2009 12:46 AM -
No Harry. That's the reason for this thread. You can't load a 32 bit .bmp image and retain the alpha channel in .NET. Try loading the OP's file.Tuesday, March 24, 2009 3:12 AM
-
Hi,
I downloaded the bitmap ,and found the the pixformat of the bitmap is Format32bppRgb, so maybe that's the reason why the alpha value is always 0.
Harry
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.Tuesday, March 24, 2009 3:21 AM -
That's what happens when you load it. You loose the alpha channel. Display the bitmap in a PictureBox using your code and using my code. This thread's subject is "Loading image from 32 bits bitmap file". You have now found the problem.Tuesday, March 24, 2009 3:32 AM
-
Hi JohnWein,
I did not get the post correctly at first.
Thanks for your explaination!
Best regards,
Harry
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.- Proposed as answer by Vinay Mohan Monday, July 19, 2010 6:45 AM
Tuesday, March 24, 2009 3:37 AM -
Hi All,
I had also faced a similar issue while loading 32 bit bitmaps with alpha channel.I had overcome this issue by creating a new memory bitmap with alpha channel(32bppArgb) and copying the rgb values of original bitmap via a BitmapData object.
using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(@"C:\test32.bmp"))) { using (bitmapImage = (Bitmap)Bitmap.FromStream(ms, true, false)) { if (Bitmap.GetPixelFormatSize(bitmapImage.PixelFormat) == 32) { // Allocate the destination bitmap in ARGB format Bitmap bitmapARGBImage = new Bitmap(bitmapImage.Width, bitmapImage.Height, PixelFormat.Format32bppArgb); // Lock the original bitmap's bits BitmapData bmpData = bitmapImage.LockBits(new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height), ImageLockMode.WriteOnly, bitmapImage.PixelFormat); // Declare an array to hold the bytes of the original bitmap byte[] rgbValues = new byte[bmpData.Stride * bitmapImage.Height]; // Copy the RGB values into the array // bmpData.Scan0 is the address of the first pixel data in the bitmap Marshal.Copy(bmpData.Scan0, rgbValues, 0, bmpData.Stride * bitmapImage.Height); // Unlock the bits from the system memory bitmapImage.UnlockBits(bmpData); // Release bitmap data if (bmpData != null) bmpData = null; // Lock the new memory bitmap with alphachannel bitmap's bits bmpData = bitmapARGBImage.LockBits(new Rectangle(0, 0, bitmapARGBImage.Width, bitmapARGBImage.Height), ImageLockMode.WriteOnly, bitmapARGBImage.PixelFormat); // Copy the RGB values of original bitmap back to the new bitmap with alpha channel Marshal.Copy(rgbValues, 0, bmpData.Scan0, bmpData.Stride * bitmapARGBImage.Height); // Unlock the bits from the system memory bitmapARGBImage.UnlockBits(bmpData); // Save the image to the memory stream and convert it to Png format bitmapARGBImage.Save(ms, ImageFormat.Png); // Set the page's content type context.Response.ContentType = "image/png"; // Send the image to the browser ms.WriteTo(context.Response.OutputStream); // Release resources if (bmpData != null) bmpData = null; if (rgbValues != null) rgbValues = null; } } }
Hope this helps!
Thanks,
Vinay \m/- Proposed as answer by Vinay Mohan Friday, July 23, 2010 9:43 AM
- Unproposed as answer by Vinay Mohan Tuesday, August 16, 2011 10:41 AM
- Proposed as answer by Vinay Mohan Tuesday, August 16, 2011 10:41 AM
Monday, July 19, 2010 9:04 AM -
Alex did you ever find a solution to the bmp Alpha channel problem?
I am facing the same issue and going a little crazy.
My bmp does load with format 32bppARGB however, the alpha values are all 255 not the correct Alpha channel values.
Friday, April 6, 2012 10:01 PM