MagickCore API は、C プログラミング言語と ImageMagick 画像処理ライブラリ間の低レベルインターフェースであり、熟練プログラマーのみに推奨されます。いくつかの不透明な型とアクセサのみを使用する MagickWand C API とは異なり、MagickCore ではほぼ排他的に構造体のメンバーに直接アクセスします。MagickCore の公開メソッドの説明は、こちらにあります。
- ImageMagick 環境の初期化または破棄
- 画像の構成
- 画像の合成
- 画像メソッド
- 画像チャンネルメソッド
- 画像内の色の数を数える
- カラーマップメソッド
- カラースペースメソッド
- 画像の歪み
- 画像レイヤーの処理
- 画像プロファイルの処理
- 画像内の固有の色数を減らす
- 画像ヒストグラム
- 閾値ファジィ c-Means による画像のセグメント化
- 画像のリサイズ
- 画像の変換
- 任意の角度による画像のシアまたは回転
- 画像の強調
- 効果の追加
- モルフォロジー的な侵食、膨張、オープニング、クロージング
- 特殊効果の追加
- 画像の装飾
- 画像属性の取得/設定
- 画像プロパティの取得/設定
- 画像統計の取得
- 画像特徴の取得
- 画像への注釈
- 画像へのペイント
- 画像への描画
- 画像サムネイルの作成
- 離散フーリエ変換 (DFT) の計算
- 画像を再構成された画像と比較
- コンピュータビジョン
- 画像のインタラクティブな表示と編集
- 画像シーケンスのインタラクティブなアニメーション
- 暗号化されたピクセルとの相互変換
- 画像リストの操作
- 画像ビューメソッド
- イメージキャッシュメソッド
- 画像ピクセルの取得または設定
- キャッシュビューの操作
- ピクセルFIFO
- バイナリラージオブジェクトの読み書き
- ロード可能なモジュール
- 画像のメッセージダイジェストの計算
- イメージレジストリ
- 例外の処理
- メモリ割り当て
- リソース消費の監視または制限
- 画像操作の進捗状況の監視
- バージョンと著作権の取得
- MIME メソッド
- 非推奨のメソッド
- エラーと警告コード
MagickCore プログラムを作成したら、次のようにコンパイルします。
cc `MagickCore-config --cflags --cppflags` -O2 -o core core.c `MagickCore-config --ldflags --libs`
ImageMagick がデフォルトのシステムパスにない場合は、PKG_CONFIG_PATH 環境変数を設定します。
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
MagickCore API を使用して開始するためのサンプルプログラム core.c を示します。これは、GIF 画像を読み取り、サムネイルを作成し、PNG 画像形式でディスクに書き込みます。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <MagickCore/MagickCore.h> int main(int argc,char **argv) { ExceptionInfo *exception; Image *image, *images, *resize_image, *thumbnails; ImageInfo *image_info; if (argc != 3) { (void) fprintf(stdout,"Usage: %s image thumbnail\n",argv[0]); exit(0); } /* Initialize the image info structure and read an image. */ MagickCoreGenesis(*argv,MagickTrue); exception=AcquireExceptionInfo(); image_info=CloneImageInfo((ImageInfo *) NULL); (void) strcpy(image_info->filename,argv[1]); images=ReadImage(image_info,exception); if (exception->severity != UndefinedException) CatchException(exception); if (images == (Image *) NULL) exit(1); /* Convert the image to a thumbnail. */ thumbnails=NewImageList(); while ((image=RemoveFirstImageFromList(&images)) != (Image *) NULL) { resize_image=ResizeImage(image,106,80,LanczosFilter,exception); if (resize_image == (Image *) NULL) MagickError(exception->severity,exception->reason,exception->description); (void) AppendImageToList(&thumbnails,resize_image); DestroyImage(image); } /* Write the image thumbnail. */ (void) strcpy(thumbnails->filename,argv[2]); WriteImage(image_info,thumbnails,exception); /* Destroy the image thumbnail and exit. */ thumbnails=DestroyImageList(thumbnails); image_info=DestroyImageInfo(image_info); exception=DestroyExceptionInfo(exception); MagickCoreTerminus(); return(0); }
次に、デュアルまたはクアッドコア処理システムを利用して、同じコントラスト強調を並列に実行してみましょう。 sigmoidal-contrast.c モジュールは、画像を読み取り、シグモイド非線形コントラスト制御を適用し、前のコントラスト強調プログラムと同様に結果をディスクに書き込みますが、現在は並列で処理を行います(ImageMagick が OpenMP サポートでビルドされていると仮定します)。
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <MagickCore/MagickCore.h> static MagickBooleanType SigmoidalContrast(ImageView *contrast_view, const ssize_t y,const int id,void *context) { #define QuantumScale ((MagickRealType) 1.0/(MagickRealType) QuantumRange) #define SigmoidalContrast(x) \ (QuantumRange*(1.0/(1+exp(10.0*(0.5-QuantumScale*x)))-0.0066928509)*1.0092503) RectangleInfo extent; register IndexPacket *indexes; register PixelPacket *pixels; register ssize_t x; extent=GetImageViewExtent(contrast_view); pixels=GetImageViewAuthenticPixels(contrast_view); for (x=0; x < (ssize_t) (extent.width-extent.x); x++) { SetPixelRed(pixels,RoundToQuantum(SigmoidalContrast(GetPixelRed(pixels))); SetPixelGreen(pixels,RoundToQuantum(SigmoidalContrast(GetPixelGreen(pixels))); SetPixelBlue(pixels,RoundToQuantum(SigmoidalContrast(GetPixelBlue(pixels))); SetPixelOpacity(pixels,RoundToQuantum(SigmoidalContrast(GetPixelOpacity(pixels))); pixels++; } indexes=GetImageViewAuthenticIndexes(contrast_view); if (indexes != (IndexPacket *) NULL) for (x=0; x < (ssize_t) (extent.width-extent.x); x++) SetPixelIndex(indexes+x,RoundToQuantum(SigmoidalContrast(GetPixelIndex(indexes+x)))); return(MagickTrue); } int main(int argc,char **argv) { #define ThrowImageException(image) \ { \ \ CatchException(exception); \ if (contrast_image != (Image *) NULL) \ contrast_image=DestroyImage(contrast_image); \ exit(-1); \ } #define ThrowViewException(view) \ { \ char \ *description; \ \ ExceptionType \ severity; \ \ description=GetImageViewException(view,&severity); \ (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); \ description=DestroyString(description); \ exit(-1); \ } ExceptionInfo *exception; Image *contrast_image; ImageInfo *image_info; ImageView *contrast_view; MagickBooleanType status; if (argc != 3) { (void) fprintf(stdout,"Usage: %s image sigmoidal-image\n",argv[0]); exit(0); } /* Read an image. */ MagickCoreGenesis(*argv,MagickTrue); image_info=AcquireImageInfo(); (void) CopyMagickString(image_info->filename,argv[1],MaxTextExtent); exception=AcquireExceptionInfo(); contrast_image=ReadImage(image_info,exception); if (contrast_image == (Image *) NULL) ThrowImageException(contrast_image); /* Sigmoidal non-linearity contrast control. */ contrast_view=NewImageView(contrast_image); if (contrast_view == (ImageView *) NULL) ThrowImageException(contrast_image); status=UpdateImageViewIterator(contrast_view,SigmoidalContrast,(void *) NULL); if (status == MagickFalse) ThrowImageException(contrast_image); contrast_view=DestroyImageView(contrast_view); /* Write the image then destroy it. */ status=WriteImages(image_info,contrast_image,argv[2],exception); if (status == MagickFalse) ThrowImageException(contrast_image); contrast_image=DestroyImage(contrast_image); exception=DestroyExceptionInfo(exception); image_info=DestroyImageInfo(image_info); MagickCoreTerminus(); return(0); }
MagickCoreTerminus() は、ImageMagick ライブラリの関数で、ImageMagick を使用するアプリケーションをシャットダウンするときに、リソースをクリーンアップして解放するために使用されます。この関数は、シャットダウンプロセス中にアプリケーションプロセスのプライマリスレッドで呼び出す必要があります。この関数が、ImageMagick 関数を使用しているすべてのスレッドが終了した後にのみ呼び出されることが重要です。
ImageMagick は、OpenMP (並列プログラミングの方法) を介して内部的にスレッドを使用する場合があります。その結果、MagickCoreTerminus() を呼び出す前に、ImageMagick へのすべての関数呼び出しが完了していることを確認することが重要です。これにより、この終了関数によって破棄されるリソースに OpenMP ワーカー スレッドがアクセスする問題を回避できます。
OpenMP を使用している場合(バージョン 5.0 から)、OpenMP の実装自体がワーカー スレッドの開始と停止を処理し、独自の方法を使用してリソースを割り当てて解放します。つまり、MagickCoreTerminus() を呼び出した後でも、一部の OpenMP リソースとワーカー スレッドが割り当てられたままになっている可能性があります。これに対処するために、関数 omp_pause_resource_all(omp_pause_hard) を呼び出すことができます。この関数は OpenMP バージョン 5.0 で導入され、OpenMP によって割り当てられたすべてのリソース(スレッドやスレッド固有のメモリなど)が解放されるようにします。MagickCoreTerminus() の実行が完了した後にこの関数を呼び出すことをお勧めします。