如何避免优化已经使用PHP优化的图像


How to avoid Optimizing images that are already optimized with PHP?

我目前正在开发一个PHP应用程序,该应用程序从命令行运行以优化Images文件夹。

PHP应用程序更像是其他图像优化器的包装器,它只需迭代目录并获取所有图像,然后通过适当的程序运行图像以获得最佳结果。

以下是我将要使用的程序,以及每个程序的用途。。。

imagemagick确定文件类型并将非动画gif转换为png
gifsicle优化动画Gif图像
jpegtran优化jpg图像
pngcrush优化png图像
pngquantpng图像优化为png8格式
pngoutpng图像优化为png8格式

我的问题是:对于1-10个图像,一切都运行得很顺利,速度也相当快。然而,一旦我在一个有10个或更多图像的较大文件夹上运行,它就会变得非常慢。我真的没有看到一个好的解决方案,但有一件事会有所帮助,那就是避免重新处理已经优化的图像。因此,如果我有一个包含100个图像的文件夹,并且我优化了该文件夹,然后添加了5个新图像,请重新运行优化器。然后它必须优化105个图像,我的目标是让它只优化5个较新的图像,因为之前的100个图像已经被优化了。当将新图像添加到图像文件夹时,仅此一项就可以大大提高性能。

我意识到,简单的解决方案是在处理完图像后,简单地将其复制或移动到一个新的文件夹中,我使用该简单解决方案的问题是,这些图像用于网络和网站,因此图像通常被硬链接到网站源代码中,更改图像的路径会使其复杂化,有时可能会破坏它。

我的一些想法是:在图像文件夹中写入某种文本文件数据库,该数据库将列出所有已处理的图像,因此当运行应用程序时,它将只在不在该文件中的图像上运行。另一个想法是更改文件名,使其名称中有某种标识,以表明它已经优化,第三个想法是在优化后将每个优化的文件移动到最终目标文件夹。想法2和3并不好,因为它们会破坏网站源代码中的所有图像路径链接。

所以,如果你能想出一个像样/好的解决方案来解决这个问题,请分享?

元数据
优化后,您可以在每个图像的元信息中放置一个标志。首先检查该标志,只有在不存在的情况下才继续。您可以使用exif_read_data()读取数据。这样写可能是

以上内容适用于JPG。PNG的Metdata也是可能的——看看这个问题,和这个

我不确定GIF,但你肯定可以将它们转换为PNG,然后添加元数据。。。尽管我很确定他们有自己的元信息,因为元数据提取工具允许GIF。

数据库支持
另一种解决方案是将有关图像的信息存储在MySQL数据库中。这样,当你调整你的优化时,你可以跟踪什么时候以及在哪个图像上进行了哪些优化。您可以根据自己选择的任何参数来选择要优化的图像。你可以为此建立一个管理面板。这种方法可以很容易地进行实验。

您也可以将上述两种方法结合起来。

最大文件大小
由于这是为了节省空间,您可以让程序只处理大于特定文件大小的图像。理想情况下,在运行压缩器一次之后,所有图像都将低于该文件大小,并且在那之后,只有太大的新添加的图像才会被触摸。我不知道这在实现方面有多实用,因为它需要压缩器获得任何低于任意文件大小的图像。您可以根据图像大小设置最大文件大小。。。。。

最简单的方法很可能是查看每个图像的最后一次更改时间。如果在上次运行脚本后更改了图像,则必须在此特定图像上运行该图像。脚本运行时的时间戳可以很容易地保存在一个短文本文件中。

我想到的一个想法是将简单的解决方案与更复杂的解决方案混合在一起。优化图像时,请将其移动到一个单独的文件夹中。当访问原始图像文件夹时,让.htaccess文件捕获这些链接,并将它们路由到一个区域,该区域可以查看优化文件夹部分中是否存在相同的图像,如果不存在,请优化、移动,然后继续。

我知道我说过simple解决方案,这是一个非常复杂的解决方案,但好的部分是该解决方案将为您的问题提供一种可扩展的方法。


编辑:还有一件事

我喜欢MySQL数据库的想法,因为如果需要的话,你可以添加一个级别的安全性(不是所有的图像都可以被每个人查看)。但这也使你的链接问题(硬编码的)不是一个大问题。由于所有链接都是一个文件,其中从数据库中检索图像,唯一发生变化的是生成的get变量。通过这种方式,您的项目变得更具可扩展性,更容易进行设计更改。

很抱歉,这太晚了,但由于有一种方法可以解决这个问题,而无需创建任何文件、存储任何类型的数据或跟踪任何事情。我想我应该分享我如何解决这类问题的解决方案。

目标
设置一个幂等解决方案,有效地优化图像,而不需要跟踪其当前状态的依赖关系。

原因
这允许一个真正可移植的解决方案,它可以在新的环境中工作,在某种程度上丢失跟踪器的环境中,或者在对您可以实际保存的文件敏感的环境中。

诊断
虽然元数据可能是你想检查这些信息的第一个来源,但在某些情况下,它确实不可用,而且元数据本身的性质是任意的,就像评论一样,它们可以来来去去,不会以任何方式影响图像。我们想要一些更具体的东西,一些对手头资产有明确描述的东西。理想情况下,你会想"识别"一个是否经过了优化,这样做的方法是查看图像,看看它是否基于其特征。

战略
当您优化图像时,您将提供各种不同的选项,以达到优化的最终状态。这些正是你将要检查的特征,以得出它是否真的被优化的结论。

示例
假设我们的脚本中有一个名为optimize(path = '')的函数,并且假设我们的优化部分执行以下操作:

$ convert /path/to/image.jpg -bit-depth=8 -quality=87% -colors=255 -colorspace sRGB ...

请注意,这些选项是您选择指定的选项,它们将应用于图像,并且是稍后可以查看的属性。。。

$ identify -verbose /path/to/image.jpg
Image: /path/to/image.jpg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Mime type: image/jpeg
  Geometry: 1250x703+0+0
  Colorspace: sRGB <<<<<<
  Depth: 8-bit <<<<<<
  Channel depth:
    Red: 8-bit
    Green: 8-bit
    Blue: 8-bit
  Channel statistics:
    Pixels: 878750
    Red:
        ...
    Green:
        ...
    Blue:
      ...
  Image statistics:
    Overall:
      ...
  Rendering intent: Perceptual
  Gamma: 0.454545
  Transparent color: none
  Interlace: JPEG
  Compose: Over
  Page geometry: 1250x703+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: JPEG
  Quality: 87 <<<<<<
  Properties:
    ...
  Artifacts:
    ...
  Number pixels: 878750

正如你在这里看到的,输出实际上包含了我想知道的一切,以确定我是否应该优化这个图像,而且就性能而言,它不需要任何成本。

结论
当您在文件夹中的文件列表中进行迭代时,您可以随心所欲地进行多次迭代,而无需担心过度优化图像或跟踪任何内容。您只需过滤掉所有不想优化(eg .bmp, .jpg, .png)的扩展,然后检查它们的统计数据,看看它们是否具有您的函数首先将应用于图像的属性。如果它具有相同的值,则跳过;如果没有,则优化。

高级
如果你想获得极高的效率,你应该检查你计划优化的图像的每个属性,在优化执行中,你只会应用尚未应用于命令的选项。

注意
这项技术显然是为了展示一个如何准确确定图像是否需要优化的例子。我上面列出的实际选项并不是可以选择的元素的完整范围。有多种可用选项可供选择,您可以根据需要申请和检查。