Magick++ STL 支持

Magick++ 提供了一组用于操作容器中图像帧范围的 标准模板库 (STL ) 算法。它还提供了一组 STL 一元函数对象,用于通过使用一元函数对象的算法对容器中的图像帧应用操作。一个很好的例子是用于处理图像帧容器的标准算法,即 STL 的 for_each 算法,该算法对容器元素范围调用一元函数对象。

Magick++ 使用有限的模板参数类型。当前的模板参数类型是

容器
具有 后插入序列 属性的容器。序列支持正向迭代器,后插入序列支持通过 push_back() 追加元素的附加功能。常见的兼容容器类型是 STL 的 < vector > 和 <list > 模板容器。此模板参数通常用于表示一个输出容器,其中可能追加一个或多个图像帧。像 STL <vector > 这样的容器,其具有给定的默认 容量,可能需要通过 reserve() 将其 容量调整到更大的 容量,以支持预期的最终 大小。由于 Magick++ 图像非常小,因此 STL < vector > 的默认容量可能足以满足大多数情况。
输入迭代器
用于表示容器中位置的输入迭代器。这些模板参数通常用于表示一组元素,其中 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 对象中的方法。这些函数对象允许使用 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++;
    }