Magick++ STL 支援

Magick++ 提供了一組 標準樣板庫 (STL ) 演算法,用於操作容器中的影像幀範圍。它還提供了一組 STL 單元函數物件,用於通過使用單元函數物件的演算法對容器中的影像幀應用操作。一個很好的標準演算法範例是 STL for_each 演算法,它會在容器元素範圍上叫用單元函數物件,這對於處理影像幀容器非常有用。

Magick++ 使用一組有限的樣板引數類型。目前的樣板引數類型為

容器
具有 後端插入序列 特性的容器。序列支援正向迭代器,而後端插入序列支援通過 push_back() 附加元素的額外能力。常見的相容容器類型是 STL < vector > 和 <list > 樣板容器。這個樣板引數通常用於表示一個輸出容器,其中可以附加一個或多個影像幀。像 STL <vector > 這樣具有給定預設「容量」的容器,可能需要通過 reserve() 將其「容量」調整為更大的「容量」,以便支援預期的最終「大小」。由於 Magick++ 影像非常小,因此 STL < vector > 的預設容量很可能足以應付大多數情況。
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 是一個圖像方法,_sharpen 是由其構造函數存儲在函數對象中的一個參數。由於構造函數可能是多態的,因此給定的函數對象可能有多個構造函數,並根據提供的參數選擇適當的圖像方法。

本質上,單參數函數對象(由 Magick++ 提供)僅提供建構對象的方法,該對象會快取參數,供稍後由設計用於單參數函數對象的演算法使用。 Image 類別提供的每個演算法都對應一個單參數函數對象,並且可以使用與 Image 類別中每個同義方法相容的建構函數。

下表顯示了 Magick++ 為支援影像操作而提供的單參數函數對象
 

函數對象可用於在圖像幀上設置屬性,這些屬性等效於 Image 對象中的方法。這些函數對象允許使用 f 在一系列圖像幀上設置選項or_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> 可能比寫入 <vector> 慢,因為 <map> 會對項目進行排序(依顏色強度)並檢查唯一性。每個直方圖項目都包含在類型 std::pair<Magick::Color,unsigned long> 中,其中配對的第一個成員是 Color,配對的第二個成員是「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++;
    }