ImageMagick 示例 -
API 和脚本

索引
ImageMagick 示例前言和索引
API 和其他 IM 使用方法
安全问题
提高 ImageMagick Shell/PHP 脚本效率的提示
为什么使用多个 "magick" 命令
提高 IM 速度(一般情况下)
从源代码编译 ImageMagick
这些示例中涉及的 ImageMagick 的命令行界面 (CLI) 只是使用、修改和控制 ImageMagick 核心库函数 (MagickCore) 的众多方法之一。它基本上是“shell” API 接口。您可以使用许多编程语言更直接地使用其他应用程序编程接口 (API),请参见 ImageMagick API。在这里,我将探讨如何改进您的 IM 脚本和编程,Windows 和 Unix 脚本之间的差异,以及从其他 API 和编程语言使用 IM 的基础知识。

API 和其他 IM 使用方法

实际上,用于实际图像处理的 API 并不比使用 CLI 命令(例如“magick”(它本身代表一种 shell-API)快。所有 IM 图像处理都使用相同的“核心”库。因此,如果您要执行复杂的任务,例如图像扭曲,在 shell “magick” 上使用 API 在总体处理“速度”方面几乎没有区别。那么为什么在命令行上使用 API?Shell 不断地“分叉”许多不同的命令(不仅仅是 IM“magick” 命令,尽管 shell 有一些“内置命令”),每个命令都需要加载和初始化才能运行。每个 IM 命令还必须重新初始化其配置文件,解析命令行参数,重新读取您正在处理的图像,并且通常将结果保存回磁盘。所有这些都需要时间,导致它们速度变慢。也就是说,所有这些额外的步骤都需要时间和处理能力,所以如果您经常这样做,API 开始变得有意义。API 还可以让您执行命令行无法执行的其他操作。
  • 如果 API 已经在运行,您几乎不需要设置时间。
  • 在内存中存储许多图像列表的数组,您可以按任意顺序处理这些数组。例如,我有一个程序可以读取数百张图像,在读取时将它们缩略为 32x32 像素的图像,然后使用 magick 将它们全部成对比较(对于 100 张图像,共进行 9900 次比较)。另一种方法是按内存中的通用颜色对图像进行排序!
  • 您可以执行许多不同的图像处理线程,并且可以按任意顺序执行。您不必在处理下一张图像或步骤之前完成一个处理序列。例如,想象一个解决拼图的程序!
  • 您可以从图像中检索信息,并以复杂的方式使用这些信息来修改图像处理,而无需反复重新初始化图像处理(重新读取配置和图像)。例如,在计算图像的构图要求之前获取图像大小。
  • 循环遍历图像,对每个图像进行非常不同的处理!例如,生成动画序列,其中每一帧以略微不同的方式扭曲。
  • 直接完全随机访问图像数据。例如,在图像中查找“面部”。
但是,对于大多数不涉及大量图像或以明确定义的方式进行常规图像处理的任务,命令行几乎一样快。但是,您可以通过以下方法节省大量时间和重新处理时间...
  • 利用 MPC 图像保存(用于更快的重新读取)中间图像。参见我的脚本 divide_vert
  • 使用管道处理进行并行处理(甚至使用不同的机器进行不同的步骤!),以更好地利用处理器并避免将中间图像保存到磁盘。参见 enlarge_image 以获取管道脚本示例,其中一个步骤将图像(s)管道传输到序列中的下一个(有时是可选的)步骤。
  • 使用循环分别处理每个图像,然后将图像结果流管道传输到最终的“将它们全部合并”步骤。我有许多这样的脚本...参见 分层图像的程序化定位,以了解其中一个脚本。
当然,在 API 中,您还拥有不同的、更快的技术,这些技术也可以用于需要访问图像的特殊处理任务。随着我们发现和获得时间,我们经常将这些技术编程到核心库中。图像扭曲和各种 FX 表达式就是一个例子。

Windows 和 DOS

使用 Windows 和 DOS 脚本(使用 CLI API)的示例已移至 Windows 下的使用

PHP(来自“system()”函数的 IM 命令)

PHP 用户可以使用三种方法使用 ImageMagick:
  • imagick PECL 接口
  • MagicWand” 接口
  • 使用“system()”和“exec()”函数运行 CLI“magick”命令。
由于存在 IM 示例,这种后一种方法(也是我们将首先介绍的方法)近年来已成为从 PHP 使用 IM 的最常见方法。当然,对于某些情况,它可能不是最佳方法(见上文),在这种情况下,API 接口可用,但可能需要系统管理员才能使其对您的 PHP 环境可用。

使用 Shell 命令的 PHP

使用这种技术的最佳信息来源是 IM 论坛用户Bonzo 以及他的网站 RubbleWebs。请注意,PHP 使用与您从命令行获得的不同环境(甚至可能作为不同的用户)运行“magick”。因此,在命令行上可用的内容可能需要进行一些调整才能在 PHP Web 驱动的脚本中使用。以下是在初始测试 ISP 的命令行 IM 接口时的推荐程序,假设您没有对远程系统的直接命令行“shell”访问权限。也就是说,您只能上传 Web 文件以供执行。因此,我们要做的第一件事是尝试找到系统上的“magick”命令,找出安装的版本以及 PHP 运行的环境。在 Linux Web 服务上,从 ISP 的 Web 服务器上传并访问此 PHP 脚本...

<?php
  header('Content-Type: text/plain');
  system("exec 2>&1; pwd");
  system("exec 2>&1; type magick");
  system("exec 2>&1; locate */magick");
  system("exec 2>&1; magick -version");
  system("exec 2>&1; magick -list type"); <!-- before IM v6.3.5-7 -->
  system("exec 2>&1; magick -list font");
  print("------ENVIRONMENT VARIABLES-------\n");
  system("exec 2>&1; env");
?>
这将运行相当多的命令来查看您的环境。第一个“pwd”告诉您运行 PHP 脚本的当前目录。这可能是也可能不是 PHP 脚本所在的目录,您可能无法从 PHP 脚本中写入该目录。接下来的两个命令告诉您,使用“type”是否可以在默认提供的命令 PATH 上使用“magick”,如果是,则告诉您它在哪里。“locate”命令应该找到服务器上存在的所有“magick”命令(假设它是 Linux 服务器),但可能会找到其他非 ImageMagick“magick”命令、文件和目录。您需要解释结果。接下来的三个命令假设“magick”位于命令 PATH 上,并要求它报告其版本号以及 IM 认为可以访问哪些字体。哪个命令报告哪些字体取决于安装的 IM 版本的旧版本。如果您只看到错误,则“magick”不在命令行路径上,并且您的 ISP 提供商在安装过程中没有正确初始化 Web 服务器的“PATH”和“LD_LIBRARY_PATH”以包含它。请参见“env”命令的输出以了解他们定义了什么。如果是这种情况,您需要找出它确切的存放位置并使用以下类似的 PHP 脚本。这将使您的脚本的可移植性降低,因为它针对该特定 ISP 进行了硬编码。例如,假设“magick”命令位于“/opt/php5extras/ImageMagick/bin”中,那么您可以设置一个变量来指定它的位置。这通常在应用程序配置和安装过程中完成,用于在不同的 ISP 主机上使用的 PHP 脚本)。

<?php
  $im_path="/opt/php5extras/ImageMagick/bin"
  header('Content-Type: text/plain');
  system("exec 2>&1; $im_path/magick -version");
  system("exec 2>&1; $im_path/magick -list type");
  system("exec 2>&1; $im_path/magick -list font");
?>
如果您遇到“ldd”库错误,“LD_LIBRARY_PATH”错误,并且 ISP 在安装过程中肯定没有完成工作,您需要报告错误并让他们修复 Web 服务器的“LD_LIBRARY_PATH”环境变量设置,或重新安装 ImageMagick。与其设置 magick 命令的位置,您也可以在顶部添加一行来调整 PATH 环境变量。但是,这种方法通常在典型的 PHP 系统配置中默认被“拒绝”...

  putenv("PATH=" . $_ENV["PATH"] . ":/opt/php5extras/ImageMagick/bin");
  putenv("LD_LIBRARY_PATH=" . $_ENV["LD_LIBRARY_PATH"] .
                                   ":/opt/php5extras/ImageMagick/lib");
之后,尝试 IM 示例中的一些更简单的示例,并尝试使它们正常工作。例如,将 IM 的“rose”图像作为 JPEG 图像文件输出回 Web 用户...

<?php
  header( 'Content-Type: image/jpeg' );
  passthru("magick rose: jpg:-");
?>
如果您需要设置 magick 命令位置,可以使用...

<?php
  header( 'Content-Type: image/jpeg' );
  $magick="/opt/php5extras/ImageMagick/bin/magick"
  passthru("$magick rose: jpg:-");
?>
或者,如果您遇到库问题,可以尝试以下类似内容...

<?php
  header( 'Content-Type: image/jpeg' );
  $magick="/opt/php5extras/ImageMagick/bin/magick";
  $libs="LD_LIBRARY_PATH=\'" .  $_ENV["LD_LIBRARY_PATH"] .
               ":/opt/php5extras/ImageMagick/bin/magick\'";
  system("$libs $magick rose: jpg:-");
?>
如果您仍然没有看到任何内容,请查看我的原始 PHP 提示和技巧 文件以获取有关重定向错误消息技术的相关信息。
当您使该基本脚本正常工作后,您可以尝试从您的 PHP 测试脚本中列出的字体(修改以下内容以适合您的 PHP 服务器)。例如,在当时我可用的 Solaris 服务器上,我注意到“Utopia”字体集可用,因此我可以尝试使用该字体创建标签...

<?php
  header('Content-Type: image/gif');
  passthru("magick -pointsize 72 -font Utopia-Italic label:'Font Test' gif:-");
?>

Shell 到 PHP 的示例转换

这里有一个非常典型的 ImageMagick 命令...

  magick -background none -fill red -gravity center \
          -font Candice -size 140x92 caption:"A Rose by any Name" \
          \( rose: -negate -resize 200% \) +swap -composite    output.gif
转换为 PHP 后,它将变成类似以下内容...

<?php
  header('Content-Type: image/gif');

  $color="red";
  $image="rose:";
  $scale="200%";
  $size="140x96";
  $string="A Rose by any Name";

  passthru( "magick -background none -fill '$color' -gravity center" .
            " -font Candice -size '$size' caption:'$string'" .
            " \\( '$image' -negate -resize '$scale' \\) +swap -composite" .
            " gif:-" );
?>
请注意,我仍然将“magick”命令的长命令行拆分成多行,以便更容易地跟踪图像处理顺序,并在以后进行编辑。这是使用 PHP 附加字符串完成的,而不是 shell 脚本中使用的 shell 行续行符。还要注意后面几行开头额外的空格。以及对原始命令中存在的其他反斜杠进行双重转义。或者,您可以使用单引号而不是反斜杠来保护这些选项。我还使用了一些 PHP 变量,以便更容易地调整 PHP 脚本生成的图像,以更好地控制结果。但是,当我将这些选项插入“magick”时,我使用了单引号来保护它们不受 shell 的进一步修改。但要注意这些插入字符串中的单引号!您可以将这些选项设为 PHP 输入参数,以便您可以为从 Web 请求传递给它的任何输入文本生成图像。您也可以在同一个系统调用字符串中执行多个 shell 命令。事实上,如果您愿意,单个系统调用可以包含一个完整的 shell 脚本!因此,您可以在一个系统调用中执行 shell 循环和多个命令(以及清理操作)。许多人可能没有意识到这一点。基本上,如果您小心,您可以很好地利用 PHP 提供的数学运算和 shell 的脚本功能。同时进行。只需注意引号。有关从 PHP 调用 ImageMagick 命令的各种示例,请参见 Rubble Web, Writing IM code in PHP,其中描述了四种不同的技术。

注意额外的引号

请注意,通常在 PHP 中,IM 命令会被额外的引号(通常是双引号)包裹,因此必须注意这些额外的引号级别。记住,当 PHP 执行一个字符串时……PHP 会进行自己的引号、反斜杠和变量替换,然后Shell 会将参数拆分并进行自己的变量和引号替换。如果存在,它还会执行任何“2>&1”类型的文件描述符重定向。ImageMagick 会获取一个参数数组,但也会对文件名元字符进行自己的处理,特别是针对 DOS(dos 环境不处理元字符)和诸如 coder:*.gif[50x50] 之类的参数,这些参数由于 coder: 前缀或 [...] 读取修饰符而无法扩展。也就是说,有很多参数解析!这可能意味着很多引号和反斜杠处理。请注意,并提前考虑。我建议您至少阅读 PHP 手册中关于 程序执行函数 的内容,包括: PHP exec()system()passthru()。还可以查看 反引号运算符。尤其重要的是,要了解究竟返回了什么(通常是最后一行)以及传递给调用客户端的内容(所有其他内容)。

PHP 安全

记住...

   On the net, the only users you can trust not to be potentially hostile
   are those who are  *activally*  hostile.
                                     -- Programming Perl - Camel Book, r3
您必须彻底检查从用户传递到 IM 命令的所有输入参数。确保参数与您的预期完全一致。在处理万维网时,过度限制总比不足限制好。一些常见的注意事项包括
  • 参数中的二进制字符 - 常见的破解技术
  • 参数中意外出现的空格、制表符、换行符和回车符。
  • 反斜杠(目录分隔符)和 '..' 路径,在 Windows 中,文件名中的 '\' 和 ';' 也是如此。
  • 文件扩展元字符,包括 "~*?[]{}<>" 以及特定于 ImageMagick 的特殊 "@" 元字符。
  • 其他 shell 元字符,包括 "$#;" 以及三个引号字符 '''、'"'、'`'
  • 参数与 ImageMagick 预期不符。使用 "-list" 来读取 IM 针对特定选项可以理解的参数类型。例如,用户输入的 "-gravity" 选项只有 10 种不同的设置。
  • 等等...
对于任何类型的 Web 编程工作,了解安全性和黑客如何使用精心制作的参数来破坏调用的命令至关重要。不仅仅是 PHP,还有 Shell 和 ImageMagick。IM 需要特别注意,因为它可以例如将密码文件读取并转换成图像,然后返回。再说一次……在涉及 Web 时,过度限制总比打开意想不到的安全漏洞好。

写入文件系统

如上所述,如果您遵循了上述初始步骤,您将确定,PHP 通常以不同的方式运行,在服务器上具有更高的限制性。因此,它通常无法写入包含脚本的目录(或它实际运行的任何地方)。出于安全原因,您通常不希望写入该目录!如果您真的想让 PHP 写入文件,请让它将图像(或数据)保存到“/tmp”中的唯一文件名,最重要的是,在正常退出时或任何错误发生时进行清理。令人惊讶的是,应用程序如果不能正确清理,就会很快用残留的临时文件填满磁盘。如果保存的文件(图像)必须对 Web 服务器可见,请为这些文件创建一个特殊的“程序写入”子目录。应该如何操作。大多数 PHP 应用程序实际上通过使用数据库后端来避免写入任何内容到文件系统。也就是说,cookie、令牌、用户数据、图像等都写入数据库,例如(按复杂性和规模排序)SQLite、PostgresSQL、MySQL 和 Oracle。它根本不会在文件系统中保存任何内容。系统程序员通常会在安装应用程序时使用这些信息配置 PHP 应用程序。图像通常由相同的或独立的 PHP 脚本生成,该脚本查找图像“blob”并将其输出到客户端。图像可以作为 HTML 本身的“内联”图像发送(请参见“inline:”格式,其中包含 HTML 内联图像的演示),或者作为单个“一体化”的多个图像发送,以便客户端 HTML/JAVA 只有一个图像请求,而不是 20 个单独的请求。最后一点。始终应该存在某种清理旧数据的方法。一个 2 年未登录的用户,他的数据可能应该被删除。

获取错误输出

尝试以下方法之一...

<?php
exec("/usr/local/bin/magick -version",$out,$returnval);
print_r($out[0]);
?>

<?php
exec("/usr/local/bin/magick -list",$out,$returnval);
print_r($out);
?>
或使用 shell_exec,如下所示

<?php
$IM_version=shell_exec("/usr/local/bin/magick -version");
echo $IM_version
?>
要包含 STDERR 输出...

<?php
$array=array();
echo "<pre>";
exec("magick read_test.png write_test.png 2>&1", $array);
echo "<br>".print_r($array)."<br>";
echo "</pre>";
?>
以上内容来自 IM 用户论坛讨论... How to show IM error info in php?。查看我自己的 PHP 调试错误日志 笔记。它指向 PHP 手册中的错误记录 PHP 错误处理和记录,特别是查看示例部分。

更安全的 ImageMagick 命令...

出于安全原因,理想情况下,您应该避免使用 shell 将单个长字符串解析成单独的命令和参数。最好自己动手!这意味着您将参数作为单独字符串的数组提供给命令,而不是作为单个 shell 解析的字符串提供。通过这样做,您可以防止出现 shell 语法错误,以及 shell 需要额外的引号负担,并防止一些黑客破坏 shell 命令并运行他们自己的命令(非常糟糕)。另一方面,您失去了 shell 脚本、管道和文件重定向,但这在您已经使用 PHP 或其他一些包装语言时通常不会造成太大损失。在 PHP 中,我唯一能找到的可以让我直接调用命令而不使用 shell 的函数是 pcntl_exec() 函数。这基本上避免了 shell,并直接调用命令。但是,它是一个真正的“execl()”系统调用,它用给定的命令替换当前进程。也就是说,它不执行“fork()”和文件描述符链接,这是将其作为子进程运行所必需的。因此,pcntl_exec() 实际上是针对生成用途而言过于底层的,并且实现“无 shell”命令可能会变得相当复杂。我非常惊讶的是,PHP 接口尚未提供更简单、更安全的“避免 shell”命令调用。但我是 PHP 程序员。另一方面,Perl 提供了许多安全调用子命令和进程的方法,这使得它通常比 PHP 更适合作为 Web 接口。有 PHP 安全知识的人愿意提供更多信息或提供更多信息的指针吗?

PHP 'IMagick' API

要测试 PHP PECL Imagick 模块是否实际工作,请将一个简单的测试“image.jpg”图像和此 PHP 脚本上传到同一个 Web 可访问目录。

<?php
  $handle = imagick_readimage( getcwd() . "image.jpg" );
  if ( imagick_iserror( $handle ) ) {
    $reason      = imagick_failedreason( $handle ) ;
    $description = imagick_faileddescription( $handle ) ;

    print "Handle Read failed!<BR>\n";
    print "Reason: $reason<BR>\n";
    print "Description: $description<BR>\n";
    exit ;
  }
  header( "Content-type: " . imagick_getmimetype( $handle ) );
  print imagick_image2blob( $handle );
?>
有一个 PHP IMagick 手册 可在线获取,您可以在 Mikko 的博客 中找到更多有关使用 IMagick 的示例。IMagick 唯一的缺点是它没有得到维护和升级,因此可能存在一些无法正常工作或缺少的函数。请确保您使用的是 v3.x 版本的 IMagick 和当前版本的 IM。它确实有效,而且对于大多数情况来说它工作得很好,但如果您需要执行其他操作,那么其他 PHP 方法可能是一个更好的选择。

PHP 'MagickWand'

您可以使用以下方法检查 PHP MagickWand 模块是否包含在 PHP 安装中...

<?php
  if (extension_loaded('magickwand')) {
    echo "PHP MagickWand is available!\n";
  } else {
    echo "PHP MagickWand is NOT available!\n";
  }
?>
但要检查它是否实际正常工作,请上传一些测试“image.png”以及此脚本...

<?php
  $image = NewMagickWand();
  if( MagickReadImage( $image, 'image.png' ) ) {
    header( 'Content-Type: image/jpeg' );
    MagickSetImageFormat( $image, 'JPEG' );
    MagickEchoImageBlob( $image );
  } else {
    echo "Error in MagickReadImage()";
    echo MagickGetExceptionString($image);
  }
?>
以上内容不提供任何保证,不过欢迎提供更多反馈。我通常不使用 PHP 编程,但我使用以上内容测试了 SunONE-PHP5 测试安装(使用所有三种方法:命令行、magick、MagickWand)。

复杂的 PHP 脚本...

如果您需要生成和输出 HTML 和图像,请考虑设计您的 PHP 脚本,以便单独的 HTML 请求或输入选项从相同或不同的 PHP 脚本生成 Web 文档所需的不同部分。也就是说,一个顶级的 PHP 脚本可以输出带有适当的 <IMG> 标签的 HTML,这些标签调用自身(或另一个 PHP 脚本)并带有适当的选项,以创建或修改在第一个顶级 PHP 脚本中显示的图像。这就是许多照片相册和绘图 PHP 脚本的工作方式。所有这些都由 URL 调用的 GET 和 PATH_INFO 扩展控制。请注意,您不能在 IMG 标签内使用 POST。通过这种方式,您应该能够完全避免为 PHP 生成的网页生成、保存和清理临时图像的需要。这是一个充满问题(例如资源限制和垃圾回收)的解决方案,使其成为一种非常糟糕的编程技术。这种技术在 ImageMagick 手册 中都有介绍,虽然它实际使用的 ImageMagick 已经有些过时了。

Perl Magick 脚本

The PerlMagick API 是将 "magick" 命令转换为脚本的良好方法,该脚本还可以处理数据库、大量图像或更复杂的图像处理,而这在其他情况下是不可能的。 最好的帮助是查看 PerlMagick 的 "demo" 脚本,该脚本既在源代码中,通常也安装在 PerlMagick 的文档区域。 在我的系统上,它位于 "/usr/share/doc/ImageMagick-perl-*/demo/" 中。 在此直接文件中,有越来越多的关于读取、写入和处理各种图像的简单示例。 此外,还有名为 "demo.pl" 的脚本,它列出了几乎所有常见的图像处理选项以及如何使用它们。 将命令行 "magick" 命令转换为 perl 时,需要记住一些事项。
  • 首先要记住,PerlMagick 不会自动删除已处理的新图像。 许多运算符从旧图像创建新的修改后的图像,而另一些则直接修改现有图像。
  • 同样,许多运算符不会将特定操作应用于整个图像列表,而只会应用于您提供的列表中的第一个图像。 这意味着您需要循环遍历图像序列(perl 数组)本身。
  • 您可能拥有多个图像序列。 事实上,您通常将每个图像读取到其自己的独立图像序列中,而不是像在命令行中那样,只使用一个图像序列。
  • 此外,一旦将图像加载到内存中,您就可以轻松地提取现有图像的大小。 这意味着您可以直接创建新的画布,而无需像在命令行中那样克隆和清除现有图像。 但是克隆图像也会复制图像的元数据,因此您可能希望跟踪诸如数码照片之类的图像的元数据。
  • 在每个主要进程后(尤其是读取图像时),检查图像错误(如 PerlMagick 页面所示)。
要将命令行转换为 perl,您基本上需要执行完全相同的操作,按完全相同的顺序。 但是,由于图像通常不会被删除,并且多个图像序列很常见,因此在 "magick" 命令中使用括号和额外的克隆操作通常不是问题。 将脚本转换为 perl 的最难的部分通常是将命令行选项映射到 PerlMagick 函数调用。 我发现最快的方法是获取 IM 的源代码并查看文件 "MagickWand/mogrify.c",然后搜索您遇到的特定命令行选项。 例如,对于 say 的 -threshold 选项,搜索 "threshold"(包括引号)。 将有两处匹配,一处用于快速语法解析以确保找到所有选项,另一处用于该选项的实际内部调用。 在这里,您将找到所用库函数的名称,该名称通常会直接映射到 Perl 函数。 在这种情况下... BilevelImageChannel()

安全警告

在编写供公众使用的脚本时,尤其是基于 web 的 PHP 脚本,世界上任何人都可以运行它,验证所有可能来自未知用户(甚至已知用户)的内容至关重要。 我指的是 **所有内容**,从参数、文件名、URL 和图像。 在您验证某个输入参数之前,该参数可能包含字母、数字、空格、标点符号,甚至 "null" 和控制字符。 在您彻底检查之前,应将其视为可疑的,不应使用它。 无论您使用什么 web 控制的输入表单都没有关系。 一个稍微了解的人可以很容易地使用自己的参数调用您的 PHP,而根本不使用该输入表单。 不要相信他们不会这样做,机器人就在那里,阅读输入表单并创建他们自己的 "hack" 参数来尝试侵入随机脚本。

文件名中的元字符

作为安全问题,您应该特别注意包含空格、引号、标点符号、控制字符或其他元字符的文件名,因为 IM 和 Shell 都可能尝试展开它们。 问题是名为 '*?@${&) .jpg' 的文件实际上是 UNIX 下完全合法的文件名,但是如果该程序(如 shell 和 IM)也执行文件名展开,那么许多程序将难以处理它。 请记住,即使您阻止 shell 执行 "glob" 元字符展开,IM 本身也会执行此展开(用于 DOS 使用)。 因此,阻止所有此类字符(并产生错误)可能是一个明智的做法。 作为一项安全措施,如果文件名包含任何未知或不寻常的字符,例如不是字母、数字或预期的后缀,则通常最好报错并中止。 在将此类文件名传递给 shell 命令或 IM 之前。 最好是更严格地限制并阻止某些内容,而不是宽松地允许某些不良内容通过。

改进 ImageMagick Shell/PHP 脚本的提示

这些是我针对发送到 IM 邮件列表以便其他人使用的贡献 shell 脚本所做的一些基本脚本编程要点。 我最初将这些内容私下发送给作者(将保持匿名),他对此表示感谢。 它们并非全部是 IM 特定的,但无论如何都应适用,作为标准编程实践。 特别是如果您打算让其他人使用、查看和/或调试您的程序或脚本。 这反过来将使您的脚本更有用。
  • 将 "help" 或 "doc" 放在脚本和程序的顶部。 这使其他人更容易弄清楚特定程序的功能,而无需安装或运行该脚本。 我自己经常会放弃没有此类清晰注释来说明其功能的程序,而不是尝试编译或运行此类未知脚本。 事实上,我见过一些大型项目,第一个 README 文件甚至没有说明庞大而复杂的项目的功能! 程序员只是假设如果您下载了它,您一定知道它的功能! 此外,请确保 "bad option"(例如 "-?")将打印选项的概要,以及程序功能或在哪里可以找到此类帮助的简要摘要。 不要仅仅指向一个远程网站,该网站可能在 10 年后消失! 有关打印自身 "opening comments" 的脚本示例,请参见 IM scripts 区域中的 "jigsaw" 脚本。 Perl 可以使用 POD 进行自文档(参见 perl "Pod::Usage" 模块)。 例如,请参见贡献的 dpx_timecode.pl 脚本。 在第一个子例程中将帮助作为 "here file" 也是可以接受的,并且适用于大多数语言。 但请将该子例程放在 **顶部**,而不是脚本或程序的底部或中间。
  • 确保清除代码,删除旧的过时代码和注释,尽可能使代码整洁美观。 尽可能简洁,并进行简单的注释阶段。 再次参见 "jigsaw" 脚本。
  • 确保在结束时清理临时文件。 使用 "trap" shell 命令在文件退出或中断时删除它们。 您当然可以多次重复使用单个临时文件,因此您不需要太多文件,尤其是在使用 IM v6 magick 命令时。 再次参见 "jigsaw" 脚本,并搜索 "trap"。
  • 此外,并非所有人都使用系统 X,虽然您可能觉得是这样。 不要提及特定系统要求或解决问题的 方法。 对您有效的方案可能完全不适合他们的系统和设置。 他们甚至可能没有互联网访问权限! 只需说 ImageMagick 的 "magick" 命令未找到即可。 如果您想添加安装要求或建议,请将其作为单独的更详细文档的一部分添加。
  • 请检查所使用的 IM 版本是否足够高,或者添加向后兼容的更改。 我故意在 IM 示例中提供 "version warning" 说明,以说明何时添加了各种特殊功能。 在使用单个最小版本检查创建脚本时,这会更容易。 以下是一种简单的方法,您可以在 shell 脚本中使用它来获取用于测试的单个版本号。 它提取 4 个版本号,并在每个数字前插入适当数量的零,以使每个数字都为 2 位数,从而生成一个简单的 8 位数字。
    
        IM_VERSION=`magick -list configure | \
             sed '/^LIB_VERSION_NUMBER /!d;
                  s//,/;  s/,/,0/g;
                  s/,0*\([0-9][0-9]\)/\1/g'`
    
    例如,IM v6.3.5-10 将生成 "06030510",而下一个版本 IM v6.3.6.0 将生成 "06030600"。 从 RubbleWeb, Font List 示例页面提供了上述内容的 PHP 版本。 可以使用简单的数字或字符串测试对生成的字符串进行测试,以发现可用的 ImageMagick 版本是否足够现代,以满足您的脚本要执行的操作。 例如...
    
        if [ "$IM_VERSION" -lt '06030600' ]; then
          echo >&2 "The perspective distortion operator is not available."
          echo >&2 "Sorry your installed ImageMagick is too old -- ABORTING"
          exit 10
        fi
    
    此外,请注意我如何向用户输出中止的确切原因,以及版本检查针对的特定特殊功能。 否则,您以后可能会忘记为什么需要该特定版本(或更高版本)。 您还可以修改 IM 在特定版本下的行为。 例如,假设我想获取可用字体的列表。 在 IM 版本 v6.3.5-7 之前,"-list" 设置 "type" 返回 "known font" 列表。 在更高版本中,您需要使用 "font" 设置。 因此,在这里,我可以进行版本检查以使用正确的设置获取所需的信息。
    
        if [ "$IM_VERSION" -lt '06030507' ];
        then font_list="type";
        else font_list="font";
        fi
        avail_fonts=`magick -list $font_list | cut -d\  -f1 |\
                        egrep -v '^($|----|Path:|Name$)'`
    
    警告:PERL 中以 "0" 开头的字符串可能会被解释为八进制数! 但是,只要第一位数字保持 "0",比较两个八进制数仍然会得出正确的结果。 建议谨慎并检查版本测试。 测试版本的另一种方法是使用 "expr" 而不是 "[' 测试...
    
        if  expr + "$im_version" \>= "06030507" >/dev/null; then
           ...
    
    警告:上述内容中的额外 "+" 通常不需要,至少对于此测试而言,但如果变量可能包含特殊关键字 "match",则需要它,尤其是在用于字符串或子字符串工作时,会给 "expr" 带来问题。
  • 您还可以利用 "-list" 信息输出检查是否已在当前安装的 ImageMagick 中添加了一些特殊功能。
    
        magick -list distort | grep 'Arc' >/dev/null 2>&1
        if [ "$?" -ne 0 ];  then
          echo >&2 "Arc distortion method not available."
          echo >&2 "Sorry your installed ImageMagick is too old -- ABORTING"
          exit 10
        fi
    
    但是请注意,在 IM 开发过程中,"-distort Arc" 之类的全新方法可能会在正式准备好供一般使用之前出现。 因此,版本检查可能仍然是一个更好的主意。 这就是为什么我在 IM 示例中尝试说明(查找 符号)IM 版本,以说明何时一项新功能已足够稳定,可以供一般使用。
  • 不要使用非常非常长的单行命令,尤其是对于复杂的“convert”命令。使用行延续方法(如上所示)将它们拆分,例如UNIX中的“\”、DOS中的“^”和PHP中的“.”字符串连接。但是,我并不意味着将每个设置和操作都放在单独的行上。每个操作或步骤占据一行,创建新图像、修改图像、与其他图像合并等。将特定操作所需的全部操作设置放在该操作符之前。将每行视为单个处理步骤。这样可以将行分开,以便于读取和理解各个处理步骤。操作符之间的划分越清晰,复杂图像处理就越容易理解。使用额外的括号、缩进各阶段的代码行,甚至在大型处理块之间添加空行,都可以让您更轻松地查看大型和长时间操作的主要阶段。我在IM示例中广泛使用这些技术,以便使示例更容易理解和理解,所以请四处看看!最后,关于特定命令正在执行的操作的额外注释可以在其他人(甚至是你自己两个月后)阅读和理解你的脚本时产生很大影响。可惜的是,目前无法在长命令行中插入注释!
  • 尽量不要依赖太多的外部程序,或者只在这些程序可用时使用它们(可能存在替代方案)。其他人可能没有那个程序,或者更喜欢使用其他东西。如果程序的使用可以是可选的,那就让它可选,要么是在用户控制下,要么是在找到的情况下自动使用。尽可能地避免将其强制要求,如果可以的话。例如,你可以使用“pngcrush”、“optipng”、“pngnq”来压缩PNG,效果比IM通常提供的更好(IM的设计是通用的,而不是特定的)。同样,“gifsicle”、“intergif”或其他用于GIF动画的LZW压缩优化器也有其优点和缺点。不要将其作为脚本运行的必要条件。作为一个实际的例子,旧版本的"gif2anim"没有使用ImageMagick的“magick identify”来查找GIF特定的元数据,而是依赖于一个修补版本的“giftrans”。由于ImageMagick的“magick identify”的改进,后来不再需要这个要求,所以我去掉了这个要求,以便使脚本更广泛地可用。ImageMagick本身有很多可选的要求,例如“ghostscript”用于PostScript和PDF文档读取,或者“librsvg”用于正确处理SVG矢量图像。当这些库可用时,IM会很高兴地工作。IM将这些库视为可选,只有在您想处理这些格式的图像时才需要它们。以下是一个代码片段,您可以用来检查脚本依赖关系(在极简的cygwin环境中特别有用)...
    
      # Check Dependencies to scripts correct working
      DEPENDENCIES="sed awk grep tr bc magick identify"  # adjust to suit
    
      for i in $DEPENDENCIES; do
        type $i >/dev/null 2>&1 ||
          Usage "Required program dependency \"$i\" missing"
      done
    
  • 进一步说明最后一点。如果您在使用IM的shell脚本中需要浮点运算,可以使用IM本身来进行运算,而不是依赖于其他程序,例如“awk”或“bc”,这些程序可能不可用(尤其是在Windows上的cygwin下)。例如,这里我们使用“magick”来计算给定角度(以度为单位)的sin()...
    
      angle=-20
      sine=`magick xc: -format "%[fx:sin( $angle *pi/180)]" info:`
      echo $sine
    
    上面的代码将输出值“-0.34202”。您可以使用精度操作控制调整小数位数。默认情况下,它设置为6位。
  • 让用户决定使用输入/输出图像格式。ImageMagick主要是一个图像转换器,能够使用许多不同的格式。它可以输出到屏幕、PostScript、打印机,或者将图像管道到另一个命令以进行进一步处理。不要将用户限制在特定的格式上。例如,“jigsaw”和"gif_anim_montage"脚本允许用户指定任何输入或输出图像。这样,用户可以将图像管道到该脚本中或从该脚本中管道出来,以便使用其他程序和脚本进行进一步处理。例如,我经常使用类似下面的命令...
    
        gif_anim_montage animation.miff show:
    
    来在我的显示屏上显示脚本的结果,而不是将其保存到文件中。事实上,在我的许多脚本中,如果缺少输出,它默认使用“show:”。我没有将其限制为仅从GIF动画文件输入,或者将输出限制为仅GIF、PNG或JPEG图像格式,而是允许脚本读取和处理ImageMagick可以处理的任何格式。事实上,IM可以从文件、管道、当前显示器甚至从万维网上读取数据,使用“URL:”或“HTTP:”输入格式。不要限制这些可能性,除非它成为一个安全问题(例如用于网络使用)。
  • 只读取输入图像和输出多图像一次!如果用户提供管道文件名或URL,您不应该尝试读取这些图像多次,否则可能会出现问题。当您需要多次引用该图像或以与程序参数所暗示的顺序不同的顺序引用该图像时,请使用临时文件、克隆图像或“MPC:”保存输入图像的副本。如果您能够处理来自管道的多个图像,那就更好了。同样,请参阅"jigsaw"脚本,了解在您被迫多次处理输入图像或以不同顺序处理输入图像时将输入图像保存到临时文件的示例。
这些基本上可以让使用您程序的用户有更多的自由度来做他们想做的事情,而不是您认为他们想做的事情。不要通过对脚本将被用于什么做出假设来限制他们或你自己。PS:我的主要专业领域是UNIX脚本编写,涵盖了各种不同的架构和UNIX、LINUX和其他类似UNIX系统的“风格”,我拥有超过25年的经验。对于以上内容,我应该知道自己在说什么。

为什么要使用多个“magick”命令

Willem于2006年10月25日(星期三)写道...
我想知道;有时我在你的示例中看到你多次调用Convert来获得想要的结果。一般来说,我希望多次调用magick是不必要的;应该可以在一次调用中完成所有操作(但命令会比以前更复杂)。你同意这个说法吗?
我完全同意。虽然在IM 6版本之前,这实际上是不可能的,因为当时的IM设计仅能完成每个命令一个或两个操作。然而,IMv7应该允许您在一个命令中完成所有处理。但遗憾的是,这并不总是可能的。我使用多个命令的原因可能有几个。通常在示例页面中,我会这样做,以便显示中间图像结果,以便更好地演示涉及的中间处理阶段。在同一示例区域的后面,我可能会重复该过程,但使用单个命令,可能稍微复杂一些。因此,原则上,一个命令可以完成所有图像处理。欢迎您将所有图像处理技术合并到一个命令中。我自己也经常这样做。唯一的例外是,当需要提取信息,然后将这些信息插入到下一个命令中时。一个例子是模糊裁剪技术,该技术需要您提取对图像模糊副本进行裁剪的结果。然后使用此结果来裁剪原始图像。我在缩略图圆角示例的更新中也使用了这种方法,其中我使用IM本身来生成一个绘制命令,使用图像的大小用于下一个命令。但是,有一些建议将允许直接从先前已读入内存的图像中生成选项。在脚本中,例如"jigsaw"脚本(请参阅高级技巧,拼图碎片),我通常会出于不同的原因使用多个命令——可选处理。这允许用户提供的各种输入选项来选择图像处理序列中的附加步骤。因此,对于可选处理,我通常也会为每个处理阶段使用单独的命令。在这种情况下,临时文件基本上是不可避免的。但是,我通常只需要一个或两个临时图像,并且每个步骤都会将图像处理回相同的或之前的临时文件名,以便下一个可选处理步骤继续进行。例如,处理图像以替换源图像。

  magick /tmp/image1.png ..operations..  /tmp/image1.png 

在这种情况下,MPC文件可以将下一个处理步骤中中间文件的读取速度提高到近乎即时,因为图像只是从内存中转储到磁盘,然后由下一个命令“分页”回内存。这样避免了IM格式化和解析图像文件格式的需要,尽管它确实使临时文件更大,因为它只是未压缩的内存。我用来避免临时文件的另一个方法是将工作图像从一个shell命令(if-then-else-fi或while循环)管道到另一个shell命令。这被称为图像管道,在许多示例中都有演示。一个例子是在MIFF图像流中,多个图像一个接一个地生成到同一个输出管道中,以便由下一个命令将它们合并到最终图像中。最后,您可能需要根据先前处理步骤的结果更改您的处理方式。例如,在图像比较中,我经常需要发现一些信息,以便在后面的处理步骤中使用,或者改变图像在后面阶段的处理方式。比较图表或漫画可能需要与比较真实照片图像完全不同的比较技术。如果使用多个命令成为问题,也许是时候使用API接口,例如PerlMagick,这样多个图像序列都可以保存在内存中,以避免不必要的磁盘I/O。

提高IM速度(一般而言)

有许多方法可以提高IM的运行速度。以下是最重要的方面,请牢记。随着您向下浏览列表,速度提升会越来越小,或者需要对IM安装进行更复杂的更改。
  • IM Q8(或每颜色值8位,每个像素3到4字节)比IM Q16默认值快得多(快3到4倍),后者具有更高的颜色分辨率。如果您不需要为图像使用Q16,也许您应该用Q8版本替换您的IM。但请注意,仅使用8位内部质量会影响整体图像处理,因为中间图像会丢失信息。请参阅HDRI了解与此相反的情况。
  • 如果可能,请使用单个“magick”命令,以便为单个图像完成所有处理。这样可以节省初始化时间,避免创建临时文件或命令之间的管道,甚至可以节省这些管道和磁盘I/O的图像文件格式的编码/解码时间。当然,有时您仍然需要使用多个命令,以允许可选的图像处理步骤,例如涉及图像大小、颜色甚至可选处理步骤的计算。IMv7脚本将有助于解决这个问题。
  • Shell 脚本本质上很慢。它是解释执行的,需要多个步骤以及额外的磁盘文件处理。当然,这得益于新的 IM v6 选项处理,它允许你在单个命令中执行大量图像处理操作。即使这样,你也很难在一个“magick”命令中完成所有操作,因此你通常需要使用多个命令来实现你想要的结果。因此,像 perl、ruby 或 PHP magick 模块这样的 API 速度更快,因为它消除了 shell 和 IM 命令行 API 的所有解释方面。它还减少了 IM 在读取字体和颜色定义时经历的初始化步骤。
  • API 还可以在程序的生命周期内保存所有图像,甚至多个图像列表(只要你有足够的内存)。这意味着你可以随意更改正在处理的图像,而无需像在命令行中那样对图像进行整理和调整。当需要根据之前的图像处理步骤进行额外的计算时,这尤其有用。
  • 写入 GIF 图像文件格式很慢。IM 必须努力减少(量化)图像的颜色以适应文件格式的有限颜色。即使这样,你通常也需要做额外的工作才能让它正确,特别是对于 GIF 动画来说。PNG 和 JPEG 速度更快,但以 PNG 的尺寸为代价,以及 JPEG 的质量损失。不过 GIF 图像在质量方面确实更差!
  • 预先准备和缓存图像,例如背景、叠加层、框架、蒙版,或预生成颜色查找表、失真映射、模板、蒙版等。所有这些都可以对你的处理时间产生重大影响。思考一下哪些可以提前完成。一个大型的预生成图像库比根据需要创建图像快得多。另请参阅"MPC:"的使用,用于中间和缓存图像。这些是磁盘上的内存映射图像,本质上具有零读取时间,但对其他任何事情或其他机器都无用。它们应该只在主要图像处理过程开始时创建,并且不应存储很长时间,因为任何最小的软件或系统升级都将使它们失效,并可能导致段错误。
  • 如果可以的话,避免使用FX,特殊效果图像操作符,如果你可以使用Alpha 合成,或更简单的评估,简单的数学运算,或其他技术。如果你确实需要使用它们,尝试将其限制在尽可能小的图像上,或限制在图像的单个通道上(处理灰度图像时)。
  • 避免使用大尺寸的图像模糊,当几个较小的模糊可能更快时。进行一些计时测试以查看哪一个更快。对于其他形态学卷积运算符(例如高斯和阴影运算符)也是如此。
  • 对小区域进行复杂处理时,使用较小的子图像或区域。例如,找到并提取一个人的眼睛(使用区域),然后进行蒙版和重新着色,这比处理完整的大图像版本要快得多。差异越大,节省的越多。
  • 在读取大型图像或大量图像时,最好使用读取修饰符在读取每个图像后立即调整大小或裁剪它们,从而减少整体内存需求。对于 JPEG,你可以使用特殊的'jpeg:size'库修饰符来避免分配内存。这反过来可以防止'磁盘抖动'(这会使计算机非常慢)。尤其是在涉及大量大型图像时,例如在生成蒙太奇目录索引或其他多图像拼贴时。
  • 对于必须从磁盘处理的真正巨大的图像,最好将它们分成更小的块进行处理。
  • 同样对于大型图像... 如果你使用的是 Window 64 位操作系统,请使用 64 位 ImageMagick 发行版。它使用更大的地址空间,并且可以将比 32 位 Windows 更大的图像放入内存。
  • IM 默认情况下会为单个图像处理操作使用多个线程。这意味着具有两个或更多个“核心”的计算机通常会比单 CPU 机器更快地处理图像。对于大型图像,OpenMP 多线程功能可以提供明显的加速优势,因为它使用更多 CPU 来完成单个图像处理操作。请注意,在 IM 中,只有单个图像处理操作是并行的。因此,节省更多的是在大型图像处理中,而不是在处理大量图像时(见下文)。
  • 对于小图像,使用 IM 多线程功能不会给你带来太多优势。在这种情况下,在不同图像上同时运行多个转换可以提高吞吐量。这在多个 PHP Web 请求可能会启动多个图像“magick”命令的情况下也可能发生。在这两种情况下,启用多线程都可能由于 CPU 竞争而造成严重不利影响,最好通过将'MAGICK_THREAD_LIMIT'环境变量设置为'1'来禁用 OpenMP。请参阅 IM 论坛讨论线程降低了“convert”的速度。你可能还想看看 MAGICK_THROTTLE,让 ImageMagick 更多地、更恰当地在 CPU 上让出控制权。
  • 如果你在图像上执行大量小操作(例如绘制),尝试不使用任何颜色名称。使用哈希颜色(例如“#00AA99”)或 RGB 数值(例如“rgb(0,160,100)”)来指定颜色,以便阻止 IM 加载颜色名称表(它相当大!)。你还可以尝试删除或减少系统“字体”列表定义文件(来自“type.xml”)。或者完全删除这些文件,并通过文件名直接指定字体。基本上减少了额外配置信息的加载,IM 在特定图像处理过程中需要时会读取和初始化这些信息。因此,要么不使用它们,要么减少配置文件的大小和影响。
  • 将 ImageMagick 构建为共享库(默认值)可以极大地减少加载时间。库和编码器模块只有在需要时才会加载,因此动态版本的 IM 不会加载在图像处理过程中不需要使用的任何东西。此外,共享库往往保持可用,因此可能不需要重新加载以进行第二次运行。
  • 如果你将 ImageMagick 作为 Apache 模块的一部分调用,它也会减少启动时间,因为部分将加载一次并保持可用以供多次使用,而不是需要反复重新加载。这在将来使用永久运行的“守护进程”IM 进程时可能会变得更加实用。

从源代码编译 ImageMagick

为 linux 构建 ImageMagick RPM 包,使用 SRPM 包

你不需要 root 权限来构建 RPM 包,但需要 root 权限来安装 RPM 包。我使用它在Fedora Linux 系统下生成和安装 IM,但据报道,它也适用于CentOS 5.4(企业 Redhat)Linux 系统(请参阅更具体的IM 在 CentOS 上的说明)。首先从Linux 源代码 RPM 包获取最新的源代码 RPM 包版本。首先确保你的机器拥有构建所需的所有编译器和工具。

  sudo yum groupinstall "Development Tools"
  sudo yum install rpmdevtool libtool-ltdl-devel
"sudo"是一个以 root 身份运行命令的程序,如果你被允许,否则使用 root shell 并从上面的命令中删除"sudo"部分。
对于像 CentOS 5.5 这样的旧系统,似乎你还需要这些软件包

  sudo yum compat-libstdc++ gcc-c++ gcc-objc++ libstdc++ libstdc++-devel
接下来,你还应该安装 IM 构建所需的库的开发包。获取最常见开发包的简单方法是首先安装 IM 的开发版本,即使我们稍后会构建一个新的版本来替换它。

  sudo yum install ImageMagick-devel
你还应该确保这些软件包及其依赖项(例如 jpeg 和 png 开发库)也已安装
freetype-devel ghostscript-devel libwmf-devel jasper-devel lcms-devel bzip2-devel librsvg2 librsvg2-devel liblpr-1 liblqr-1-devel libtool-ltdl-devel autotrace-devel
"ImageMagick 示例"中的一些示例也可能使用这些可选软件包和库提供的程序,但这些对于构建过程并不需要。
gnuplot autotrace
一般来说,所有这些软件包都是可选的,但如果未安装,则使用这些库的“编码器”和运算符可能不会自动构建。例如,“liblqr”模块是启用液体重新缩放运算符所必需的。现在下载一个 SRPM(源代码 RPM)包,从中构建你的二进制 RPM 包。或者使用...从现有 TAR 或 SVN 下载中构建 SRPM 包。

  rm config.status config.log
  nice ./configure
  rm *.src.rpm
  make srpm
请注意,一旦你拥有 SRPM 包,就可以构建实际的 RPM 包进行安装。

  nice rpmbuild --nodeps --rebuild   ImageMagick*.src.rpm
这将在你的主目录中创建一个子目录“rpmbuild”,它将在其中提取 SRPM 源代码,并构建 IM 的编译后的包 RPM 版本。
在旧版本的 Fedora 和 Redhat 中,这在“/usr/src”中完成,该目录通常仅限于 root 访问。但是,你可以将此目录的拥有者或写入权限设置为你,这样你仍然可以在不需要完全 root 访问权限的情况下进行构建。
现在从构建目录中获取刚刚构建的 RPM 包。这只会获取 ImageMagick Core 和 PerlMagick 软件包,你可能想要获取更多软件包,但这取决于你...

  cp -p ~/rpmbuild/RPMS/*/ImageMagick-[6p]*.i[36]86.rpm .
清理并删除构建区域(包括可能为你创建的区域)...

  rm -rf /var/tmp/rpm-tmp.*  ~/rpmbuild
现在你可以安装你构建的 RPM 包。你需要以 root 身份执行此操作(请参阅上面关于“sudo”命令的说明)...

  sudo rpm -ihv --force --nodeps  ImageMagick-*.i[36]86.rpm
"--nodeps"通常是必要的,因为 Linux 系统上有时存在一些不寻常的依赖项。为了升级现有的安装,我通常会执行以下操作(以 root 身份)。

  sudo rpm -Uhv --force --nodeps  ImageMagick-*.i[36]86.rpm
如果你想更进一步,我建议你查看 IM 网站上的高级 Unix 源代码安装指南
要稍后删除 IM,你可以直接删除软件包,例如(仍然以 root 身份)...

  sudo rpm -e --nodeps  ImageMagick\*

有时我只是想完全清理并清除系统中 IM 的所有痕迹。为此,我首先使用前面的命令从系统中删除实际软件包(下面显示了一个变体)。然后我运行以下删除命令。请注意,我对此不做任何保证,我会在执行这些命令之前仔细检查它们,以确保它们不会删除不该删除的东西。如果它遗漏了什么,或者它删除了一些不该删除的东西,请告诉我,以便我可以更新它。

  rpm -e --nodeps `rpm -q ImageMagick ImageMagick-perl`
  rpm -e --nodeps `rpm -q ImageMagick-devel`
  rm -rf /usr/lib/ImageMagick-*
  rm -rf /usr/lib/lib{Magick,Wand}*
  rm -rf /usr/share/ImageMagick-*
  rm -rf /usr/share/doc/ImageMagick-*
  rm -rf /usr/include/{ImageMagick,Magick++,magick,wand}
  rm -rf /usr/lib/perl5/site_perl/*/i386-linux-thread-multi/Image/Magick*
  rm -rf /usr/lib/perl5/site_perl/*/i386-linux-thread-multi/auto/Image/Magick*
  rm -rf /usr/share/man/man?/*Magick*
  rm -f /usr/lib/pkgconfig/ImageMagick.pc
警告,其他软件包可能需要安装 IM,因此如果你删除了它,我建议你立即更新你的计算机系统,这样它将再次安装为你 Linux 系统提供的原始默认(通常非常旧)版本的 ImageMagick。这通常涉及使用“GUI 软件更新”软件包或命令“yum upgrade”。享受。

在 Ubuntu 上从源代码安装 ImageMagick

要获取构建 ImageMagick 所需的所有开发库,请使用以下命令

  sudo apt-get install imagemagick libmagick++-dev
"Shane" 的一个网页介绍了如何在Ubuntu 8.04 上从源代码安装 ImageMagick。我没有尝试过,但它直接使用“make”将 IM 安装到“/usr/local”中。它不会生成一个安装“DEB”包,这不是一个理想的解决方案。如果有人知道如何在 Ubuntu 上创建“DEB”包,请告诉我。可能可以使用Debian 打包入门

在 MacOSX 上编译

在 MacOSX 上安装 ImageMagick 最简单的方法是使用 MacPorts。但是,以下是对在 MacOSX 上编译的指示。我不知道它是否有效或是否有用,因为我从未使用过它。但请查看 在没有 Fink 或 MacPorts 的情况下安装 ImageMagick在 Snow Leopard 上安装 ImageMagick。以上内容摘自 IM 用户论坛上的讨论

编译 HDRI 版本的 IM

有关编译 HDRI 版本的 IM 的信息,请参阅 IM 主网站上的 在 ImageMagick 中启用 HDRI,以及有关 Windows 和 Ubuntu Linux 的特定信息,请参阅用户论坛上的 傅里叶变换公告讨论

创建个人 ImageMagick

您并不总是拥有对您进行图像处理的机器的超级用户访问权限,而且通常那些拥有访问权限的人也不想更新他们的 ImageMagick 安装。可能是出于包管理问题或兼容性问题。如果您拥有命令行访问权限(例如通过 SSH),那么一切都没有丢失。您可以安装并使用个人版本的 ImageMagick。坏消息是您仍然需要系统管理员安装编译器和开发包(参见 上方),但通常这些已经存在,因此并不总是一个问题。首先决定您想在哪个子目录中安装您的 IM 版本。专用目录是最佳选择,因为它意味着您只需要删除整个目录即可删除您的安装。在我的情况下,我将安装到我的主目录的“apps/im”子目录中。

  export MAGICK_HOME=$HOME/apps/im
现在,要安装个人版本,请下载、解压缩并更改到 ImageMagick 源代码目录。然后将其配置为“未安装”版本。

  rm config.status config.log
  nice ./configure --prefix=$MAGICK_HOME --disable-installed \
          --enable-shared --disable-static --without-modules --with-x \
          --without-perl --without-magick-plus-plus --disable-openmp \
          --with-wmf --with-gslib --with-rsvg --with-xml \
          CFLAGS=-Wextra \
          ;
  nice make clean
  nice make
  nice make install
在上述定义中,“--disable-installed”与“--prefix”非常重要。其他部分禁用了您的个人版本 ImageMagick 中更多可选方面的编译。您可以根据自己的喜好修改它们。现在,要使用您自己安装的版本,而不是正常的系统版本,您只需要设置以下环境变量即可。

  export MAGICK_HOME=$HOME/apps/im
  export PATH="$MAGICK_HOME/bin:$PATH"
  export LD_LIBRARY_PATH="$MAGICK_HOME/lib:$LD_LIBRARY_PATH"
现在,如果我输入

  magick -version
默认情况下,我可以看到您刚刚安装的更新版本的 IM。请注意,对于使用“--disable-installed”选项创建的 Imagemagick,必须设置变量“$MAGICK_HOME”。另外两个环境变量确保我们使用个人版本,而不是可能也安装的任何系统版本。
警告:请勿混合使用上述变量。要么全部定义它们,要么不要以这种方式定义它们。您使用的 IM 可执行文件也必须使用与那些可执行文件一起构建的相同库、编码器和配置文件。混合使用系统版本和个人版本可能会导致分段错误和内存错误。
您可以移动个人 IM 的位置而无需重新编译,但您不仅需要修改上述环境变量,还需要更改(或删除)您个人安装版本的“delegate.xml”文件中使用的“magick display”程序对“show:”委托的硬编码路径。有关 IM 的这方面内容的更多信息,请参阅 委托
为了方便我在系统安装的 IM 和多个个人版本的 IM 之间切换,我通常不会设置上述变量。相反,我会调用一个脚本,该脚本在调用特定版本的 IM 之前设置这些变量。例如,我有一个个人版本的 IM,它是使用 HDRI 编译的,我仅在 ImageMagick 示例中的特定示例中使用它。我通常不想使用此版本,而是更喜欢使用非 HDRI 系统安装版本进行大多数图像处理工作。因此,我在我的个人区域“$HOME/apps/im_hdri”中安装了一个“HDRI”版本的 IM,并创建了一个名为“hdri”的脚本,其中包含...

#!/bin/sh
#
#   hdri imagemagick_command....
#
# Run the HDRI version of imagemagick (or other personal installed IM)
#
# Where is the HDRI version of IM stored
export MAGICK_HOME=$HOME/apps/im_hdri

# Set the other two environment variables
export PATH="$MAGICK_HOME/bin:$PATH"
export LD_LIBRARY_PATH="$MAGICK_HOME/lib:$LD_LIBRARY_PATH"

# Execute the HDRI version of the command
exec "$@"
现在,如果我输入...

  hdri magick -version
[IM Text]
我看到我运行了 HDRI 质量版本的 ImageMagick,但只有在我需要它的时候才会运行。如果我不在上述命令之前加上“hdri”,那么我将运行正常的系统版本的 IM。警告:如果您的个人版本 IM 未被脚本找到,它将静默地恢复为使用系统版本。上述“版本”检查是确保我实际上使用的是个人版本,而不是系统版本的重要测试。您还可以使用“which”检查脚本尝试执行的具体 magick 命令。

  hdri which convert
也就是说,该脚本足够灵活,您实际上不需要运行“magick”,而是可以运行任何命令,例如 ImageMagick Shell 脚本,以便该脚本使用 HDRI magick 而不是正常的系统 convert。

  hdri  some_im_script   image.png   image_result_hdri.png