57

I need to convert a Bitmap from PixelFormat.Format32bppRgb to PixelFormat.Format32bppArgb.

I was hoping to use Bitmap.Clone, but it does not seem to be working.

Bitmap orig = new Bitmap("orig.bmp");
Bitmap clone = orig.Clone(new Rectangle(0,0,orig.Width,orig.Height), PixelFormat.Format24bppArgb);

If I run the above code and then check clone.PixelFormat it is set to PixelFormat.Format32bppRgb. What is going on/how do I convert the format?

Omar
  • 16,329
  • 10
  • 48
  • 66
Jono
  • 1,690
  • 2
  • 18
  • 29
  • 2
    Does this only happen on XP? I found the problem on XP but it seems to work fine on Windows 7. Hans' solution fixed it for me. – Sugrue Mar 21 '13 at 14:11
  • 1
    That's kind of funny. I have a solution that works fine on XP but breaks, giving this error, on Windows 7... – Matt Klein Apr 15 '13 at 14:54
  • I can confirm that only XP is affected. – PMF Nov 20 '13 at 14:59
  • You should watch out on systems that aren't XP too. I haven't tested this spesific code, but working on the pixel level when comparing two images on Windows 7 I ran into a similar problem that was caused from this bug/feature. Dan7 explained exactly what is happening and a more general approach to fixing it. – Eric Feb 10 '15 at 08:01
  • [This](https://docs.kgysoft.net/drawing/?topic=html/M_KGySoft_Drawing_ImageExtensions_ConvertPixelFormat_1.htm) works on all platforms (disclaimer: written by me). Can be downloaded as a [NuGet](https://www.nuget.org/packages/KGySoft.Drawing). – György Kőszeg Jul 23 '20 at 08:37

3 Answers3

103

Sloppy, not uncommon for GDI+. This fixes it:

Bitmap orig = new Bitmap(@"c:\temp\24bpp.bmp");
Bitmap clone = new Bitmap(orig.Width, orig.Height,
    System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

using (Graphics gr = Graphics.FromImage(clone)) {
    gr.DrawImage(orig, new Rectangle(0, 0, clone.Width, clone.Height));
}

// Dispose orig as necessary...
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I had a similar issue to the OP, except I had problems with a 48BppRgb TIFF that was saved as 32BppArgb PNG. GDI+ couldn't convert properly and the resulting image was very dark. This solution allowed me to solve that problem by manually redrawing the image as 32BppRgb, so +1. – Tom Lint Feb 03 '17 at 13:24
38

For some reason if you create a Bitmap from a file path, i.e. Bitmap bmp = new Bitmap("myimage.jpg");, and call Clone() on it, the returned Bitmap will not be converted.

However if you create another Bitmap from your old Bitmap, Clone() will work as intended.

Try something like this:

using (Bitmap oldBmp = new Bitmap("myimage.jpg"))
using (Bitmap newBmp = new Bitmap(oldBmp))
using (Bitmap targetBmp = newBmp.Clone(new Rectangle(0, 0, newBmp.Width, newBmp.Height), PixelFormat.Format32bppArgb))
{
    // targetBmp is now in the desired format.
}
Dan7
  • 1,657
  • 1
  • 19
  • 31
  • 6
    +1 Thanks Dan7 for explaining what the trigger was. I've seen `new Bitmap(new Bitmap("image.jpg"))` before but didn't know why it worked. – Matt Klein Apr 15 '13 at 14:47
  • is there an easy way to `Clone` and convert all the pages of the bitmap ? I've noticed that `targtBmp` only has the active frame in `oldBmp`. – Ciprian Tomoiagă Jul 08 '16 at 20:32
  • This better than marked "Solution" - it's worked with Indexed PixelFormat 4bpp, 8bpp – Geograph Jul 09 '18 at 15:40
8
using (var bmp = new Bitmap(width, height, PixelFormat.Format24bppArgb))
using (var g = Graphics.FromImage(bmp)) {
  g.DrawImage(..);
}

Should work like that. Maybe you want to set some parameters on g to define the interpolation mode for quality etc.

Benjamin Podszun
  • 9,679
  • 3
  • 34
  • 45
  • InterpolationMode is for scaling, i don't really think that he wants to scale it. Maybe do something like bmp.SetResolution(old.HorizontalResolution, old.VerticalResolution) and call g.DrawImageUnscaled(old, 0,0). But its just my opinion :) – lauCosma Jul 01 '14 at 17:41
  • @Elmue - do you have any reference to your statement?MSDN states other.. – ephraim Nov 26 '17 at 20:35