Why does resizing a png image lose transparency?

2019-01-15 14:10发布

问题:

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;
  }
}

回答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.)



回答2:

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



回答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);
}