23

我正在构建一个 PHP 系统,用户可以创建一个视觉复杂的图像,最终要求为50kB 或更少

用户可以选择将文本打印到 37 个模板图像之一上,因此结果是单个平面图像。

文本可以是任何颜色和多种字体中的一种。这意味着最终图像在视觉上可能非常复杂且不可预测(图像尺寸除外)。

然后我要求最终图像文件大小不大于 50kB(这是外部要求,无法更改)。

最后一个要求(同样是外部的)是图像格式必须是.jpeg、.png 或 .gif

我查看了GraphicsMagick文档,但找不到任何提到能够设置文件大小并自动计算压缩的地方。

我考虑过通过 compress->save->test 循环以编程方式执行此操作,但是我可以想象这将是处理器密集型的,因为我不一定能提前根据压缩计算文件大小。这就是为什么我要求查看问题是否已经在 GraphicsMagick 中解决。

编辑

要清楚为什么有外部要求:

用户将利用该系统创建平面图像,然后将其保存到他们的 PC 上。然后将此图像上传到Adroll以用于重新定位广告系列。

这是Adroll对图像的要求。我的系统将只提供 728x90、300x250 和 120x600 的图像尺寸。

编辑2010 年 11 月 27 日

由于 GraphicsMagick 似乎无法做到这一点,因此我愿意研究其他解决方案,例如直接与能够提供该功能的压缩库(libpng 等)接口。

作为最后的手段,我什至可以看看可以实现这一点的算法并自己实现一个。


打个比方,对于那些有这种倾向的人:

我追求的是 A* 的搜索:它有一个明确的起点/终点,并在最快的时间内找到最好的可能路线。

我希望避免的是广度/深度优先是搜索:确定的起点/终点,但一旦找到局部最小值就可能无法达到最佳解决方案,并且有可能在计算上完全崩溃。

4

9 回答 9

11

由于无法压缩到我知道的目标大小,我建议研究间接解决方案:

  1. 做一些快速统计(可能通过使用不同的 JPEG 压缩因子压缩大量图像)来找出给定质量级别的平均压缩大小及其标准偏差。
  2. 接受图像时,请尝试以合适的质量进行压缩。如果生成的文件太大,请降低质量并重试。或者,如果结果太小,您也可以提高质量。
  3. 当生成的图像“接近”您的目标尺寸但更小时停止。

详细说明步骤 2 中的数学:

如果您选择的起始质量使您的平均计算大小 + 3 * 标准偏差 < 您的目标大小,那么 99.7% 的压缩将在第一次尝试时生成一个适当的小文件(假设压缩大小的正态分布)。

您可以根据需要调整启动质量和增加或减少它的逻辑,在较少的服务器负载和接近最大大小的文件之间进行平衡(“更好地利用”您的限制)。

于 2010-11-27T00:59:03.410 回答
9

看看下面的包:

http://www.phpclasses.org/package/3810-PHP-Optimize-images-to-fit-in-a-given-file-size-limit.html

很酷 - 我会说作者应该喝啤酒;)

示例图像实际上是 61081 字节(第一个 jpeg 图像在图像中显示文件大小?):

替代文字

于 2010-12-02T14:31:07.240 回答
1

是否可以将 GraphicMagick 的“-limit disk 50mb”与“-list resource”结合使用,以便您可以在整个过程中及早检查(或实际上在整个过程中进行轮询)并进行调整以适应?

http://www.graphicsmagick.org/GraphicsMagick.html#details-limit

于 2010-11-26T15:53:19.310 回答
0

Purhaps您从错误的角度看待问题。通过选择使用 PNG 并最小化存储在图像中的元数据,您将最小化文件大小。这是因为 PNG 是位图结构。只要 GMagick 不将文本存储为元数据,它就不会影响文件大小。只有颜色深度(您也可以控制)会影响文件的大小。不过滤文件大小的非交错应该与模板大小基本相同。只要模板小于 50Kb,就可以了。

于 2010-12-02T21:53:11.577 回答
0

虽然循环直到达到目标文件大小的编程选项似乎是流行的答案,但有两种方法可以使用.jpeg 压缩来做到这一点:


Kuo, Chun-ming 有一个专利方法,所以我不确定使用它的商业可行性:

调整jpeg图像压缩比的方法及电子装置

这是基于这个公式:

log(NSF) = (log(SF1 / SF2) / log(FileSize1 / FileSize2)) * log(Target / FileSize1) + log(SF1)

在哪里

SF1 is a first compression parameter
SF2 is a second compression parameter
FileSize1 is the size of the image compressed with SF1
FileSize2 is the size of the image compressed with SF2
Target is the target file size
NSF is the target compression parameter.

不清楚 SF1、SF2 和 NSF 是否在 0-1 或 0-100 等范围内,以及 FileSize1、FileSize2 和 Target 是否在 Bytes、KiloBytes 等范围内。在这里尝试正确的组合以找到出正确的单位。


第二种方法来自 MIT 的 Ricky D. Nguyen:

JPEG 转码的速率控制和比特分配

他建议在压缩发生时改变用于压缩的数据。此选项可能无法实现,因为它需要修改实际的压缩代码本身。


从这两个示例中,当然可以保存具有特定目标文件大小的 .jpeg 文件。

于 2010-12-02T02:14:21.133 回答
0

首先尝试 24 位 .png。如果合适,它将是最好的质量,你就完成了。或者,您可以测试一些典型的图像,如果它们都不适合,您可以完全排除这种格式。

对于 .gif 和 .jpg,您需要搜索最合适的;这两种算法都不能有足够的把握进行预测,而且这两种算法都不适用于恒定比特率编码。您可以使用二进制搜索来找到最合适的。您可以从预先确定的列表中选择压缩系数,以限制您需要进行的测试压缩次数;例如,如果您的 .jpg 压缩因子列表是 4、6、8、12、18、27、44、66,则您最多需要进行 4 次测试压缩。

.gif 和调色板 .png 非常相似,您应该只选择一个而忘记另一个。

根据压缩结果,很难在 .gif/.png 和 .jpg 之间进行选择;每个过程引入的工件是完全不同的。同样,您最好将一些测试图像压缩到您的目标大小,并根据眼球测试消除一种或另一种格式。

于 2010-12-02T03:49:57.540 回答
0

只有三种方法可以减小任何给定图像的最终尺寸:

  1. 降低分辨率
  2. 减少颜色深度
  3. 降低图像复杂度

前两个在你的控制之下。如果上传的图片文件大小超过限制,您可以尝试将其缩小到下一个较小的可用大小,看看它是否适合。鉴于您只有 3 个目标分辨率,这不会太贵。但是,如果您需要“大”尺寸可用,那么您就剩下选项 3。

降低图像复杂性是一头讨厌的野兽。您可以尝试减少像素间“噪声”以产生更大的相同颜色区域,这将在 GIF/PNG 图像中很好地压缩。一个简单的模糊滤镜可以做到这一点,但它也可能破坏图像中任何精美印刷品/文本的易读性。对于 JPG 目标,您可以尝试降低压缩质量,但同样,如果您将质量降低得太低,这可能会破坏图像。如果简单的服务器端转换无法处理此问题,则图像必须由最初创建它的艺术家重做。

我能看到的唯一实用的方法是你提到的 compress-save-test 循环。鉴于最终的图像相对较小,这不会对服务器造成太大的负担。保存 gif/png 是一种轻量级的操作。JPG 压缩需要更多的 CPU 能力,但同样,对于小图像,现代服务器在一两秒内处理 10 或 20 个测试图像应该没有任何问题。

于 2010-11-26T03:46:51.917 回答
0

所以,如果我理解正确 - 您正在构建一个系统,允许用户在您提供的模板图像之一上写一些文本。如果这是正确的,你为什么要保存图像?您可以通过保存用户操作本身轻松移除 50Kb 大小限制。您可能可以执行以下操作 - 保存文本(连同其属性和位置)和它所在的模板。

于 2010-11-24T19:46:29.167 回答
0

我不知道有一种方法可以自动确定图像的最终文件大小——这是生成图像的库的任务。除非您自己实施压缩,否则您无法预先计算结果大小。

您可以做的是收集统计数据(图像高度和宽度以及文件大小与不同的压缩选项),并根据该数据对新图像进行估计。

例子:

  • 50k jpg,100x200 压缩 30k
  • 100k jpg,100x200 压缩为 60k

-> 当你得到一个 59k 的 100x202px 的图像时,压缩后的大小将大致估计为 35k。

于 2010-11-23T10:30:57.443 回答