22

I'm copying an image. (My actual code is resizing the image but that's not relevant to my question.) My code looks something like this.

Image src = ...

using (Image dest = new Bitmap(width, height))
{
    Graphics graph = Graphics.FromImage(dest);
    graph.InterpolationMode = InterpolationMode.HighQualityBicubic;
    graph.DrawImage(src, 0, 0, width, height);
    dest.Save(filename, saveFormat);
}

This seems to work great unless src is loaded from an image with transparencies (such as GIF) or an alpha channel (such as PNG).

How can I get DrawImage() to transfer the transparencies/alpha channel to the new image, and then keep them when I save the file?

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
  • 1
    The question is what is the value of `saveFormat` variable? It should be `PixelFormat.Format32bppArgb` (or another format with alpha channel handled). Try also: `using (Image dest = new Bitmap(width, height, PixelFormat.Format32bppArgb))`. – Lukasz M May 18 '12 at 20:05
  • This seems to work for alpha channels, but not for GIF transparencies. `saveFormat` will vary depending on the format of the input file. If the input file does not support alpha channel, then it's safe to assume the image will not contain alpha channel pixels. – Jonathan Wood May 18 '12 at 20:13
  • So, what's the value of `saveFormat` for GIF files then:)? – Lukasz M May 18 '12 at 20:18
  • In that case, it's `ImageFormat.Gif`. – Jonathan Wood May 18 '12 at 20:20
  • Thanks for a quick reply. In the meantime I've found an article about GIF transparency. Take a look at it: http://support.microsoft.com/kb/319061. I suppose that basically you just have to get the image's palette and set the color saved in the first index to a transparent one. – Lukasz M May 18 '12 at 20:23
  • Yikes. Thanks, but a lot of that I didn't quite follow. Either way, if I need all that code just for handling GIF files, that is unfortunate indeed. Still looking... – Jonathan Wood May 18 '12 at 20:27
  • BTW, I also tried `using (Image dest = new Bitmap(src, width, height))`. This makes the image compatible with the source image. As with your recommendation, this supports alpha channels but not, unfortunately, GIF transparencies. – Jonathan Wood May 18 '12 at 20:39
  • I can't find appropriate file to test it, but try: `if (saveFormat == ImageFormat.Gif && src.Palette.Entries.Length > 0) { System.Drawing.Color firstColor = src.Palette.Entries[0]; src.Palette.Entries[0] = System.Drawing.Color.FromArgb(0, firstColor); }` before file saving. – Lukasz M May 18 '12 at 21:10
  • Sorry, there was a mistake in the previous comment. I meant you should change the Palette for destination image of course (not in src). – Lukasz M May 18 '12 at 21:24
  • Or you can try this across the board, may work: `src.Palette.Entries.CopyTo(dest.Palette.Entries, 0);` – yamen May 18 '12 at 21:55
  • @JonathanWood: Have you tried to use my suggetion with updating the Palette? – Lukasz M May 19 '12 at 09:47
  • @Lucas: I have not. This is only part of a large task we're working on, and GIF files are only an small portion of the files we want to support. I've not yet determined that it's worth writing custom code just for GIF transparencies. I may determine that later. I appreciate the input. – Jonathan Wood May 19 '12 at 15:15
  • If the solution I described worked for you, maybe the other formats (for which it does not work) are also associated with modification of palette or/and creating bitmap with alpha channel support. – Lukasz M May 19 '12 at 15:26

2 Answers2

30

It is pretty unclear, there's a lot you didn't say. The biggest issue with transparency is that you can't see it. You skipped a couple of steps, you didn't explicitly specify the pixel format of your new bitmap, you didn't initialize it at all and you didn't say what output format you use. Some don't support transparency. So let's make a version that makes it crystal clear. From a PNG image that looks like this in paint.net:

enter image description here

Using this code

        using (var src = new Bitmap("c:/temp/trans.png"))
        using (var bmp = new Bitmap(100, 100, PixelFormat.Format32bppPArgb)) 
        using (var gr = Graphics.FromImage(bmp)) {
            gr.Clear(Color.Blue);
            gr.DrawImage(src, new Rectangle(0, 0, bmp.Width, bmp.Height));
            bmp.Save("c:/temp/result.png", ImageFormat.Png);
        }

Produces this image:

enter image description here

You can clearly see the blue background so the transparency worked.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    Well, my intent was to support whichever format matched the input file. I thought I was pretty specific. It's just that the code wasn't meant to support only one file type. Perhaps I need a bunch of code to handle each file type--I don't know. I did try specifying the PixelFormat as you have, but then it seemed like that was causing errors when the file type was GIF with transparency. And, in fact, some variations seemed to work fine with PNGs without specifying the PixelFormat. – Jonathan Wood May 19 '12 at 01:42
  • @JonathanWood create a new bitmap with the old bitmap's width and height, and your new desired format. Preferably in a `using` statement, create a Graphics object `FromImage(`your new bitmap`)` and `DrawImage(`your old bitmap`)`. –  Feb 20 '16 at 16:10
0

I found this thread because I had the same problem (i.e. DrawImage didn't copy the alpha channel), but in my case it was simply because I overlooked that I used PixelFormat.Format32bppRgb instead of PixelFormat.Format32bppArgb. So pretty much what Lukasz M said in the comments.

Alex
  • 1,198
  • 2
  • 12
  • 26