Magick++のSTLサポート

Magick++は、コンテナ内の画像フレームの範囲を操作するための標準テンプレートライブラリSTL)アルゴリズムのセットを提供します。また、単項関数オブジェクトを使用してコンテナ内の画像フレームに対して操作を適用するためのSTL単項関数オブジェクトのセットも提供します。画像フレームのコンテナを処理するのに役立つ標準アルゴリズムの良い例として、コンテナ要素の範囲に単項関数オブジェクトを呼び出すSTLのfor_eachアルゴリズムがあります。

Magick++は、テンプレート引数の型を限定的に使用します。現在のテンプレート引数の型は以下のとおりです。

コンテナ
Back Insertion Sequence の特性を持つコンテナ。シーケンスは順方向イテレータをサポートし、Back Insertion Sequenceはpush_back()を介して要素を追加する機能もサポートします。一般的な互換性のあるコンテナ型には、STLの<vector>および<list>テンプレートコンテナがあります。このテンプレート引数は通常、1つ以上の画像フレームを追加できる出力コンテナを表すために使用されます。特定のデフォルトのcapacityを持つSTLの<vector>のようなコンテナでは、予期される最終的なsizeをサポートするために、reserve()を使用してcapacityをより大きな値に調整する必要がある場合があります。Magick++の画像は非常に小さいため、ほとんどの場合、STLの<vector>のデフォルトのcapacityで十分です。
InputIterator
コンテナ内の位置を表すために使用される入力イテレータ。これらのテンプレート引数は、通常、first_が処理される最初の要素を表し、last_が停止する要素を表す要素の範囲を表すために使用されます。コンテナの内容全体を処理する場合、STLコンテナは通常、それぞれ最初の要素と最後の要素に対応する入力イテレータを返すbegin()メソッドとend()メソッドを提供していることを知っておくと便利です。

GIFアニメーションのフレームを水平方向に連結する例を以下に示します。"test_image_anim.gif"を連結した画像をファイルappended_image.miffに書き込みます。

#include <list> 
#include <Magick++.h> 
using namespace std; 
using namespace Magick;

int main(int argc,char **argv) 
{ 
   InitializeMagick(*argv);
   list<Image> imageList; 
   readImages( &imageList, "test_image_anim.gif" );

   Image appended; 
   appendImages( &appended, imageList.begin(), imageList.end() ); 
   appended.write( "appended_image.miff" ); 
   return 0; 
}

画像フレームのシーケンスを操作するための利用可能なMagick++固有のSTLアルゴリズムを次の表に示します。
 

さらに、まだ文書化されていない次のメソッドもサポートしています。combineImages()evaluateImages()mergeImageLayers()optimizeImageLayers()optimizePlusImageLayers()separateImages()


 

Magick++単項関数オブジェクト

Magick++単項関数オブジェクトは、STLのunary_functionテンプレートクラスから継承します。STLのunary_functionテンプレートクラスは次の形式です。
unary_function<Arg, Result>
そして、派生クラスが次の形式のメソッドを実装することを期待しています。
Result operator()( Arg argument_);
これは、関数オブジェクトを使用するアルゴリズムによって呼び出されます。Magick++で定義された単項関数オブジェクトの場合、呼び出される関数は次のようになります。
void operator()( Image &image_);
典型的な実装は次のようになります。
void operator()( Image &image_ ) 
  {
    image_.contrast( _sharpen );
  }
ここで、contrastはImageメソッドであり、_sharpenはコンストラクタによって関数オブジェクト内に格納される引数です。コンストラクタはポリモーフィックであるため、特定の関数オブジェクトには複数のコンストラクタがあり、提供された引数に基づいて適切なImageメソッドを選択します。

本質的に、単項関数オブジェクト(Magick++によって提供される)は、単項関数オブジェクトで使用するために設計されたアルゴリズムによって後で使用する引数をキャッシュするオブジェクトを構築する手段を提供するだけです。Imageクラスによって提供される各アルゴリズムに対応する単項関数オブジェクトがあり、Imageクラスの各同義メソッドと互換性のあるコンストラクタがあります。

Magick++が画像の操作をサポートするために提供する単項関数オブジェクトを次の表に示します。
 

関数オブジェクトは、Imageオブジェクトのメソッドと同等の画像フレームに属性を設定するために使用できます。これらの関数オブジェクトを使用すると、`for_each()`を使用して複数の画像フレームにオプションを設定できます。for_each().

次のコードは、GIFアニメーションで色「赤」を透明にする方法の例です。

list<image> images; 
readImages( &images, "animation.gif" ); 
for_each ( images.begin(), images.end(), transparentImage( "red" )  ); 
writeImages( images.begin(), images.end(), "animation.gif" );

画像属性を設定するための利用可能な関数オブジェクトは次のとおりです。
 


 

画像フォーマットのサポートの照会

Magick++は、 coderInfoList() 関数を提供して、ImageMagickでサポートされている画像フォーマットに関する情報の取得をサポートしています。ImageMagickの画像フォーマットのサポートは、「コーダー」と呼ばれるモジュールによって提供されます。ユーザーが提供したコンテナは、ブール真理値表の一致に基づいて更新されます。真理値表は、ImageMagickがフォーマットを読み取れるか、書き込めるか、またはフォーマットに対して複数のフレームをサポートしているかどうかに基づいて一致させることをサポートします。ワイルドカード指定子は、任意の「気にしない」フィールドでサポートされています。coderInfoList() を介して取得されたデータは、GUIダイアログボックスの準備や、ImageMagickビルド内のサポートに基づいて書き込む出力形式を決定するのに役立つ可能性があります。

coderInfoListの定義は次のとおりです。

class CoderInfo 
  { 
  public:

    enum MatchType { 
      AnyMatch,  // match any coder 
      TrueMatch, // match coder if true 
      FalseMatch // match coder if false 
    };

    [ remaining CoderInfo methods ]

   }

  template <class Container > 
  void coderInfoList( Container *container_, 
                      CoderInfo::MatchType isReadable_   = CoderInfo::AnyMatch, 
                      CoderInfo::MatchType isWritable_   = CoderInfo::AnyMatch, 
                      CoderInfo::MatchType isMultiFrame_ = CoderInfo::AnyMatch 
                      );

次の例は、画像の読み取りをサポートするすべてのコーダーのリストを取得し、コーダー属性を出力する方法を示しています(リストされているすべてのフォーマットは読み取り可能です)。

  list<CoderInfo> coderList; 
  coderInfoList( &coderList,           // Reference to output list 
                 CoderInfo::TrueMatch, // Match readable formats 
                 CoderInfo::AnyMatch,  // Don't care about writable formats 
                 CoderInfo::AnyMatch); // Don't care about multi-frame support 
  list<CoderInfo>::iterator entry = coderList.begin(); 
  while( entry != coderList.end() ) 
  { 
    cout << entry->name() << ": (" << entry->description() << ") : "; 
    cout << "Readable = "; 
    if ( entry->isReadable() ) 
      cout << "true"; 
    else 
      cout << "false"; 
    cout << ", "; 
    cout << "Writable = "; 
    if ( entry->isWritable() ) 
      cout << "true"; 
    else 
      cout << "false"; 
    cout << ", "; 
    cout << "Multiframe = "; 
    if ( entry->isMultiframe() ) 
      cout << "true"; 
    else 
      cout << "false"; 
    cout << endl;
    entry ++;
   } 
} 

カラーヒストグラムの取得

Magick++は、colorHistogram テンプレート関数を提供して、画像からカラーヒストグラムを取得します。カラーヒストグラムは、各色が画像に何回出現するかを示すカウントを提供します。ヒストグラムは、ユーザーが提供したコンテナ(例:<vector>または<map>)に書き込まれます。<map>が使用されると、Colorがキーとして使用されるため、色の使用回数を迅速に検索できます。<map>への書き込みは、<map>がエントリ(色強度で)をソートし、一意性を確認するため、<vector>への書き込みよりも遅くなる可能性があります。各ヒストグラムエントリは、std::pair<Magick::Color,unsigned long>型に含まれ、ペアの最初のメンバーはColor、ペアの2番目のメンバーはunsigned longです。<pair>の "first" メンバーを使用してColorにアクセスし、"second" メンバーを使用して画像の色が出現する回数をアクセスします。

テンプレート関数の宣言は次のとおりです。

template <class Container >
void colorHistogram( Container *histogram_, const Image image)

次の例は、<map><vector>の両方を使用してカラーヒストグラムを取得し、フォーマットされた概要を出力する方法を示しています。

<map>の使用
   

  Image image("image.miff");
  map<Color,unsigned long> histogram;
  colorHistogram( &histogram, image );
  std::map<Color,unsigned long>::const_iterator p=histogram.begin();
  while (p != histogram.end())
    {
      cout << setw(10) << (int)p->second << ": ("
           << setw(quantum_width) << (int)p->first.redQuantum() << ","
           << setw(quantum_width) << (int)p->first.greenQuantum() << ","
           << setw(quantum_width) << (int)p->first.blueQuantum() << ")"
           << endl;
       p++;
    }

<vector>の使用
   
  Image image("image.miff");
  std::vector<std::pair<Color,unsigned long> > histogram;
  colorHistogram( &histogram, image );
  std::vector<std::pair<Color,unsigned long> >::const_iterator p=histogram.begin();
  while (p != histogram.end())
    {
      cout << setw(10) << (int)p->second << ": ("
           << setw(quantum_width) << (int)p->first.redQuantum() << ","
           << setw(quantum_width) << (int)p->first.greenQuantum() << ","
           << setw(quantum_width) << (int)p->first.blueQuantum() << ")"
           << endl;
      p++;
    }