Why does resizing a png image lose transparency?

17,469

Solution 1

Your code doesn't do quite what you think that it does...

You use the GetThumbnailImage to resize the image, then you draw the thumbnail image into itself which is rather pointless. You probably lose the transparency in the first step.

Create a blank bitmap instead, and resize the source image by drawing it on the blank bitmap.

private byte[] GetThumbNail(string imageFile) {
  try {
    byte[] result;
    using (Image thumbnail = new Bitmap(160, 59)) {
      using (Bitmap source = new Bitmap(imageFile)) {
        using (Graphics g = Graphics.FromImage(thumbnail)) {
          g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
          g.InterpolationMode =  System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
          g.DrawImage(source, 0, 0, 160, 59);
        }
      }
      using (MemoryStream ms = new MemoryStream()) {
        thumbnail.Save(ms, ImageFormat.Png);
        thumbnail.Save("test.png", ImageFormat.Png);
        result = ms.ToArray();
      }
    }
    return result;
  } catch (Exception) {
    throw;
  }
}

(I removed some parameters that were never used for anything that had anything to do with the result, like the imageLen parameter that was only used to create a byte array that was never used.)

Solution 2

Try using the .MakeTransparent() call on your bitmap object.

Solution 3

May be you should do something like this because this thing worked for me:

String path = context.Server.MapPath("/images");
if (!path.EndsWith("\\"))
    path += "\\";
path += "none.png";

Image img = CreateThumbnail(Image.FromFile(path));

MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Png);
ms.WriteTo(context.Response.OutputStream);

private System.Drawing.Image CreateThumbnail(System.Drawing.Image i)
{
    int dWidth = i.Width;
    int dHeight = i.Height;
    int dMaxSize = 150;

    if (dWidth > dMaxSize)
    {
        dHeight = (dHeight * dMaxSize) / dWidth;
        dWidth = dMaxSize;
    }
    if (dHeight > dMaxSize)
    {
        dWidth = (dWidth * dMaxSize) / dHeight;
        dHeight = dMaxSize;
    }
    return i.GetThumbnailImage(dWidth, dHeight, delegate() { return false; }, IntPtr.Zero);
}
Share:
17,469
Admin
Author by

Admin

Updated on June 07, 2022

Comments

  • Admin
    Admin almost 2 years

    I am trying to resize an image as follows. I return the resized image into byte[] so that I can store it in database. The transparency of png image is lost. Please help to make this better.

    private byte[] GetThumbNail(string imageFile, Stream imageStream, 
      int imageLen)
    {
      try
      {
        Image.GetThumbnailImageAbort imageCallBack = 
          new Image.GetThumbnailImageAbort(ThumbnailCallback);
        Bitmap getBitmap = new Bitmap(imageFile);
        byte[] returnByte = new byte[imageLen];
        Image getThumbnail = getBitmap.GetThumbnailImage(160, 59, 
          imageCallBack, IntPtr.Zero);
        using (Graphics g = Graphics.FromImage(getThumbnail))
        {
          g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
          g.InterpolationMode = 
            System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
          g.DrawImage(getThumbnail, 0, 0, 160, 59);
        }
        using (MemoryStream ms = new MemoryStream())
        {
          getThumbnail.Save(ms, ImageFormat.Png);
          getThumbnail.Save("test.png", ImageFormat.Png);
          returnByte = ms.ToArray();
        }
        return returnByte;
      }
      catch (Exception)
      {
        throw;
      }
    }
    
  • Admin
    Admin about 15 years
    This solution also doesnt give me a transparent image.
  • Guffa
    Guffa about 15 years
    I tried it out with both PNG-8 and PNG-24 images, and it does preserve the transparency. Could you post the image that you are trying to resize?
  • Admin
    Admin about 15 years
    Well if I look at test.png it does preserve the transparency. But If I store the byte[] in database and re-access it, the try to load that image on my web page then the background is displayed as grey. But this wasnt the case when I was loading the image directly into the database without reszing.
  • Admin
    Admin about 15 years
    I tried to load test.png without resizing into the database and displaying test.png, I found that the transparency was lost. Although when I open up test.png in Windows Picture viewer it seems to have transparency.
  • Admin
    Admin about 15 years
    when I open test.png in paintbrush the image shows up with black background and not as transparent. Therefore, I am pretty certain that resizing is destroying the transparency of the image.
  • Guffa
    Guffa about 15 years
    What browser are you using? IE6 does not support transparency for PNG-24 images. Paint doesn't support transparency at all.
  • Maksym Kozlenko
    Maksym Kozlenko over 12 years
    Yes, it works for resizing PNG files with transparency. Thanks!
  • KChaloux
    KChaloux over 11 years
    +1 - Ran into this problem today while trying to resize System icons to 16x16. Worked very nicely, even 3 years after it was answered =D
  • Riccardo Bassilichi
    Riccardo Bassilichi over 10 years
    Yes!!! It Works! You Save Me! It is important to Use .MakeTransparent() on every step of image resize or crop. After you create a new Image(). Thank You!
  • Christian Findlay
    Christian Findlay over 6 years
    What object has this MakeTransparent call?
  • Ahmad
    Ahmad over 4 years
    I am creating stream and Upload on blob how to call .MakeTransparent() init