如何保存特定文件大小的图像?

发布于 2024-10-04 13:56:01 字数 1218 浏览 17 评论 0 原文

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

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

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

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

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

我已经浏览了 GraphicsMagick 文档,但找不到任何提到能够设置文件大小并具有 自动计算压缩

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

编辑

要明确为什么存在外部要求:

用户将利用该系统创建平面图像,然后将其保存到 PC 上。然后将该图片上传到 Adroll 以用于重定向营销活动。

以下是 Adroll 对图片的要求。我的系统仅提供 728x90、300x250 和 120x600 图像尺寸。

编辑 2010年11月27日

由于这对于GraphicsMagick来说似乎不可能,我愿意研究其他解决方案,例如直接与压缩库(libpng等)连接,它可能能够提供功能。

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


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

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

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

I am building a PHP system whereby users can create a visually complex image that has the final requirement of being 50kB or less.

The user can select to have text printed onto one of 37 template images, so the result is a single flat image.

The text can be any colour and one of a number of fonts. This means the final image can be quite visually complex and unpredictable (with the exception of image dimensions).

I then have the requirement of having the final image file size no greater than 50kB (this is an external requirement and cannot be changed).

The last requirement (again, external) is the image format must be .jpeg, .png, or .gif.

I have looked through the GraphicsMagick documentation, but cannot find anywhere that mentions being able to set the filesize and have the compression automatically calculated.

I have considered doing this programatically via a compress->save->test loop, however I can imagine this would be quite processor intensive as I cannot necessarily calculate the filesize based on compression in advance. This is why I am asking to see if the problem has already been solved in GraphicsMagick.

Edit

To be clear as to why there are external requirements:

The user will utilize this system to create a flat image, which they will then save onto their PC. This image is then to be uploaded to Adroll for use in a Retargeting campaign.

Here are Adroll's requirements on the image. My system will only provide the 728x90, 300x250, and 120x600 image sizes.

Edit 27th Nov, 2010

As this does not seem to be possible with GraphicsMagick, I am willing to look into other solutions, such as directly interfacing with compression libraries (libpng, etc) which may be able to provide the functionality.

As a last resort, it my even be feasible to look at algorithms which can accomplish this and implement one myself.


As an analogy, for those who are that way inclined:

I am after what A* is to search: It has a definite starting/ending point, and finds the best possible route in the fastest time.

What I was hoping to avoid was what Breadth/Depth First is to Search: definite starting/ending points, but may not hit on the optimal solution once finding a local minimum, and has the potential to completely blow out computationally.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

浪漫之都 2024-10-11 13:56:01

由于无法压缩到我所知道的目标大小,我建议寻找一种间接解决方案:

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

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

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

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

Since there is no way to compress to a target size that I know of, I suggest looking into an indirect solution:

  1. Do some quick stats (possibly by compressing lots of images with different JPEG compression factors) to find out what the mean compressed size and its standard deviation is for a given quality level.
  2. When accepting an image, try to compress with a suitable quality. If the resulting file is too big, decrease the quality and try again. Optionally, if it turns out too small you can increase the quality too.
  3. Stop when the resulting image is "close" to your target size, but smaller.

To elaborate a bit on the maths in step 2:

If you choose your starting quality such that your mean calculated size + 3 * standard deviation < your target size, then 99.7% of compressions will result in a suitably small file on the first try (assuming a normal distribution of compressed sizes).

You can tweak the starting quality and the logic that increases or decreases it as you wish, balancing between less server load and files closer to your maximum size ("making better use" of your restrictions).

妄断弥空 2024-10-11 13:56:01

看一下以下包:

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

漂亮酷 - 我想说作者应该喝一杯啤酒;)

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

替代文字

Have a look at the following package:

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

Pretty cool - I'd say the author deserves a beer ;)

Example image which is actually 61081 bytes (first ever jpeg image to show file size in image?):

alt text

隔纱相望 2024-10-11 13:56:01

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

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

Would it be possible to use GraphicMagick's "-limit disk 50mb" in coalition with "-list resource" so you can check this early on in (or indeed polled throughout) the process and make adjustments to suit?

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

何以畏孤独 2024-10-11 13:56:01

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

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

示例:

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

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

I do not know of a way to automatically determine the resulting file size of an image - that's task of the library generating the image. Unless you implement the compression yourself, you cannot pre-calculate the resulting size.

What you could do is collect statistical data (image height and width and file size vs. different compression options) and do your estimations based on that data for new images.

Example:

  • 50k jpg, 100x200 is compressed 30k
  • 100k jpg, 100x200 is compressed 60k

-> when you get a 100x202px image with 59k, the compressed size will be roughly estimated 35k.

我为君王 2024-10-11 13:56:01

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

So, if I understand this correctly - You are building a system which allows users to write some text on one of the template images that you provide. If that is correct, why are you saving the image at all? You can easily remove the 50Kb size limit by saving the user actions itself. You might be able to do something like - save the text (along with its properties and location) and the template it is on.

心奴独伤 2024-10-11 13:56:01

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

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

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

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

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

There's only three ways to reduce the final size of any given image:

  1. reduce resolution
  2. reduce color depth
  3. reduce image complexity

The first two are under your control. If the uploaded image comes out with a file size over the limit, you can try shrinking it to the next smaller available size and see if it fits into that. Given you've only got 3 target resolutions, this wouldn't be too expensive. But if you need the "large" size to be available, then you're left with option 3.

Reducing image complexity is a nasty beast. You can try to reduce inter-pixel "noise" to produce larger areas of the same color, which will compress in GIF/PNG images very nicely. A simple blur filter could accomplish this, but it might also destroy the legibility of any fine print/text within the image. For a JPG target, you can try to lower the compression quality, but again, this can trash images if you take the quality down too low. If simple server-side transforms can't handle this, the image would have to be redone by the artist who created it in the first place.

The only practical method I can see to automate this is the compress-save-test loop you mention. Given that the final images are relatively small, this won't be that large a burden on the server. Saving a gif/png is a lightweight operation. JPG compression takes more CPU power, but again, with small images, a modern server shouldn't have any trouble doing 10 or 20 test images within a second or two.

你怎么敢 2024-10-11 13:56:01

虽然循环直到达到目标文件大小的编程选项似乎是流行的答案,但有两种方法可以使用 .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 的单位为字节、千字节等。在此处尝试正确的组合以找出正确的单位。


The second method comes from Ricky D. Nguyen at MIT:

JPEG 转码的速率控制和位分配

他建议改变用于压缩的数据当它发生的时候。该选项实施起来可能不太可行,因为它需要修改实际的压缩代码本身。


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

Whilst the programmatic option of looping until the target filesize is reached seems to be the popular answer, there are two ways to do this with .jpeg compression:


There is a patented method by Kuo, Chun-ming, so I'm not sure of the commercial viability of utilizing it:

Method and electronic device for adjusting compression ratio of jpeg image

Which is based on this formula:

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

Where

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.

It's not clear if SF1, SF2, and NSF are in the range 0-1, or 0-100, etc, and if the FileSize1, FileSize2, and Target are in Bytes, KiloBytes, etc. Experiment with the correct combination here to find out the correct units.


The second method comes from Ricky D. Nguyen at MIT:

Rate control and bit allocations for JPEG transcoding

He suggests varying the data that is used for the compression while it's happening. This option may not be as feasible to implement as it requires modifications to the actual compression code itself.


From both of these examples, it is certainly possible to save out a .jpeg file with a certain target file size.

以酷 2024-10-11 13:56:01

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

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

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

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

Try 24-bit .png first. If that fits it will be the best quality, and you're done. Alternatively you could test some typical images and if none of them fit, you could eliminate the format from consideration altogether.

For the .gif and .jpg you'll need to search for the best fit; neither one can be predicted with enough certainty, and neither algorithm is suitable for constant bit rate encoding. You can use a binary search to find the best fit. You can choose compression factors from a predetermined list to limit the number of test compressions you need to do; for example if your list of .jpg compression factors is 4, 6, 8, 12, 18, 27, 44, 66, you would need to do 4 test compressions at most.

.gif and paletted .png are similar enough that you should just pick one and forget about the other.

It will be tough to choose between .gif/.png and .jpg based on the compression results; the artifacts introduced by each process are completely different. Again you might be best off by compressing a number of test images to your target size, and eliminating one format or the other based on eyeball testing.

裸钻 2024-10-11 13:56:01

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

Purhaps you are looking at the problem from the wrong angle. By selecting to use PNG and minimizing the metadata stored in the image you will minimize the file size. This is because PNG is a Bitmap structure. So long as GMagick does not store the text as metadata it will have no impact on the file size. Only the color depth (which you can also control) will impact the size of the file. Non-interlaces without filtering the file size should be essentially the same as the template size. So long as the templates are less than 50Kb you should be alright.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文