Magick++ STL Support

Magick++ provides a set of Standard Template Libary (STL ) algorithms for operating across ranges of image frames in a container. It also provides a set of STL unary function objects to apply an operation on image frames in a container via an algorithm which uses unary function objects. A good example of a standard algorithm which is useful for processing containers of image frames is the STL for_each algorithm which invokes a unary function object on a range of container elements.

Magick++ uses a limited set of template argument types. The current template argument types are:

Container
A container having the properties of a Back Insertion Sequence . Sequences support forward iterators and Back Insertion Sequences support the additional abilty to append an element via push_back(). Common compatable container types are the STL < vector > and <list > template containers. This template argument is usually used to represent an output container in which one or more image frames may be appended. Containers like STL <vector > which have a given default capacity may need to have their capacity adjusted via reserve() to a larger capacity in order to support the expected final size . Since Magick++ images are very small, it is likely that the default capacity of STL < vector > is sufficient for most situations.
InputIterator
An input iterator used to express a position in a container. These template arguments are typically used to represent a range of elements with first_ representing the first element to be processed and last_ representing the element to stop at. When processing the entire contents of a container, it is handy to know that STL containers usually provide the begin() and end() methods to return input interators which correspond with the first and last elements, respectively.

The following is an example of how frames from a GIF animation "test_image_anim.gif" may be appended horizontally with the resulting image written to the file 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; 
}

The available Magick++ specific STL algorithms for operating on sequences of image frames are shown in the following table:
 

In addition, we support these yet to be documented methods: combineImages(), evaluateImages(), mergeImageLayers(), optimizeImageLayers(), optimizePlusImageLayers(), and separateImages().


 

Magick++ Unary Function Objects

Magick++ unary function objects inherit from the STL unary_function template class . The STL unary_function template class is of the form
unary_function<Arg, Result>
and expects that derived classes implement a method of the form:
Result operator()( Arg argument_);
which is invoked by algorithms using the function object. In the case of unary function objects defined by Magick++, the invoked function looks like:
void operator()( Image &image_);
with a typical implementation looking similar to:
void operator()( Image &image_ ) 
  {
    image_.contrast( _sharpen );
  }
where contrast is an Image method and _sharpen is an argument stored within the function object by its contructor. Since constructors may be polymorphic, a given function object may have several constructors and selects the appropriate Image method based on the arguments supplied.

In essence, unary function objects (as provided by Magick++) simply provide the means to construct an object which caches arguments for later use by an algorithm designed for use with unary function objects. There is a unary function object corresponding each algorithm provided by the Image class and there is a contructor available compatable with each synonymous method in the Image class.

The unary function objects that Magick++ provides to support manipulating images are shown in the following table:
 

Function objects are available to set attributes on image frames which are equivalent to methods in the Image object. These function objects allow setting an option across a range of image frames using f or_each().

The following code is an example of how the color 'red' may be set to transparent in a GIF animation:

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

The available function objects for setting image attributes are
 


 

Query Image Format Support

Magick++ provides the  coderInfoList() function to support obtaining information about the image formats supported by ImageMagick. Support for image formats in ImageMagick is provided by modules known as "coders". A user-provided container is updated based on a boolean truth-table match. The truth-table supports matching based on whether ImageMagick can read the format, write the format, or supports multiple frames for the format. A wildcard specifier is supported for any "don't care" field. The data obtained via coderInfoList() may be useful for preparing GUI dialog boxes or for deciding which output format to write based on support within the ImageMagick build.

The definition of coderInfoList is:

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 
                      );

The following example shows how to retrieve a list of all of the coders which support reading images and print the coder attributes (all listed formats will be readable):

  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 ++;
   } 
   } 

Obtaining A Color Histogram 

Magick++ provides the colorHistogram template function to retrieve a color histogram from an image. A color histogram provides a count of how many times each color occurs in the image. The histogram is written into a user-provided container, which (for example) could be a <vector> or a <map>.  When a <map> is used, the Color is used as the key so that quick lookups of usage counts for colors may be performed. Writing into a <map> may be slower than writing into a <vector> since the <map> sorts the entries (by color intensity) and checks for uniqueness. Each histogram entry is contained in type std::pair<Magick::Color,unsigned long> with the first member of the pair being a Color, and the second member of the pair being an 'unsigned long'. Use the <pair> "first" member to access the Color and the "second" member to access the number of times the color occurs in the image.

The template function declaration is as follows:

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

The following examples illustrate using both a <map> and a <vector> to retrieve the color histogram, and print out a formatted summary.

Using <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++;
    }

Using <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++;
    }