ImageMagickの例 --
APIとスクリプティング

目次
ImageMagickの例の序文と目次
APIとその他のIM使用方法
セキュリティの問題
より良いImageMagickシェル/PHPスクリプトのためのヒント
なぜ複数の「magick」コマンドを使用するのですか?
IMを高速化する(一般的に)
ソースからのImageMagickのコンパイル
この例が扱うImageMagickのコマンドラインインターフェース(CLI)は、ImageMagick関数の core ライブラリ(MagickCore)を使用して画像を使用、変更、制御できる方法の1つにすぎません。 基本的に「シェル」APIインターフェースです。 多くのプログラミング言語からより直接使用できる、他の多くのアプリケーションプログラミングインターフェース(API)があります。 ImageMagick APIを参照してください。ここでは、IMスクリプトとプログラミングの改善方法、WindowsとUnixスクリプトの違い、他のAPIやプログラミング言語からIMを使用する際の基本について説明します。

APIとその他のIM使用方法

実際の画像処理用のAPI(アプリケーションプログラミングインターフェース)は、実際にはCLIコマンド(「magick」(これはそれ自体が一種のシェルAPIを表します))を使用するよりも高速ではありません。 IMのすべての画像処理には、同じ「コア」ライブラリが使用されます。 したがって、画像の歪みなどの複雑なタスクを実行する場合、シェル「magick」よりもAPIを使用しても、処理の全体的な「速度」にはほとんど違いがありません。 *では、なぜコマンドラインではなくAPIを使用するのでしょうか?*シェルは、常に多くの異なるコマンド(IMの「magick」コマンドだけでなく、シェルにはいくつかの「組み込み」があります)を「フォーク」します。 これらのコマンドは、実行されるたびにロードおよび初期化される必要があります。 また、すべてのIMコマンドは、構成ファイルを再初期化し、コマンドライン引数を解析し、作業中の画像を再読み込みし、多くの場合、結果をディスクに保存する必要があります。 これらすべてに時間がかかるため、処理速度が低下します。 つまり、これらの追加の手順には時間と処理能力がかかるため、頻繁に実行する場合、APIは理にかなっています。 また、APIを使用すると、コマンドラインではできない他の操作を実行できます。
  • APIがすでに実行されている場合、セットアップ時間はほとんど、またはまったくかかりません。
  • メモリに、任意の順序で処理できる多数の画像リストの配列を格納します。 たとえば、数百枚の画像を読み込み、読み込み時に32x32ピクセルのサムネイル画像として作成し、それらをmagickで1ペアずつ比較するプログラムがあります(100枚の画像で9,900回の比較)。 もう1つは、メモリ内の一般的な色で画像をソートすることです!
  • 任意の順序で、多くの異なる画像処理スレッドを実行できます。 次の画像または手順で作業を開始する前に、1つの処理シーケンスを「完了」する必要はありません。 たとえば、ジグソーパズルを解くプログラムを想像してみてください!
  • 画像から情報を取得し、その情報を複雑な方法で使用して、画像処理を何度も再初期化(構成と画像の再読み込み)することなく、画像処理を変更できます。 たとえば、画像のフレーミング要件を計算する前に、画像サイズを取得します。
  • 画像をループして、各画像で非常に異なる処理を実行します。 たとえば、各フレームがわずかに異なる方法で歪められたアニメーションシーケンスを生成します。
  • 画像データへの直接的かつ完全にランダムなアクセス。 たとえば、画像内の「顔」を探す。
しかし、多数の画像や、明確に定義された方法での画像の一般的な処理を含まないほとんどの場合、コマンドラインはほぼ同じ速度です。 ただし、次の方法で多くの時間と再処理を節約できます...
  • 中間画像の高速再読み込みのためにMPC画像保存を利用します。 スクリプトdivide_vertを参照してください。
  • パイプライン(異なるステップに異なるマシンを使用することもあります!)を使用して並列処理を行い、プロセッサの使用率を向上させ、中間画像をディスクに保存することを回避します。 シーケンスの次の(場合によってはオプションの)ステップに画像をパイプするパイプライン化されたスクリプトの例については、enlarge_imageを参照してください。
  • ループを使用して各画像を個別に処理してから、画像結果のストリームを最終的な「すべてをマージ」ステップにパイプします。 これに似たスクリプトがたくさんあります...そのようなスクリプトの1つについては、レイヤー化された画像のプログラムされた配置を参照してください。
もちろん、APIでは、画像へのアクセスを可能にする特別な処理タスクに使用できる、異なり、より高速な手法もあります。 時間を見つければ、そのような手法をコアライブラリにプログラムすることがよくあります。 画像の歪みとさまざまなFX式は、この一例です。

WindowsとDOS

CLI APIを使用したWindowsおよびDOSスクリプトの使用例は、Windowsでの使用法に移動されました。

PHP(「system()」関数からのIMコマンド)

PHPユーザーは、ImageMagickを使用する3つの方法があります。
  • imagick」PECLインターフェース
  • MagicWand」インターフェース
  • 「system()」および「exec()」関数を使用して、CLIの「magick」コマンドを実行します。
IMの例が存在するため、この後者の方法(そして次に検討する最初の方法)は、近年、PHPからIMを使用する最も一般的な方法になっています。 もちろん、場合によっては、これが最良の方法ではない可能性があります(上記を参照)。 その場合は、APIインターフェースを使用できますが、システム管理者がPHP環境で利用できるようにする必要がある場合があります。

シェルコマンドを使用するPHP

この手法を使用する際の具体的な情報の最良の情報源は、IMフォーラムユーザー* Bonzo*と彼のウェブサイトRubbleWebsです。 PHPは、コマンドラインとは異なる環境で、おそらく異なるユーザーとして「magick」を実行することに注意してください。 そのため、コマンドラインで機能するものは、PHP Web駆動型スクリプトで機能させるために少し調整が必要になる場合があります。 以下は、リモートシステムで直接コマンドライン「シェル」アクセスできないと仮定して、ISPのコマンドラインIMインターフェースの初期テストに推奨される手順です。 つまり、実行のためにWebファイルをアップロードすることしかできません。 したがって、最初に行う必要があるのは、システムで「magick」コマンドを見つけ、インストールされているバージョンと、PHPが実行されている環境を確認することです。 Linux Webサービスでは、このPHPスクリプトをISPのWebサーバーにアップロードしてアクセスします...

<?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スクリプトからそのディレクトリに書き込むことができない場合があります。 次の2つのコマンドは、「type」を使用してデフォルトで提供されるコマンドPATHで「magick」が使用可能かどうか、そして使用可能な場合はその場所を示します。 「locate」コマンドは、サーバー(Linuxサーバーであると仮定)に存在するすべての「magick」コマンドを見つけますが、ImageMagick以外の「magick」コマンド、ファイル、およびディレクトリを見つける場合があります。 結果を解釈する必要があります。 次の3つのコマンドは、「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テストスクリプトにリストされているフォントの1つを試すことができます(PHPサーバーに合わせて以下を変更してください)。 たとえば、この時点で利用可能だったSolarisサーバーでは、「Utopia」フォントセットが利用可能であることに気づいたので、そのフォントを使用してラベルを作成しようとしました...

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

シェルから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の文字列連結を使用して行われています。また、後続の行の先頭に余分なスペースが追加され、元のコマンドに存在する他のバックスラッシュが二重になっていることにも注意してください。あるいは、バックスラッシュの代わりにシングルクォートを使用して、これらのオプションを保護することもできます。また、PHPスクリプトで生成される画像を簡単に調整できるように、いくつかのPHP変数を使用して、結果をより適切に制御できるようにしました。ただし、これらのオプションを`magick`に挿入する際には、シェルによるさらなる変更を防ぐためにシングルクォートを使用しました。ただし、挿入された文字列内にシングルクォートがある場合は注意してください!これらのオプションをPHPの入力引数にすることで、Webリクエストから渡された任意の入力テキストの画像を生成できます。また、同じシステムコール文字列内から複数のシェルコマンドを実行することもできます。実際、単一のシステムコールには、必要に応じて完全なシェルスクリプトを含めることができます!そのため、1つのシステムコールでシェルループと複数のコマンド(クリーンアップを含む)を実行できます。多くの人が気づかない可能性のあることです。基本的に、注意すれば、PHPで提供される数学とシェルのスクリプト機能をうまく活用できます。すべて同時に。引用符に注意してください。PHPからImageMagickコマンドを呼び出すさまざまな例については、約4つの異なる手法について説明しているRubble Web, Writing IM code in PHPを参照してください。

追加の引用符に注意してください

通常、PHPのIMコマンドは追加の引用符(通常は二重引用符)で囲まれているため、この追加の引用符レベルの使用を考慮する必要があります。PHPが文字列を実行するとき... PHPは引用符、バックスラッシュ、変数の置換を行い、シェルは引数を分割し、独自の変数と引用符の置換を行います。また、存在する場合は「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コマンドに渡されるすべての入力引数を徹底的にチェックする必要があります。引数が期待どおりであることを確認してください。World Wide Webを扱う場合は、制限が厳しすぎる方が、制限が緩すぎるよりもはるかに優れています。注意すべき一般的な事項には、次のものが含まれます。
  • 引数内のバイナリ文字 - 一般的なクラッカーの手法
  • 引数内の予期しないスペース、タブ、改行、復帰
  • バックスラッシュ(ディレクトリ区切り文字)と「..」パス。また、Windowsではファイル名に「\」と「;」を使用します。
  • 「~*?[]{}<>」を含むファイル展開メタ文字と、ImageMagickに固有の特別な「@」メタ文字。
  • 「$#;」を含むその他のシェルメタ文字と、3つの引用符「'」、「"」、「`」
  • 引数がImageMagickの期待と一致しません。「-list」を使用して、IMが特定のオプションに対してどのようなタイプの引数を理解しているかを確認してください。たとえば、ユーザー入力の「-gravity」オプションには、10種類の異なる設定しかありません。
  • など...
あらゆる種類のWebプログラミング作業では、セキュリティと、ハッカーが特別に細工された引数を使用して呼び出されたコマンドをどのように破壊できるかについての理解が不可欠です。PHPだけでなく、シェルとImageMagickについてもです。IMは、たとえばパスワードファイルを画像に読み込んで返却できるため、特に注意が必要です。繰り返しますが... Webが関係している場合は、予期せぬセキュリティホールを開くよりも、過度に制限する方がはるかに優れています。

ファイルシステムへの書き込み

上記で述べたように、上記の初期手順に従った場合、PHPは一般的にサーバー上で異なる、より制限の厳しいユーザーとして実行されることが確実にわかります。このため、通常はスクリプトを含むディレクトリ(または実際に実行されている場所)に書き込むことはできません。セキュリティ上の理由から、通常はそのディレクトリに書き込みたくありません!PHPにファイルを書き込ませる必要がある場合は、画像(またはデータ)を「/tmp」の一意のファイル名に保存し、とりわけ、正常終了時とエラー発生時の両方で後片付けを行ってください。適切にクリーンアップしないアプリケーションから残された一時ファイルでディスクがいっぱいになる速度は驚くほどです。保存されたファイル(画像)をWebサーバーから見えるようにする必要がある場合は、それらのファイル用に特別な「プログラムによる書き込み」サブディレクトリを作成します。どのように行うべきか。ほとんどのPHPアプリケーションは、データベースバックエンドを使用することで、ファイルシステムへの書き込みを実際に回避しています。つまり、Cookie、トークン、ユーザーデータ、画像などはすべて、(複雑さと規模の順に)SQLite、PostgresSQL、MySQL、Oracleなどのデータベースに書き込まれます。ファイルシステムには何も保存されません。システムプログラマーは通常、アプリケーションのインストール時にPHPアプリケーションをその情報で構成します。画像は通常、同じ、または画像「ブロブ」を検索してクライアントに出力する別のPHPスクリプトによって再現されます。画像はHTML自体に「インライン」画像として送信される場合があります(HTMLインライン画像のデモがある「inline:」形式を参照してください)、または単一の「オールインワン」複数画像として送信されるため、クライアントHTML/JAVAは20個の個別のリクエストではなく1つの画像リクエストのみを行います。最後のポイント。古いデータをクリーンアップする何らかの方法が常に存在する必要があります。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ユーザーフォーラムのディスカッションからのものです... PHPでIMエラー情報を表示するにはどうすればよいですか?。私自身のPHPデバッグエラーログのメモを参照してください。これは、エラーロギングに関するPHPマニュアルPHPエラー処理とロギング、特に例セクションを指しています。

より安全なImageMagickコマンド...

セキュリティ上の理由から、シェルを使用して単一の長い文字列を個別の コマンドと引数に解析することは避けるのが理想的です。自分で行う方が良いでしょう!これは、コマンドへの引数を1つのシェル解析文字列としてではなく、個別の文字列の配列として提供することを意味します。これにより、シェル構文エラーの可能性、シェルに必要な追加の引用符の負担を防ぎ、ハッカーがシェルコマンドを破って独自のコマンドを実行する可能性を防ぎます(非常に悪いことです)。一方、シェルスクリプト、パイプ、ファイルリダイレクトは失われますが、PHPや他のラッパー言語をすでに使用している場合は、通常は大きな損失ではありません。PHPでは、シェルなしでコマンドを直接呼び出すことができる唯一の関数は、pcntl_exec()関数です。これは基本的にシェルを回避し、コマンドを直接呼び出します。ただし、これは真の「execl()」システムコールであり、現在のプロセスを指定されたコマンドに置き換えます。つまり、「fork()」とファイル記述子のリンクを行わず、サブプロセスとして実行するために必要です。そのため、pcntl_exec()は実際には一般的な使用には低レベルすぎ、「シェルなし」コマンドの実装はかなり複雑になる可能性があります。よりシンプルで安全な「シェルを回避する」コマンドコールがPHPインターフェースによってまだ提供されていないことに非常に驚いています。しかし、私は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ブックはオンラインで入手でき、IMagickを使用する例はMikkoのブログにあります。IMagickの唯一の問題は、保守とアップグレードが行われていないため、機能しないか、欠落している関数が多数ある可能性があることです。IMagick v3.xと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の3つの方法すべて)をテストするために上記を使用しました。

複雑なPHPスクリプト...

HTMLとIMAGEの両方を作成および出力する必要がある場合は、個別のHTMLリクエストまたは入力オプションが、同じまたは異なるPHPスクリプトからWebドキュメントに必要なさまざまな部分を作成するように、PHPスクリプトを設計することを検討してください。つまり、トップレベルのPHPスクリプトは、適切な<IMG>タグを含むHTMLを出力でき、適切なオプションを使用して自身(または別のPHPスクリプト)を呼び出して、最初のトップレベルのPHPスクリプトに表示される画像を作成または変更できます。これは、多くのフォトアルバムとグラフ作成PHPスクリプトが行っていることです。すべて、URL呼び出しのGETおよびPATH_INFO拡張機能によって制御されます。IMGタグ内ではPOSTを使用できないことに注意してください。このようにすることで、PHPで生成されたWebページの一時画像を生成、保存、クリーンアップする必要がなくなります。リソースの制限やガベージコレクションなどの問題が山積しているソリューションであり、非常に悪いプログラミング手法です。この手法は、ImageMagickブックの両方で検討されていますが、実際に使用されているImageMagickは少し古くなっています。

Perl Magickスクリプト

PerlMagick APIは、「magick」コマンドを、データベース、多数の画像、あるいはその他の方法では不可能な、より複雑な画像処理も扱うことができるスクリプトに変換する優れた方法です。 最良のヘルプは、PerlMagickの「デモ」スクリプトを参照することです。これはソースにも含まれており、通常はPerlMagickのドキュメント領域にインストールされています。 私のシステムでは、「/usr/share/doc/ImageMagick-perl-*/demo/」にありました。 このディレクトリには、さまざまな画像の読み取り、書き込み、処理に関する簡単な例が多数あります。 また、ほぼすべての一般的な画像処理オプションとその使用方法を一覧表示するスクリプト「demo.pl」も含まれています。 コマンドラインの「magick」コマンドをPerlに変換する際には、いくつかの注意点があります。
  • 最初に覚えておくべきことは、PerlMagickは処理された新しい画像を自動的に削除しないことです。多くの演算子は古い画像から新しい変更された画像を作成しますが、他の演算子は既存の画像を直接変更します。
  • また、多くの演算子は、画像のリスト全体に特定の操作を適用するのではなく、指定したリストの最初の画像にのみ適用します。 つまり、画像シーケンス(Perl配列)自体をループ処理する必要があります。
  • 複数の画像シーケンスを持つことができます。 実際には、コマンドラインの場合のように単一の画像シーケンスで済ませるのではなく、通常はすべての画像をそれぞれ独自の画像シーケンスに読み込みます。
  • また、画像がメモリに読み込まれたら、既存の画像のサイズを簡単に抽出できます。 つまり、コマンドラインで行うように、既存の画像を複製してクリアする必要なく、新しいキャンバスを作成できます。 ただし、画像の複製は画像のメタデータもコピーするため、デジタル写真などの画像のメタデータを追跡することをお勧めします。
  • 特に画像の読み込み時には、主要な処理の後ごとに画像エラー(PerlMagickページに示されているとおり)を確認してください。
コマンドラインをPerlに変換するには、基本的にまったく同じ操作をまったく同じ順序で実行します。 ただし、画像は一般的に削除されず、複数の画像シーケンスが一般的であるため、「magick」コマンドでの括弧の使用や余分な複製操作は通常問題になりません。 スクリプトの変換で最も難しい部分は、通常、コマンドラインオプションをPerlMagick関数呼び出しにマッピングすることです。私が発見した最速の方法は、IMのソースコードを取得し、「MagickWand/mogrify.c」ファイルを見て、問題のある特定のコマンドラインオプションを検索することです。 たとえば、-thresholdオプションの場合は、引用符を含めて"threshold"を検索します。 2つの一致があります。1つはすべてのオプションが見つかったことを確認するためのクイック構文解析用で、2つ目はそのオプションの実際の内部呼び出し用です。 ここで、使用されているライブラリ関数の名前が見つかります。これは通常、Perl関数に直接マッピングされます。 この場合... BilevelImageChannel()

セキュリティ警告

特に、世界中の誰もが実行できるWebベースのPHPスクリプトなど、公共の用途向けにスクリプトを作成する場合、未知の(または既知の)ユーザーから発信された可能性のあるすべての内容を確認することが非常に重要です。 そして、私はすべてを意味します。引数、ファイル名、URL、そして画像もです。 入力引数を確認するまでは、その引数には文字、数字、スペース、句読点、さらには「ヌル」文字や制御文字が含まれている可能性があります。 徹底的にチェックするまでは、疑わしいものとして扱われ、使用しないでください。 Webで制御された入力フォームを使用しているかどうかは関係ありません。 少し知識のある人なら、その入力フォームをまったく使用せずに、独自の引数を使用してPHPを簡単に呼び出すことができます。 彼らがそうしないと思うのは間違いです。ロボットはそこら中にいて、入力フォームを読み取り、独自の「ハッキングされた」引数を作成して、ランダムなスクリプトに侵入しようとしています。

ファイル名に含まれるメタ文字

セキュリティ上の問題として、特に注意すべき点は、スペース、引用符、句読点、制御文字、またはその他のメタ文字を含むファイル名です。IMとシェルの両方がそれらを展開しようとする可能性があります。 問題は、「*?@${&) .jpg」というファイルは、UNIXでは実際には完全に合法なファイル名ですが、そのプログラム(シェルとIMの両方など)がファイル名展開も行う場合、多くのプログラムはそれを処理するのに苦労します。 シェルが「glob」メタ文字展開を実行するのを防いでも、IM自体もこの展開を実行します(DOSの使用のため)。 そのため、そのような文字をすべて禁止する(そしてエラーを生成する)ことは、おそらく賢明なことです。 セキュリティ対策として、ファイル名に未知の文字や ungewöhnliche 文字、つまり文字、数字、または予想されるサフィックス以外の文字が含まれている場合は、エラーを発生させて中止することをお勧めします。 そのようなファイル名をシェルコマンドまたはIMに渡す前に。 許容的で何か悪いことを通すよりも、はるかに制限的で物事を防ぐ方が良いです。

より優れたImageMagickシェル/PHPスクリプトのためのヒント

これらは、他のユーザーが使用するためにIMメーリングリストに送信された寄稿されたシェルスクリプトについて私が行った基本的なスクリプトプログラミングのポイントです。 これらを当初は個人的に作者(匿名のままです)に送信しましたが、彼は感謝していました。 これらはすべてIMに固有のものではありませんが、標準的なプログラミングプラクティスとして、とにかく適用する必要があります。 特に、他の誰かにプログラムまたはスクリプトを使用、参照、および/またはバグ修正してもらう予定がある場合はなおさらです。 これにより、スクリプトがより便利になります。
  • スクリプトとプログラムの先頭に「help」または「doc」を配置します。 これにより、他の人がスクリプトをインストールまたは実行することなく、特定のプログラムの機能を理解しやすくなります。 私自身は、そのような未知のスクリプトをコンパイルまたは実行しようとするのではなく、それが何のためにあるのかについての明確なコメントがないプログラムをしばしば破棄します。 実際、最初のREADMEファイルでさえ、巨大で複雑なプロジェクトが何をするのかさえ書かれていない巨大なプロジェクトを見たことがあります! プログラマーは、ダウンロードしたということは、それが何をするのか知っているはずだと考えているだけです! また、「-?」などの「不正なオプション」は、オプションの概要だけでなく、プログラムの機能の簡単な要約、またはそのようなヘルプを見つける場所を出力するようにしてください。 リモートWebサイトを指すだけではいけません。10年後には消えてしまうかもしれません! スクリプトが独自の「オープニングコメント」を出力する例については、IM scriptsエリアの「jigsaw」スクリプトを参照してください。 Perlは自己文書化にPODを使用できます(Perlの「Pod::Usage」モジュールを参照)。 たとえば、寄稿されたdpx_timecode.plスクリプトを参照してください。最初のサブルーチンに「ヒアドキュメント」としてヘルプを用意することも許容され、ほとんどの言語で機能します。 ただし、そのサブルーチンはスクリプトまたはプログラムの下部または中央ではなく、上部に配置してください。
  • コードをクリーンアップし、古い不要なコードとコメントを削除して、できるだけきれいに整理してください。 簡潔で、簡単なコメント付きのステージにしてください(可能な場合)。 再び「jigsaw」スクリプトを参照してください。
  • 最後に一時ファイルがクリーンアップされていることを確認してください。 ファイルの終了または中断時にそれらを削除するには、「trap」シェルコマンドを使用します。 もちろん、単一の一時ファイルを複数回再利用できるため、特にIM v6 magickコマンドでは、それほど多くは必要ありません。 再び「jigsaw」スクリプトを参照し、「trap」を検索してください。
  • また、誰もがシステムXを使用しているわけではありませんが、あなたにはそう見えるかもしれません。 特定のシステム要件、または問題の修正方法については言及しないでください。 あなたに有効なことが、彼らのシステムと設定にはまったく不適切かもしれません。 彼らはインターネットアクセスを持っていないかもしれません! ImageMagickの「magick」コマンドが見つからなかったと言うだけです。 インストール要件または提案を追加する場合は、別のより広範なドキュメントの一部として追加してください。
  • 使用されているIMのバージョンが十分に高いかどうかを確認するか、下位互換性のある変更を追加してください。 この目的のために、さまざまな特別な機能が追加された時期について、IMの例全体で意図的に「バージョンの警告」ノートを提供しています。 これにより、単一の最小限のバージョンチェックでスクリプトを作成するのが容易になります。 シェルスクリプトでテスト目的で単一のバージョン番号を取得する簡単な方法を次に示します。 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」を生成します。 上記のPHPバージョンは、RubbleWeb、フォントリストのサンプルページから入手できます。 結果の文字列は、単純な数値テストまたは文字列テストを使用してテストして、使用可能な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」は「既知のフォント」リストを返しました。 以降のバージョンでは、代わりに「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」で始まる文字列は8進数として解釈される可能性があります!!! ただし、最初の桁が「0」のままである限り、2つの8進数を比較しても正しくなります。 バージョンチェックの注意と確認をお勧めします。 バージョンをテストする別の方法は、「[」テストの代わりに「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
    
    ただし、「-distort Arc」などの新しいメソッドは、一般的に使用できるようになる前に、IMの開発中に表示される場合があることに注意してください。 そのため、バージョンチェックの方が良い考えかもしれません。 このため、IMの例では、新しい機能が一般的に使用できるほど安定したIMバージョンをメモするようにしています(記号を探してください)。
  • 非常に長い一行は使用しないでください。特に複雑な 'convert' コマンドの場合には。上記で示したように、UNIX では '\'、DOS では '^'、PHP では '.' 文字列連結などの行継続方法を使用して分割してください。しかし、すべて設定や操作を別々の行に配置するという意味ではありません。1行につき1つの主要な操作または段階を実行し、新しい画像を作成し、画像を変更し、他の画像と結合するなどしてください。特定の演算子に必要なすべての操作設定を、その演算子の直前に配置します。各行を単一の処理ステップと考えてください。これにより、行を分離して、個々の処理ステップを読みやすく理解しやすくなります。演算子の分離が明確であるほど、複雑な画像処理を理解しやすくなります。追加の括弧を使用したり、さまざまな段階でインデントを付けたり、大きな処理ブロックの間に空行を追加したりすることで、大規模で長い操作の主要な段階をさらに見やすくすることができます。IM の例では、例を理解しやすくするために、これらの手法を至るところで使用しているので、参考にしてください。最後に、特定のコマンドが何をしているかについての追加のコメントは、他の誰か(あるいは2か月後のあなた自身でさえ)がスクリプトを読み理解する上で大きな違いを生むことがあります。長いコマンドラインにコメントを挿入できないのは残念です!
  • あまり多くの外部プログラムに依存しないようにするか、利用可能な場合にのみ使用してください(可能な代替手段を用意してください)。他の人は、そのプログラムを持っていないか、他のものを使用することを好むでしょう。プログラムの使用がオプションの場合は、ユーザー制御下または見つかった場合は自動的に使用されるように、オプションにしてください。可能な限り、強制的な要件にしないでください。たとえば、 "pngcrush"、"optipng"、"pngnq" を使用して、IM が通常提供するよりも PNG を圧縮することができます(IM は特定ではなく汎用性を重視して設計されています)。また、GIF アニメーション用の LZW 圧縮オプティマイザである "gifsicle"、"intergif" などにも、長所と短所があります。スクリプトの動作に絶対必要な要件にしないでください。実際的な例として、古いバージョンの "gif2anim" は、ImageMagick の "magick identify" を使用して GIF 固有のメタデータを参照するのではなく、パッチが適用されたバージョンの "giftrans" に依存していました。この要件は、ImageMagick の "magick identify" の改善により後で必要なくなったため、スクリプトの使い勝手を良くするために削除しました。ImageMagick 自体には、PostScript および PDF ドキュメントの読み取り用の "ghostscript" や、SVG ベクトル画像の正しい処理用の "librsvg" など、多くのオプションの要件があります。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 を使用しているシェルスクリプトで浮動小数点演算が必要な場合は、'awk' や 'bc' などの他のプログラムに頼るのではなく、IM 自体を使用してその演算を実行できます。これらのプログラムは利用できない場合があります(特に 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:" 入力形式を使用して World Wide Web から読み取ることができます。セキュリティ上の懸念(Web 使用など)がない限り、これらの可能性を制限しないでください。
  • 入力画像の読み取りと複数画像の出力は、一度だけ行ってください。ユーザーがパイプラインファイル名または URL を提供した場合、それらの画像を複数回読み取ろうとしないでください。問題が発生する可能性があります。その画像を複数回参照する必要がある場合は、一時ファイル、複製された画像、または "MPC:" を使用して入力画像のコピーを保存してください。パイプラインからの複数の画像を処理できる場合は、さらに優れています。プログラムの引数が示唆するものとは異なる順序で、または複数回入力画像を処理する必要がある場合に、入力画像を一時ファイルに保存する例については、"jigsaw" スクリプトを再び参照してください。
これらのことは基本的に、あなたのプログラムを使用するユーザーに、あなたが彼らに望むことではなく、彼らが望むことをする自由を与えます。スクリプトが何に使用されるかについて仮定することによって、彼らまたはあなた自身を制限しないでください。追伸:私の主な専門知識は、25年以上の経験を持つ、さまざまなアーキテクチャと「フレーバー」の UNIX、LINUX、およびその他の UNIX ライクシステムにわたる UNIX スクリプトの作成です。上記に関して私が何を言っているのかを知っているはずです。

なぜ複数の "magick" コマンドを使用するのですか?

Willem on Wed, 25 Oct 2006 wrote...
疑問に思っているのですが、あなたの例では、目的の結果を得るために Convert を複数回呼び出しているのを見ることがあります。一般的に、magick を複数回呼び出す必要はないはずです。1回の呼び出しで全てが可能になるはずです(ただし、コマンドはより複雑になります)。この声明に同意しますか?
全く同意します。IM バージョン 6 以前は、IM はコマンドごとに 1 つまたは 2 つの操作しか実行できないように設計されていたため、実際には不可能でした。しかし、IMv7 では、すべての処理を 1 つのコマンドで実行できるはずです。しかし、悲しいことに、それも常に可能とは限りません。私は、いくつかの理由で複数のコマンドを使用します。通常、サンプルページでは、中間画像の結果を表示できるようにすることで、関係する中間処理段階をよりよく示すために、複数のコマンドを使用します。同じサンプルエリアの後半では、プロセスを繰り返しますが、おそらくもう少し複雑な単一のコマンドを使用します。そのため、原則として、はい、単一のコマンドですべての画像処理を実行できます。すべての画像処理手法を 1 つのコマンドに自由に組み合わせることができます。私はいつもこれを自分で行っています。この例外は、情報を抽出して後でその情報を次のコマンドに挿入する必要がある場合です。この例としては、ファジートリム手法があります。これは、画像のぼかしコピーのトリム結果を抽出する必要があります。この結果は、元の画像のトリミングに使用されます。また、サムネイルの角を丸めるの例の更新でもこれを行いました。ここでは、IM 自体を使用して、次のコマンドの画像サイズを使用して描画コマンドを生成しました。ただし、以前にメモリに読み込まれた画像からオプションを直接生成できる提案があります。「'jigsaw'」スクリプト(高度なテクニック、ジグソーパズルピースを参照)などのスクリプトでは、別の理由、つまりオプションの処理のために、複数のコマンドを使用することがよくあります。これにより、ユーザーが提供するさまざまな入力オプションを使用して、画像処理シーケンスに追加のステップを選択できます。そのため、オプションの処理では、通常、処理の各段階に別々のコマンドを使用します。このような場合、一時ファイルは基本的に避けられません。ただし、通常は最大で 1 つまたは 2 つの tymczasowe obrazy が必要であり、各ステップでは画像を同じまたは以前の一時ファイル名に処理して戻し、次のオプションの処理ステップを続行します。たとえば、ソース画像を置き換えて画像を処理します。

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

この場合、MPCファイルを使用すると、画像がメモリからディスクにダンプされ、次のコマンドによって「ページング」されて戻されるため、次の処理ステップで中間ファイルの読み取りをほぼ瞬時に高速化できます。これにより、IM が画像ファイル形式をフォーマットおよび解析する必要がなくなりますが、非圧縮メモリであるため一時ファイルのサイズが大きくなります。一時ファイルを回避するために使用するもう 1 つの方法は、作業画像を 1 つのシェルコマンド(if-then-else-fi または while ループ)から別のシェルコマンドにパイプすることです。これは画像パイプラインとして知られており、多くの例で示されています。この例は、MIFF 画像ストリーミングに示されています。ここでは、複数の画像が次々と同じ出力パイプラインに生成され、次のコマンドによって取得されて最終画像にマージされます。最後に、前の処理ステップの結果に基づいて処理スタイルを変更する必要がある場合があります。たとえば、画像比較では、後の処理ステップで使用するため、または後の段階で画像を処理する方法を変更するために、いくつかの情報を検出する必要があることがよくあります。図や漫画の比較には、実際の写真画像とは大きく異なる比較手法が必要になる場合があります。複数のコマンドの使用が問題になっている場合は、おそらくPerlMagickなどの API インターフェースに移行する時期です。そこでは、複数の画像シーケンスをすべてメモリに保持して、不要なディスク IO を回避できます。

IM の高速化(一般的に)

IM の動作を高速化するには、多くの方法があります。注意すべき最も重要な側面を次に示します。リストを下に進むにつれて、高速化は小さくなるか、IM インストールのより複雑な変更が必要になります。
  • IM Q8(またはカラー値あたり 8 ビット、ピクセルあたり 3 ~ 4 バイト)は、より高いカラー解像度を持つ IM Q16 デフォルトよりもはるかに高速です(3 ~ 4 倍高速)。画像に Q16 が 필요하지 않은 경우、IM を Q8 バージョンに置き換える必要があります。ただし、8 ビットの内部品質のみを使用すると、中間画像の情報が失われるため、画像処理全体に影響を与える可能性があることに注意してください。この反対については、HDRI を参照してください。
  • 可能な限り、単一の画像に必要なすべての処理を1つの"magick"コマンドで行ってください。 これにより、初期化、一時ファイルの作成、コマンド間のパイプライン、さらにはパイプラインやディスクI/Oのための画像ファイル形式へのエンコード/デコードが節約されます。 もちろん、画像サイズ、色、あるいはオプションの処理手順などを含む計算など、オプションの画像処理手順を可能にするために、複数のコマンドを使用する必要がある場合もあります。 IMv7スクリプトはこの点で役立ちます。
  • シェルスクリプトは本質的に遅いです。 解釈され、複数の手順とディスクへの追加のファイル処理が必要です。 もちろん、これは新しいIM v6オプション処理のおかげで改善されており、1つのコマンドで多数の画像処理操作を実行できます。 それでも、単一の"magick"コマンドですべてを実行できることは稀であるため、多くの場合、目的を達成するために複数のコマンドを使用する必要があります。 そのため、perl、ruby、またはPHP magickモジュールのようなAPIは、シェルとIMコマンドラインAPIの両方のすべての解釈部分を削除するため、高速です。 また、IMがフォントと色の定義を読み込む際の初期化手順も削減します。
  • APIはまた、プログラムの存続期間中、すべての画像、あるいは複数の画像リストを保持することもできます(十分なメモリがある限り)。 つまり、コマンドラインで行うように画像をシャッフルしたり、ジャグリングしたりすることなく、作業中の画像を自由に切り替えたり、変更したりできます。 これは、以前の画像処理手順に基づいて追加の計算を行う必要がある場合に特に便利です。
  • GIF画像ファイル形式の書き込みは遅いです。 IMは、画像の色をファイル形式の限られた色に収まるように減らす(量子化する)ために、懸命に作業する必要があります。 それでも、特にGIFアニメーションでは、正しく処理するために追加の作業が必要になることがよくあります。 PNGとJPEGは高速ですが、PNGはサイズが大きくなり、JPEGは品質が低下します。 ただし、実際にはGIF画像は品質の面で最悪です!
  • 背景、オーバーレイ、フレーム、マスクなどの画像を事前に準備してキャッシュしたり、カラー検索テーブル、歪みマップ、テンプレート、マスクなどを事前に生成したりします。 これらのすべてが処理時間に大きな違いをもたらす可能性があります。 事前に何ができるかを考えてください。 事前に生成された画像の大きなライブラリは、必要に応じて画像を作成しようとするよりもはるかに高速です。 中間およびキャッシュされた画像には「MPC:」の使用も参照してください。 これらはディスク上のメモリマップされた画像であり、基本的に読み取り時間はゼロですが、他の用途や他のマシンでは役に立ちません。 これらは、主要な画像処理プロセスの開始時にのみ作成する必要があり、最小限のソフトウェアまたはシステムのアップグレードによって無効になり、おそらくセグメンテーション違反が発生するため、長期間保存しないでください。
  • アルファ合成、またはより単純な評価、単純な数学演算、または他の手法を使用できる場合は、FX、特殊効果画像演算子の使用を避けてください。 これらを使用する必要がある場合は、できるだけ小さい画像、または画像の単一のチャネル(グレースケールを処理する場合)にその使用を制限してみてください。
  • いくつかの小さなぼかしの方が速い場合は、大きなサイズの画像ぼかしの使用を避けてください。 どちらが速いかを確認するために、いくつかのタイミングテストを行ってください。 同じことが、ガウス演算子やシャドウ演算子などの他のモルフォロジーおよび畳み込み演算子にも当てはまります。
  • 小さな領域の複雑な処理には、小さなサブ画像または領域を使用します。 たとえば、マスクと再着色を行う前に、人の目を(領域を使用して)見つけて抽出すると、画像の完全な大きなバージョンを処理するよりも速度が大幅に向上する可能性があります。 差が大きいほど、節約量も大きくなります。
  • 大きな画像、または多数の画像を読み取る場合は、読み取り修飾子を使用して、各画像の読み取り直後にサイズ変更またはトリミングを行う方が、全体的なメモリ要件を削減できます。 JPEGの場合、特別な 'jpeg:size' ライブラリモディファイアを使用して、メモリの割り当てを回避することもできます。 これにより、「ディスクスラッシング」(コンピューターの速度が非常に遅くなる)を防ぎます。 特に、モンタージュディレクトリインデックスやその他の複数画像のコラージュを生成する場合など、多数の大きな画像が関係する場合に有効です。
  • ディスクから処理する必要がある非常に巨大な画像の場合、それらを小さなチャンクで処理する方が良い場合があります。
  • 大きな画像の場合も同様です... Windows 64ビットOSを使用している場合は、64ビットImageMagickディストリビューションを使用してください。 より大きなアドレス空間を使用し、32ビットWindowsよりも大きな画像をメモリに収めることができます。
  • IMはデフォルトで、個々の画像処理操作にマルチスレッドを使用します。 つまり、「コア」が2つ以上あるコンピューターは、一般に単一CPUマシンよりも高速に画像を処理します。 大きな画像の場合、OpenMPマルチスレッド機能は、個々の画像処理操作を完了するためにより多くのCPUを使用するため、明確な速度上の利点をもたらす可能性があります。 IM内では、並列化されるのは個々の画像処理操作のみであることに注意してください。 したがって、節約は、多数の画像を処理する場合ではなく、大きな画像処理で行う方が多くなります(次を参照)。
  • 小さな画像の場合、IMマルチスレッド機能を使用しても大きな利点はありません。 この場合、異なる画像で複数の変換を同時に実行すると、スループットが向上する可能性があります。 これは、複数のPHP Webリクエストが複数の画像「magick」コマンドを起動できる状況でも発生する可能性があります。 これらのいずれの状況でも、CPUの競合によりマルチスレッドを有効にすると非常に有害になる可能性があり、'MAGICK_THREAD_LIMIT' 環境変数を '1' に設定してOpenMPを無効にする方が良いでしょう。 IMフォーラムディスカッションスレッド化は「変換」を遅くするを参照してください。 また、ImageMagickがより適切な時点でCPUの制御をより頻繁に放棄するように、MAGICK_THROTTLEを確認することもできます。
  • 画像に多数の小さな操作(描画など)を実行する場合は、色の名前を使用しないでください。 IMが(かなり大きい)カラーネームテーブルを読み込まないようにするために、「#00AA99」などのハッシュカラー、または「rgb(0,160,100)」などのrgb番号を使用して色を指定してください! また、システムの「フォント」リスト定義ファイル(「type.xml」から)を削除または削減することもできます。 あるいは、これらのファイルを完全に削除し、代わりにファイル名でフォントを直接指定します。 基本的に、IMが必要に応じて特定の画像プロセス用に読み取って初期化する追加の構成情報の読み込みを削減します。 したがって、それらを使用しないか、構成ファイルのサイズと影響を減らしてください。
  • ImageMagickを共有ライブラリ(デフォルト)としてビルドすると、ロード時間を大幅に短縮できます。 ライブラリとコーダーモジュールは必要に応じてのみロードされるため、IMの動的バージョンは、画像処理中に使用する必要のないものはロードしません。 また、共有ライブラリは使用可能なままになる傾向があるため、2回目の実行のためにリロードする必要がない場合があります。
  • Apacheモジュールの一部としてImageMagickを呼び出すと、起動時間も短縮されます。 パーツは一度ロードされて複数回使用できるようになるため、何度もリロードする必要がなくなります。 これは、将来、永続的に実行される「デーモン」IMプロセスでより実用的になる可能性があります。

ソースからのImageMagickのコンパイル

SRPMからのLinux用ImageMagick RPMのビルド

RPMをインストールするにはrootが必要ですが、RPMを実際にビルドするにはrootは必要ありません。 私はこれを*Fedora Linux Systems*にIMを生成してインストールするために使用しますが、*CentOS 5.4 (Enterprise Redhat) Linux Systems* でも動作することが報告されています(より具体的なCentOSのIMに関する注意事項を参照)。 まず、LinuxソースRPMから最新のソースRPMリリースを入手してください。 まず、マシンに必要なすべてのコンパイラとツールが揃っていることを確認してください。

  sudo yum groupinstall "Development Tools"
  sudo yum install rpmdevtool libtool-ltdl-devel
"sudo"は、許可されている場合はrootとしてコマンドを実行するプログラムです。そうでない場合は、rootシェルを使用して、上記から"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」モジュールは、Liquid Rescale Operatorを有効にするために必要です。 SRPMをビルドする既存のTARまたはSVNダウンロードから、バイナリRPMをビルドするSRPM(ソースRPM)パッケージをダウンロードします。 または、次を使用して...から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の古いバージョンでは、これは通常rootのみに制限されている「/usr/src」で行われていました。 ただし、このディレクトリを所有または書き込み可能にすることができるため、ビルドのために完全なrootアクセスを必要とせずに実行できます。
ビルドディレクトリからビルドされたばかりのRPMを取得します。 これはImageMagick CoreとPerlMagickパッケージのみを取得します。 これら2つだけでなく、もっと多くのパッケージを取得することもできますが、それはあなた次第です...

  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システムに存在する unusual な依存関係のために、通常必要です。 既存のインストールをアップグレードするには、通常、(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ユーザーフォーラムでの議論から抜粋したものです。

IMのHDRIバージョンのコンパイル

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
上記の定義で重要なのは、「--prefix」と共に使用される「--disable-installed」です。他の部分は、個人用バージョンの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」を設定する必要があります。他の2つの環境変数は、インストールされている可能性のあるシステムバージョンではなく、個人用バージョンを使用することを保証します。
警告:上記の変数を混在させないでください。すべてを定義するか、この方法で定義しないでください。使用するIM実行ファイルは、それらの実行ファイルでビルドされたのと同じライブラリ、コーダー、および設定ファイルを使用する必要があります。システムバージョンと個人用バージョンを混在させると、セグメンテーション違反やメモリフォールトが発生する可能性があります。
再コンパイルせずに個人用IMの場所を移動できますが、上記の環境変数を変更するだけでなく、「delegate.xml」ファイルの個人用インストールバージョンの「show:」デリゲートで使用される「magick display」プログラムへのハードコードされたパスも変更(または削除)する必要があります。このIMの側面の詳細については、デリゲートを参照してください。
システムインストールバージョンと複数の個人用バージョンのIMを簡単に切り替えられるように、通常は上記の変数をまったく設定しません。代わりに、特定のバージョンのIMを呼び出す前にこれらの変数を設定するスクリプトを呼び出します。たとえば、HDRIでコンパイルされた個人用バージョンのIMがあり、これはImageMagickの例で特定の例にのみ使用します。通常はこのバージョンを使用せず、ほとんどの画像処理にはHDRI以外のシステムインストールバージョンを使用することを好みます。そのため、個人用領域「$HOME/apps/im_hdri」にIMの「HDRI」バージョンをインストールし、「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シェルスクリプトなどの任意のコマンドを実行できるほど柔軟性があるため、そのスクリプトは通常のシステム変換ではなくHDRI magickを使用します。

  hdri  some_im_script   image.png   image_result_hdri.png