C# 如何在不丢失透明背景的情况下压缩.png?
C# how to compress .png without transparent background lost?
我使用以下代码将图像文件压缩为 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文件呢?
这里有几个问题。
首先,您不需要为 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);
您可以使用 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);
}
}
我使用以下代码将图像文件压缩为 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文件呢?
这里有几个问题。
首先,您不需要为 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);
您可以使用 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);
}
}