【问题标题】:C#: Seeking PNG Compression algorithm/library [closed]C#:寻求PNG压缩算法/库[关闭]
【发布时间】:2011-05-24 00:55:23
【问题描述】:

我需要压缩或至少降低用户上传到我网站的某些 png 图像的质量。我已经调整了它的大小,但这对图像大小没有太大影响。

寻求 .net 4.0 或更低版本的 png/图像压缩或质量损失算法或库。


这是我目前保存/转换图像的方式:

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

【问题讨论】:

  • "for .net 4.0 or under":抱歉,我只有一个 .NET 5.0 ;)
  • 出于好奇,您对 .NET 5 的回答是什么?
  • 我打赌会有一些仅基于 4.5 :)

标签: c# .net algorithm png


【解决方案1】:

不幸的是,.NET(以及构建 .NET 图形库的 GDI+)不支持 PNG 的任何编码参数。事实上,如果您使用 PNG 编码器 Clsid 对图像调用 GetEncoderParameterList,您将收到“未实现”异常。

更不幸的是,ImageFormat 和 ImageCodecInfo 都是密封类,您不能只将新编解码器添加到 .NET 可以本机访问的内容中。微软在这个问题上丢了球。

这意味着您的替代方案按自虐的降序排列: 1) 在实现 RFC 2083 的 .NET 中自行实现保存功能, 2) 实现基于将 libpng 移植到 .NET 的保存功能, 3) 直接调用从 libpng 构建的非托管代码

libpng 有很好的文档,并且在可用性和许可许可方面都是免费的。

【讨论】:

  • +1 用于调用非托管代码...通常只使用基于控制台的处理器。
【解决方案2】:

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

  • 减少像素数(通过缩小图像);这里有明显的分辨率损失
  • 使用不同的预压缩过滤器/DEFLATE 压缩器参数(OptiPNG 是我最喜欢的自动选择最佳过滤器/压缩器设置组合的工具)
  • 将颜色深度从真彩色降低到 256 色(或更少)将为您节省大量字节,但通常会带来巨大的视觉成本(尤其是摄影图像)

.NET 似乎没有内置方法来更改 PNG 的预压缩过滤器或压缩器参数,因此您必须使用外部库。 OptiPNG 或任何other PNG 优化工具不是本机 .NET 库,因此您必须处理 P/Invoking 库或运行单独的进程来处理每个图像。但是,您通常会看到大约 5% 或更少的节省(尽管我看到的节省高达 40%),因为这最终是一个无损过程。

我建议不要在您描述的自动化场景中减少颜色深度,因为结果看起来真的很糟糕(想想旧的抖动 GIF)。 (但是,如果您要进行手动优化,请查看 Windows 上的 Color Quantizer 和 Mac 上的 ImageAlpha。)

实际上,以牺牲质量为代价来减小文件大小的最佳方法是只转换为 JPEG,它不需要外部依赖,并且被设计为一种有损压缩算法:

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

【讨论】:

  • 这并不完全正确。 PNG 实现了压缩过滤器的概念,用于在不损失质量的情况下减小图像大小。它不能保证任何事情,但在某些情况下,改进可能非常显着。你可以在这里阅读:libpng.org/pub/png/pngintro.html
  • 但我同意 josh3736,最简单、最可靠的方法是使用 JPEG。
  • @detunized:是的,但压缩过滤器可能无法实现有损压缩,而这正是@Shawn 真正要求的。无论如何,他的用户上传的任何 PNG 都必然已经应用了压缩过滤器,因此无法进一步减小文件大小。
  • 如果未应用过滤器,则可以重新编码 PNG。有一些工具可以做到这一点。仍然必须同意结果不能保证。虽然准确地说,OP 正在寻找compression or quality loss algorithm。我建议前者。
  • 当您解码然后调整大小/保存时,任何优化过滤器都会在新文件输出中丢失。您仍然可以在输出文件上运行 optipng/pngcrush,并且通常会收获很多……尤其是当颜色托盘真的小于 256 色时。 Sixteencolors.net 在 .Net 代码上运行时会将渲染图像优化为 16 色托盘,从而大大减小了图像尺寸。
【解决方案3】:

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

在大多数情况下,如果上传的是照片并且原始格式是 JPEG,那么使用 JPEG 输出会更好地为您服务。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-27
    • 1970-01-01
    • 2012-08-22
    • 2013-12-28
    • 1970-01-01
    相关资源
    最近更新 更多