Php 如何加速复杂的图像处理?

Php 如何加速复杂的图像处理?,php,image,imagemagick,converter,imagemagick-convert,Php,Image,Imagemagick,Converter,Imagemagick Convert,每个用户都可以上传100张TIFF(黑白)图像 该过程需要: real 0m6.806s user 0m37.582s sys 0m6.642s real 1m4.225s user 0m51.577s sys 0m8.247s 将tif转换为jpg 将图像大小调整为xx 将图像裁剪到200px 添加文本水印 以下是我的PHP代码: move_uploaded_file($image_temp,$destination_folder.$image_name);

每个用户都可以上传100张TIFF(黑白)图像

该过程需要:

real  0m6.806s
user  0m37.582s
sys   0m6.642s
real   1m4.225s
user   0m51.577s
sys    0m8.247s
  • tif
    转换为
    jpg

  • 将图像大小调整为xx

  • 将图像裁剪到200px

  • 添加文本水印

  • 以下是我的PHP代码:

    move_uploaded_file($image_temp,$destination_folder.$image_name);
        
    $image_name_only = strtolower($image_info["filename"]);
    
    $name=$destination_folder.$image_name_only.".jpg";
    $thumb=$destination_folder."thumb_".$image_name_only.".jpg";
    $exec = '"C:\Program Files\ImageMagick-6.9.0-Q16\convert.exe" '.$destination_folder.$image_name. ' '.$name.' 2>&1';
    exec($exec, $exec_output, $exec_retval);                
    
    $exec = '"C:\Program Files\ImageMagick-6.9.0-Q16\convert.exe" '.$name. ' -resize 1024x  '.$name;
    exec($exec, $exec_output, $exec_retval);
    
    $exec = '"C:\Program Files\ImageMagick-6.9.0-Q16\convert.exe" '.$name. ' -thumbnail 200x200!  '.$thumb;
    exec($exec, $exec_output, $exec_retval);
    
    $exec = '"C:\Program Files\ImageMagick-6.9.0-Q16\convert.exe" '.$name. "  -background White  label:ش.پ12355  -append  ".$name;
    exec($exec, $exec_output, $exec_retval);
    
    这个代码有效。但每个图像的平均处理时间为1秒。 因此,对于100张图像,可能需要大约100秒

    如何加快整个过程(转换、调整大小、裁剪、水印)

    编辑


    我有一台服务器G8:Ram:32G,CPU:Intel Xeon E5-2650(4进程)

    版本:ImageMagick 6.9.0-3 Q16 x64

    特点:OpenMP

    资源限制:

    宽度:100MP;高度:100MP;面积:17.16GP;内存:7.9908GiB;Map:15.982GiB;磁盘:无限制;档案:1536;线程:8;节流阀:0;时间:无限期

    0两种方法 基本上,这一挑战可以通过两种不同的方式来解决,或者两者结合:

  • 尽可能巧妙地构造命令
  • 用加速收益换取质量损失
  • 接下来的几节将讨论这两种方法

    1.检查您有哪些ImageMagick:“Q8”、“Q16”、“Q32”或“Q64”? 首先,检查您的确切ImageMagick版本并运行:

    convert -version
    
    如果您的ImageMagick在其版本字符串中有
    Q16
    (甚至
    Q32
    Q64
    ,这是可能的,但有点过头了!): 这意味着,ImageMagick的所有内部函数都将所有图像视为具有16位(或32位或64位)通道深度。 这将为您提供更好的图像处理质量。 但与Q8相比,它也需要两倍的内存。 因此,这同时意味着性能下降

    因此:您可以通过切换到
    Q8
    -build来测试您将获得哪些性能优势。 (Q是ImageMagick构建支持的“量子深度”的符号。)

    您将支付可能的
    Q8
    ——性能提高但质量降低。 只需检查一下您在
    Q8
    上比
    Q16
    取得的速度,以及您遭受的质量损失。 然后决定你是否能忍受这些缺点

    在任何情况下,
    Q16
    将使用两倍于每个图像的RAM进行处理,而
    Q32
    将再次使用两倍于
    Q16
    的RAM。 这与输入文件中每像素的实际位数无关。 16位图像文件在保存时也会比8位文件占用更多的磁盘空间

    由于
    Q16
    Q32
    需要更多内存,您必须始终确保有足够的内存。 因为超过你的物理内存将是一个非常坏的消息。 如果一个较大的
    Q
    将进程交换到磁盘,性能将急剧下降。
    1074 x 768
    像素图像(
    width x height
    )将需要以下数量的虚拟内存,具体取决于量子深度:

    Quantum                   Virtual Memory
      Depth    (consumed by 1 image 1024x768)
    -------    ------------------------------  
          8         3.840 kiB  (=~  3,75 MiB)
         16         7.680 kiB  (=~  7,50 MiB)
         32        15.360 kiB  (=~ 14,00 MiB)
         
    
    还要记住,一些“优化”的处理管道(见下文)将需要在虚拟内存中保留图像的多个副本! 一旦可用RAM无法满足虚拟内存的需求,系统将开始交换并从磁盘中声明“内存”。 在这种情况下,所有聪明的命令管道优化当然都消失了,并开始转向相反的方向

    ImageMagick的生日在aera,当时CPU一次只能处理1位数据。 那是几十年前的事了。 从那时起,CPU体系结构发生了很大的变化。 16位操作的时间是8位操作的两倍,甚至更长。 然后16位处理器出现了。 16位操作成为标准。 CPU优化为16位: 突然间,某些8位操作可能需要比16位等效操作更长的时间

    如今,64位CPU很常见。 因此,
    Q8
    vs.
    Q16
    vs.
    Q32
    实数参数甚至可能无效。 谁知道呢? 我不知道有任何关于这方面的严肃基准测试。 如果有一天有人(对CPU和基准测试现实世界的程序有很深的了解)会运行这样一个项目,那将是很有趣的

    是的,我看到您正在Windows上使用Q16。 但为了完整起见,我还是想提一下。。。 将来会有其他用户阅读此问题和给出的答案

    很有可能,由于您的输入TIFF仅为黑白,因此
    Q8
    构建的图像质量输出足以满足您的工作流程。 (我只是不知道它是否会更快: 这在很大程度上还取决于运行此功能的硬件资源…)

    此外,如果您的安装支持
    HDRI
    (高动态分辨率图像),这也可能会导致一些速度损失。 谁知道呢? 因此,使用configure options
    ——disable hdri——quantum depth 8
    构建IM可能会也可能不会带来速度提升。 从来没有人认真地测试过这个。。。 关于这一点,我们只知道: 这些选项将降低图像质量。 然而,大多数人甚至不会注意到这一点,除非他们真的仔细观察,并进行直接的图像对比

    2.检查ImageMagick的功能 接下来,检查ImageMagick安装是否附带和/或支持:

    如果它是(像我的一样),你应该看到这样的东西:

    FEATURES      DPC HDRI OpenCL OpenMP Modules
    
    identify -list resource File Area Memory Map Disk Thread Time -------------------------------------------------------------------- 192 4.295GB 2GiB 4GiB unlimited 1 unlimited OpenCL(用于C计算L语言)利用ImageMagick的并行计算功能(如果在中编译)。 这将利用计算机的GPU和CPU进行图像处理操作

    OpenMP(用于Multi-p处理)执行类似的操作: 它允许ImageMagick在系统的所有核心上并行执行。 因此,如果您有一个四核系统,并调整图像的大小,调整大小发生在4核(甚至8,如果您有超线程)

    命令

    convert -version 
    
    印刷品
    convert logo: -resize 500% -bench 10 logo.png
    
      [....]
      Performance[4]: 10i 1.489ips 1.000e 6.420u 0:06.510
    
    identify -list resource File Area Memory Map Disk Thread Time -------------------------------------------------------------------- 384 8.590GB 4GiB 8GiB unlimited 4 unlimited identify -list resource File Area Memory Map Disk Thread Time -------------------------------------------------------------------- 192 4.295GB 2GiB 4GiB unlimited 1 unlimited
    convert -limit thread 2
    
    convert input.jpeg input.mpc
    
    convert input.mpc [...your long-long-long list of crops and operations...]
    
    convert image.tiff image.jpg
    
    convert image.jpg -resize 1024x image-1024.jpg
    
    convert image-1024.jpg -thumbnail 200x200 image-thumb.jpg
    
    convert -background white image-1024.jpg label:12345 -append image-labelled.jpg
    
    convert image.tiff                                                             \
     -respect-parentheses                                                          \
     +write mpr:XY                                                                 \
      \( mpr:XY                                       +write image-1024.jpg \)     \
      \( mpr:XY -thumbnail 200x200                    +write image-thumb.jpg \)    \
      \( mpr:XY -background white label:12345 -append +write image-labelled.jpg \) \
      null:
    
    time for i in $(seq -w 1 100); do
       convert image.tiff                                                          \
                                                   image-indiv-run-${i}.jpg
       convert image-indiv-run-${i}.jpg -sample 1024x                              \
                                                   image-1024-indiv-run-${i}.jpg
       convert image-1024-indiv-run-${i}.jpg -thumbnail 200x200                    \
                                                   image-thumb-indiv-run-${i}.jpg
       convert -background white image-1024-indiv-run-${i}.jpg label:12345 -append \
                                                   image-labelled-indiv-run-${i}.jpg
       echo "DONE: run indiv $i ..."
    done
    
    real  0m49.165s
    user  0m39.004s
    sys   0m6.661s
    
    time for i in $(seq -w 1 100); do
        convert image.tiff                                        \
         -respect-parentheses                                     \
         +write mpr:XY                                            \
          \( mpr:XY -resize 1024x                                 \
                    +write image-1024-pipel-run-${i}.jpg     \)   \
          \( mpr:XY -thumbnail 200x200                            \
                    +write image-thumb-pipel-run-${i}.jpg    \)   \
          \( mpr:XY -resize 1024x                                 \
                    -background white label:12345 -append         \
                    +write image-labelled-pipel-run-${i}.jpg \)   \
         null:
       echo "DONE: run pipeline $i ..."
    done
    
    real   0m29.128s
    user   0m28.450s
    sys    0m2.897s
    
    time for i in $(seq -w 1 100); do
        convert image.tiff                                         \
         -respect-parentheses                                      \
          \( -clone 0 -thumbnail 200x200                           \
                      +write image-thumb-pipel-run-${i}.jpg    \)  \
          \( -clone 0 -resize 1024x                                \
                      -background white label:12345 -append        \
                      +write image-labelled-pipel-run-${i}.jpg \)  \
         null:
       echo "DONE: run pipeline $i ..."
    done
    
    real   0m19.432s
    user   0m18.214s
    sys    0m1.897s
    
    time for i in $(seq -w 1 100); do
        convert image.tiff                                         \
         -respect-parentheses                                      \
          \( -clone 0 -thumbnail 200x200                           \
                      +write image-thumb-pipel-run-${i}.jpg    \)  \
          \( -clone 0 -scale 1024x                                 \
                      -background white label:12345 -append        \
                      +write image-labelled-pipel-run-${i}.jpg \)  \
         null:
       echo "DONE: run pipeline $i ..."
    done
    
    real   0m16.551s
    user   0m16.124s
    sys    0m1.567s
    
    time for i in $(seq -w 1 100); do
        convert image.tiff                                            \
         -respect-parentheses                                         \
          \( -clone 0 -thumbnail 200x200 -depth 8                     \
                      +write d08-image-thumb-pipel-run-${i}.jpg    \) \
          \( -clone 0 -scale 1024x       -depth 8                     \
                      -background white label:12345 -append           \
                      +write d08-image-labelled-pipel-run-${i}.jpg \) \
         null:
       echo "DONE: run pipeline $i ..."
    done
    
    time for i in $(seq -w 1 100); do                                 \
        cat <<EOF
        convert image.tiff                                            \
          \( -clone 0 -scale  1024x         -depth 8                  \
                      -background white label:12345 -append           \
                      +write d08-image-labelled-pipel-run-${i}.jpg \) \
          \( -clone 0 -thumbnail 200x200  -depth 8                    \
                      +write d08-image-thumb-pipel-run-${i}.jpg   \)  \
           null:
        echo "DONE: run pipeline $i ..."
    EOF
    done | parallel --will-cite
    
    real  0m6.806s
    user  0m37.582s
    sys   0m6.642s
    
    time for i in $(seq -w 1 100); do
        cat <<EOF
        convert image.tiff                                        \
         -respect-parentheses                                     \
         +write mpr:XY                                            \
          \( mpr:XY -resize 1024x                                 \
                    +write image-1024-pipel-run-${i}.jpg     \)   \
          \( mpr:XY -thumbnail 200x200                            \
                    +write image-thumb-pipel-run-${i}.jpg    \)   \
          \( mpr:XY -background white label:12345 -append         \
                    +write image-labelled-pipel-run-${i}.jpg \)   \
         null:
       echo "DONE: run pipeline $i ..."
    EOF
    done | parallel
    
    #!/bin/bash
    for i in $(seq -w 1 100); do
        echo ffmpeg -y -loglevel panic -i image.tif ff-$i.jpg 
        echo ffmpeg -y -loglevel panic -i image.tif -vf scale=1024:682 ff-$i-1024.jpg
        echo ffmpeg -y -loglevel panic -i image.tif -vf scale=200:200 ff-$i-200.jpg
    done | parallel
    
    time for i in $(seq -w 1 100); do 
     gm convert         image.tiff                         gm-${i}-image.jpg
     gm convert gm-${i}-image.jpg      -resize 1024x       gm-${i}-image-1024.jpg
     gm convert gm-${i}-image-1024.jpg -thumbnail 200x200  gm-${i}-image-thumb.jpg
     gm convert -background white    \
                gm-${i}-image-1024.jpg label:12345 -append gm-${i}-image-labelled.jpg
     echo "GraphicsMagick run no. $i ..."
    done
    
    real   1m4.225s
    user   0m51.577s
    sys    0m8.247s
    
    #!/bin/bash
    
    for file in $*; do
            convert $file \
                    -respect-parentheses \
                    \( -clone 0 -resize 200x200 \
                            +write $file-thumb.jpg \)  \
                    \( -clone 0 -resize 1024x \
                            -background white label:12345 -append \
                            +write $file-labelled.jpg \) \
                    null:
    done
    
    #!/usr/bin/python
    
    import sys
    from gi.repository import Vips
    
    for filename in sys.argv[1:]:
        im = Vips.Image.new_from_file(filename, access = Vips.Access.SEQUENTIAL)
    
        im = im.resize(1024.0 / im.width)
        mem = Vips.Image.new_memory()
        im.write(mem)
    
        thumb = mem.resize(200.0 / mem.width)
        thumb.write_to_file(filename + "-thumb.jpg")
    
        txt = Vips.Image.text("12345", dpi = 72)
        footer = txt.embed(10, 10, mem.width, txt.height + 20)
        mem = mem.join(footer, "vertical")
    
        mem.write_to_file(filename + "-labelled.jpg")
    
    $ time ../im-bench.sh * 
    real    0m32.033s
    user    1m40.416s
    sys 0m3.316s
    $ time ../vips-bench.py *
    real    0m22.559s
    user    1m8.128s
    sys 0m1.304s