C#如何压缩.png而没有透明背景丢失?

时间:2017-08-16 00:42:24

标签: c# image-compression

我使用以下代码将图像文件压缩为jpg:

// _rawBitmap = a Bitmap object

ImageCodecInfo encoder = GetEncoder(ImageFormat.Jpeg);
System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
myEncoderParameters.Param[0] = myEncoderParameter;

ImageConverter imageConverter = new ImageConverter();
byte[] b = (byte[])imageConverter.ConvertTo(_rawBitmap, typeof(byte[]));

using (MemoryStream ms = new MemoryStream())
{
    ms.Write(b, 0, b.Length);
    ms.Seek(0, SeekOrigin.Begin);
    rawBitmap.Save(ms, encoder, myEncoderParameters);
    bmp = ToBitmap(ms.ToArray());
    return (Bitmap)bmp.Clone();
}

但是当我尝试以相同的方式压缩png文件但只改变时:

ImageCodecInfo encoder = GetEncoder(ImageFormat.Jpeg);

ImageCodecInfo encoder = GetEncoder(ImageFormat.Png);

我的png文件丢失了透明数据。

那么如何正确压缩PNG文件?

2 个答案:

答案 0 :(得分:1)

这里有几个问题。 首先,您不需要为PNG设置质量EncoderParams

其次,您不需要ImageConverter

第三,你正在编写ImageConverter产生的任何内容流,倒带,然后将编码的PNG写在它的顶部 - 很可能你有一个PNG文件,其末尾有一堆垃圾结果。

简化方法应该是:

using (MemoryStream ms = new MemoryStream())
{
    rawBitmap.Save(ms, ImageFormat.Png);    
}

如果要重新加载位图,请从流中打开它,但不要关闭该流(当您返回的位图被丢弃时,将处理该流):

var ms = new MemoryStream();    
rawBitmap.Save(ms, ImageFormat.Png);    
ms.Seek(0, SeekOrigin.Begin);
return Bitmap.FromStream(ms);

答案 1 :(得分:0)

您可以使用nQuant(https://www.nuget.org/packages/nQuant/

使用它,您可以将32位PNG转换为高质量的8位PNG

    private static int alphaTransparency = 10;
private static int alphaFader = 70;
var quantizer = new WuQuantizer();
using(var bitmap = new Bitmap(sourcePath))
{

    using(var quantized = quantizer.QuantizeImage(bitmap, alphaTransparency, alphaFader))
    {
        quantized.Save(targetPath, ImageFormat.Png);
    }

}