【问题标题】:ImageMagick multiple operations in single invocationImageMagick 一次调用中的多个操作
【发布时间】:2015-06-26 11:38:27
【问题描述】:

我试图让 ImageMagick 在一次调用中执行多个操作(在本例中为裁剪),但这似乎是不可能的。例如,我可以使用两个单独的命令进行裁剪、旋转,然后再进行裁剪:

$ convert test.jpg -crop 223x187+588+757 -rotate 330 crop2.jpg 
$ convert crop2.jpg -crop 200x100+43+87 crop3.jpg

但是如果我尝试将它们组合成一个命令,我会得到一个错误:

$ convert test.jpg -crop 223x187+588+757 -rotate 330 -crop 200x100+43+87 裁剪3.jpg 转换:几何不包含图像“test.jpg”@warning/transform.c/CropImage/666。

显然我可以只创建一个管道,但如果可能的话,我想避免多个进程的额外开销。有没有办法做到这一点?

更新: 此外,管道似乎有问题:我不想要额外的压缩/解压缩阶段,所以我尝试将它作为 RGB 管道,但我似乎无法正确设置参数:

convert test.jpg -crop 223x187+588+757 -rotate 330 rgb:- | convert -size 287x273 -depth 8 rgb:- -crop 200x100+43+87 crop3.jpg
convert: unexpected end-of-file `-': No such file or directory @ error/rgb.c/ReadRGBImage/231.

好的,所以上面的错误是因为我计算的图像大小与 ImageMagick 的计算结果相差两个像素。因此,显然必须尝试使图像大小计算与 IM 完全相同,这是由于需要对两个命令进行管道化而引入的一个额外问题。

【问题讨论】:

    标签: imagemagick imagemagick-convert


    【解决方案1】:

    这是一个更通用的问题方法。

    ImageMagick 提供了一些巧妙的技巧,可以帮助优化处理速度......

    1. ...您要处理大图像和
    2. ...当您想从同一个原件创建不同的输出时。

    甚至可以组合不同的方法:

    1. 利用 ImageMagick 的特殊mpr:{label} 格式和语法。 这告诉 ImageMagick 将输入图像临时保存到一个命名的 magick 程序寄存器 标签中。 (我也看到它被解释为 magick persistent (memory) registermemory program register。) 然后,命令管道可以稍后(在处理时)从那里读取图像数据,这比从硬盘读取的速度要快得多。 该命令可以根据需要多次读取它。
    2. 利用 ImageMagick 的特殊 mpc:{name} 格式和语法。 这类似于mpr:。 它的全名是magick pixel cache。 我也将其视为magick 持久(磁盘)缓存。 MPC 是 ImageMagick 的原生 in-memory 未压缩文件格式,但转储到磁盘。 写入磁盘后,它可以比 JPEG、TIFF 或 PNG 更快地重新读入内存,因为不需要转换。
    3. 构建一个巧妙的命令序列。 利用“横向”处理,在适当的情况下使用转义括号中的\( ... \) 语法。

    MPC

    convert 命令读取输入图像(JPEG、TIFF、GIF、PNG...任何当前格式)时,它首先将此格式处理为 MPC。

    此处理后的结果以未压缩的光栅格式保存在 RAM 中。 从那里发生进一步的转换和图像处理。 当您想将 MPC作为 MPC 写入磁盘时,您可以使用 +write mpc:myfilename。 这基本上只是直接将内存转储到磁盘。

    ImageMagick 然后写入两个,而不是一个,(并且比平常大)二进制文件:myfilename.mpcmyfilename.cache.mpc 文件保存图像的元数据,.cache 保存实际像素缓存数据。

    从此磁盘文件中读取是根据需要从磁盘到内存的快速内存映射(类似于内存页面交换)。 但由于最初的+write 操作确实存储了原生未压缩的内部、IM 原生光栅格式,因此现在不需要图像解码。

    所以这可以更快地使用(特别是对于大图像),如果你不能避免写出你需要再次读入的临时文件。 但是,请注意您的磁盘空间。 记住清理,一旦您不再需要磁盘上的 MPC 文件。 IM 不会自动为您跟踪您的+write 命令。

    (更多技术细节:MPC 作为磁盘文件格式不可移植。 它也不适合作为长期存档格式。 它唯一的适用性是作为高性能图像处理的中间格式。 它需要 两个 文件来支持 一个 图像。 它不能保证在 ImageMagick 版本之间是“稳定的”。 它可能无法在与您创建它的机器不同的机器上运行。)

    如果您仍想将此格式保存到磁盘,请记住:

    • 图像属性被写入扩展名为.mpc的文件中。
    • 图像像素被写入扩展名为.cache的文件中。

    MPC 的主要优势在于...

    1. ...处理非常大的图像,或者当
    2. ...在“操作管道”中对同一图像应用多个操作。

    MPC 专为符合条件“多次读取,一次写入”的工作流模式而设计。

    MPR

    MPR 格式(内存持久寄存器)的作用类似于 MPC。 它通过命名的内存寄存器使图像可用。 您可以使用任何您想要的名称(偶数)。 您的流程管道还可以从该寄存器再次读取图像 - 如果需要,甚至可以多次读取。 图像mpr:label 保留在寄存器中,直到当前命令管道退出。 (这与写入磁盘的mpc:filename 不同。这会持续完成当前管道;它甚至可以在系统重新启动后继续存在。)

    聪明的命令管道

    (我在这里使用的“管道”一词不要与 shell 中的管道混淆,其中启动并链接了多个命令和进程。 这里我只讨论convert 的单个调用,它将多个图像操作和操作链接到一个进程中。)

    因此可以在一个过程中完成所有调整大小、裁剪、追加、缩略图、颜色处理、模糊等操作,写出您需要的不同中间输出。

    实际例子...

    ...嗯,我不太确定它是否soooo 实用。我没有测试过,我只是用我的幻想构建了一个例子,展示了不同概念的使用原理。

    注意:+write someimage-write someimage +delete 相同。

    convert \
        very-very-large.jpg \
       -write mpr:XY \
       +delete \
       -respect-parentheses \
         \( mpr:XY -crop '3000x2001+0+491' -resize '170x116!>'   +write pic1.png   \) \
         \( mpr:XY -crop '2981x2883+8+0'   -resize '75x75!>'     +write pic2.png   \) \
         \( mpr:XY -crop '1100x1983+0+0'   -resize '160x160!>'   +write pic3.png   \) \
         \( mpr:XY -crop '2000x2883+0+0'   -resize '1024x960!>'  +write pic4.png   \) \
         \( mpr:XY -crop '1000x2883+0+0'   -resize '190x188!>'   +write mpr:pic5   \) \
         \( mpr:pic5                                             +write pic5.png   \) \
         \( mpr:XY -crop '3000x2000+0+0'   -resize '2048x2047!>' +write pic6.png   \) \
         \( mpr:XY -crop '3000x2883+0+0'   -resize '595x421!>'   +write pic7.png   \) \
         \( mpr:XY -crop '3000x2883+0+0'   -resize '3000x2883!>' +write mpr:AB     \) \
         \( mpr:AB                                               +write pic8.tiff  \) \
         \( mpr:AB -blur 0x8                                     +write blur1.gif  \) \
         \( mpr:pic5 mpr:AB +append mpr:pic5 -append             +write append.jpg \) \
         \( mpr:pic5 -rotate -130 mpr:AB -gravity center                              \
                     -compose difference -composite +write final.png               \) \
    null:
    

    第一次操作-write mpr:XY后,栈中有两张图片:

    1. 输入文件very-very-large.png,和
    2. 它的一个副本,可以使用标签XY从内存中读取。

    我们不再需要这两个中的第一个。 因此我们使用+delete 将其从堆栈中删除。

    因此,此命令使用一个命令管道,该管道执行多个命令和操作,一次创建 11 个不同的输出图像: pic{1,2,3,4,5,6,7}.pngblur1.gifpic8.tiffappend.jpgfinal.png

    【讨论】:

    • 我试过你的方法,但它会抛出一个错误,比如“无法打开 mpr:XY,没有这样的文件或目录”
    • 啊,最后我发现我错过了null:,这就是导致它失败的原因。
    【解决方案2】:

    快速回答:在您的第一个命令中插入+repage

        convert test.jpg             \
               -crop 223x187+588+757 \
               -rotate 330           \
               +repage               \
               -crop 200x100+43+87   \
                crop3.jpg
    

    长而全面的回答:稍后会跟进。我必须先完成另一个任务。长答案将为您提供一种更通用的方法,即如何在一个命令中裁剪多个部分,同时保持性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多