2010-12-11 172 views
15

我需要压缩或至少降低用户上传到我的网站的一些png图像的质量。我已经调整过它的大小,但对于图像大小并没有太大的作用。C#:寻求PNG压缩算法/库

为.net 4.0或以下版本寻找一个PNG /图像压缩或质量损失算法或库。


这是怎么了我目前保存/转换我的图片:

Image mainImg = ImageHelper.ResizeImage(bmp, 600, 500, false); 
mainImg.Save(filePath, System.Drawing.Imaging.ImageFormat.Png); 
+2

“for .net 4.0 or under”:对不起,我只有一个用于.NET 5.0;) – 2010-12-12 00:13:49

+0

出于好奇你对.NET 5有什么回答? – Dylan 2012-08-07 19:25:28

+0

我敢打赌,会有一些仅基于4.5 :) – 2012-08-07 21:16:24

回答

22

不幸的是,.NET(和GDI +,其.NET图形库是建立在)不支持任何PNG编码参数。实际上,如果您使用PNG编码器Clsid在图像上调用GetEncoderParameterList,则会出现“未实现”异常。

更不幸的是,ImageFormat和ImageCodecInfo都是密封类,你不能只是添加新的编解码器,以.NET本来可以访问。微软在这一球上放下了球。

这意味着你的替代品,在降低受虐狂的顺序: 1)实现你自己的.NET实现了RFC 2083保存功能, 2)实现基于关闭的libpng移植到一个保存功能。NET, 3)调用直接从libpng构建的非托管代码

libpng拥有出色的文档并且在可用性和许可允许性方面都是免费的。

+0

感谢您的洞察力。 – 2010-12-23 17:30:31

+0

+1用于调用非托管代码...通常只需使用基于控制台的处理器。 – Tracker1 2012-02-09 22:06:45

+0

FreeImage怎么样? – jjxtra 2012-10-09 19:05:10

7

PNG一般是无损压缩方案,这意味着图像质量是永远不会减少,除非你减少像素数(大小)或颜色深度。有三种方法可以减小PNG图像的文件大小:

  • 减少像素数(通过缩小图像);这里有
  • 分辨率的明显丧失使用不同的压缩前的过滤器/ DEFLATE压缩机参数(OptiPNG是我最喜欢的工具来自动选择过滤器的最佳组合/压缩设置)
  • 减少从真彩256色深(或更少)的颜色会给你大量的字节的储蓄,但通常是在巨大的视觉成本(尤其是照片图像)

好像.NET不具有一个内置的方式来改变预压缩过滤器或压缩机参数的PNG,所以你必须使用外部库。 OptiPNG或任何other PNG优化工具不是本机.NET库,因此您必须处理P /调用库或运行单独的进程来处理每个映像。但是,您通常会将储蓄减少到5%或更少(尽管我已看到多达40%),因为这最终是一个无损的过程。

我建议不要在您描述的自动化场景中减少颜色深度,因为结果可能看起来真的很糟糕(想想老掉牙的GIF)。 (但是,如果您正在手动优化,请在Windows上查看Color Quantizer,在Mac上查看ImageAlpha)。没有外部的依赖,并且被设计成是一种有损压缩算法:

mainImg.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg); // make sure you change `filePath` to end with jpg instead of png. 
+0

这不完全正确。 PNG实现了压缩过滤器的概念,用于减少图像大小而不会损失质量。它并不保证任何内容,但在某些情况下,这种改进可能非常重要。你可以在这里阅读:http://www.libpng.org/pub/png/pngintro.html – detunized 2010-12-11 19:26:27

+0

但我同意josh3736,最简单也是最可靠的方法是使用JPEG。 – detunized 2010-12-11 19:28:36

+0

@detunized:是的,但压缩过滤器可能不会实现有损压缩,这是@Shawn真正要求的。无论如何,由他的用户上传的任何PNG必然已经应用了压缩过滤器,所以不可能进一步减小文件大小。 – josh3736 2010-12-11 19:31:27

0

不幸的是.Net的png图像处理器不会对输出做任何优化启发式处理。最好的办法是在服务器上安装一个optipng/pngcrush二进制文件,将调整后的输出渲染为一个临时文件,然后通过System.Diagnostics.Process对其使用pngcrush。

大部分情况下,如果上传的是照片,原始格式为JPEG,那么使用JPEG输出可以更好地提供服务。