为什么改变 PNG 图片大小会丢失透明度?

10

我正在尝试按以下方式调整图像大小。 我将调整后的图像返回到 byte[] 中,以便可以将其存储在数据库中。 PNG 图像的透明度丢失了。 请帮忙改进。

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

25

你的代码并没有完全达到你想要的效果...

你使用 GetThumbnailImage 来调整图像大小,然后将缩略图绘制到自身中,这是相当无意义的。在第一步可能会失去透明度。

相反,应该创建一个空白位图,并通过将源图像绘制到空白位图上来调整源图像的大小。

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

(我删除了一些从未与结果有任何关系的参数,比如 imageLen 参数,它仅用于创建未使用的字节数组。)


这个解决方案也没有给我一个透明的图像。 - ssk
如果我查看test.png,它确实保留了透明度。但是,如果我将byte[]存储在数据库中并重新访问它,然后尝试在我的网页上加载该图像,则背景会显示为灰色。但是,当我直接将图像加载到数据库中而不进行调整大小时,情况并非如此。 - ssk
1
你使用的是哪个浏览器?IE6不支持PNG-24图像的透明度。Paint根本不支持透明度。 - Guffa
是的,它适用于具有透明度的PNG文件的调整大小。谢谢! - Maksym Kozlenko
今天在尝试将系统图标调整为16x16时遇到了这个问题。即使是在回答3年后,它仍然非常有效=D - KChaloux
显示剩余3条评论

9
尝试在位图对象上使用.MakeTransparent()调用。

是的!!! 它起作用了! 你救了我! 在每个图像调整大小或裁剪步骤中使用 .MakeTransparent() 是很重要的。在创建新的 Image() 后,谢谢! - Riccardo Bassilichi
这个MakeTransparent调用作用于哪个对象? - Christian Findlay
我正在创建流并将其上传到 Blob,如何调用 .MakeTransparent() 初始化函数? - Ahmad

2
也许你应该像我这样做一些事情,因为这个方法对我有效:
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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接