/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *
 * This file is part of NMM. 
 * 
 * NMM is free software; you can redistribute it and/or modify it    
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; only version 2 of the License.      
 * 
 * NMM is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 
 * License for more details.  
 * 
 * You should have received a copy of the GNU General Public License 
 * along with NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef NMM_MAGICKMANIPULATIONNODE_HPP
#define NMM_MAGICKMANIPULATIONNODE_HPP

#include <list>
#include <Magick++.h>

//#include "nmm/NMM.hpp"
#include "nmm/multimedia/GenericProcessorNode.hpp"

#include "IMagickManipulationNodeImpl.hpp"
#include "Manipulators.hpp"

namespace NMM {
  //! Supports most of the image manipulation methods (sixty) from ImageMagick. The Node can perform multiple manipulations by storing a list of manipulators.
  class MagickManipulationNode : public GenericProcessorNode,
				 public IMagickManipulationNodeImpl
  {
  public:
    //! The main constructor.
    MagickManipulationNode(const char* = "MagickManipulationNode");
    
    //! The destructor.
    virtual ~MagickManipulationNode();
    
    //! The doInit method from Node.
    virtual Result doInit();

    //! The doInitOutput method from Node.
    virtual Result doInitOutput();

    //! The processBuffer method from GenericNode.
    virtual Message* processBuffer(Buffer* buffer);

    //! Clears the internal list of manipulators.
    void clearManipulators();

    //! Sets the color that should be used when applying the 'border' manipulator.
    virtual void setBorderColor(const nmm_double& r, const nmm_double& g, const nmm_double& b);

    // The image manipulation methods.
    virtual void adaptiveThreshold(const nmm_uint32& width, const nmm_uint32& height, const nmm_uint32& offset = 0);
    virtual void addNoise(const string& noise_type);
    virtual void annotate(const string& text, const string& bounding_area, const string& gravity, const nmm_double& degrees);
    virtual void blur(const nmm_double& radius = 1, const nmm_double& sigma = 0.5);
    virtual void border(const string& geometry = "6x6+0+0");
    virtual void channel(const string& layer);
    virtual void charcoal(const nmm_double& radius = 1, const nmm_double& sigma = 0.5);
    virtual void chop(const string& geometry);
    virtual void colorize(const nmm_uint32& opacity_red, const nmm_uint32& opacity_green, const nmm_uint32& opacity_blue, const nmm_double& pen_color_r, const nmm_double& pen_color_g, const nmm_double& pen_color_b);
    virtual void comment(const string& comment);
    virtual void contrast(const nmm_uint32& sharpen);
    virtual void crop(const string& geometry);
    virtual void cycleColormap(const nmm_int32& amount);
    virtual void despeckle();
    virtual void edge(const nmm_uint32& radius = 0.0);
    virtual void emboss(const nmm_double& radius = 1, const nmm_double& sigma = 0.5);
    virtual void enhance();
    virtual void equalize();
    virtual void erase();
    virtual void flip();
    virtual void floodFillColor(const nmm_uint32& x, const nmm_uint32& y, const nmm_double& fill_color_r, const nmm_double& fill_color_g, const nmm_double& fill_color_b);
    virtual void floodFillOpacity(const nmm_int64& x, const nmm_int64& y, const nmm_uint32& opacity, const string& method);
    virtual void flop();
    virtual void frame(const nmm_uint32& width, const nmm_uint32& height, const nmm_int32& x, const nmm_int32& y, const nmm_int32& innerBevel = 0, const nmm_int32& outerBevel = 0);
    virtual void gamma(const nmm_double& gamma_red, const nmm_double& gamma_green, const nmm_double& gamma_blue);
    virtual void gaussianBlur(const nmm_double& width, const nmm_double& sigma);
    virtual void implode(const nmm_double& factor);
    virtual void label(const string& name);
    virtual void magnify();
    virtual void matteFloodfill(const nmm_double& target_r, const nmm_double& target_g, const nmm_double& target_b, const nmm_uint32& opacity, const nmm_int32& x, const nmm_int32& y, const string& method);
    virtual void medianFilter(const nmm_double& radius = 0.0);
    virtual void minify();
    virtual void modulate(const nmm_double& brightness, const nmm_double& saturation, const nmm_double& hue);
    virtual void negate();
    virtual void normalize();
    virtual void oilPaint(const nmm_uint32& radius = 3);
    virtual void opacity(const nmm_uint32& opacity);
    virtual void opaque(const nmm_double& opaque_color_r, const nmm_double& opaque_color_g, const nmm_double& opaque_color_b, const nmm_double& pen_color_r, const nmm_double& pen_color_g, const nmm_double& pen_color_b);
    virtual void quantize(const bool& measureError = false);
    virtual void raise(const string& geometry, const bool& raisedFlag = false);
    virtual void reduceNoise(const nmm_uint32& order);
    virtual void roll(const nmm_int32& columns, const nmm_int32& rows);
    virtual void rotate(const nmm_double& degrees);
    virtual void sample(const string& geometry);
    virtual void scale(const string& geometry);
    virtual void segment(const nmm_double& cluster_threshold = 1.0, const nmm_double& smoothing_threshold = 1.5);
    virtual void shade(const nmm_double& azimuth = 30, const nmm_double& elevation = 30, const bool& color_shading = false);
    virtual void sharpen(const nmm_double& radius = 1, const nmm_double& sigma = 0.5);
    virtual void shave(const string& geometry);
    virtual void shear(const nmm_double& x_shear_angle, const nmm_double& y_shear_angle);
    virtual void solarize(const nmm_double& factor = 50.0);
    virtual void spread(const nmm_uint32& amount = 3);
    virtual void swirl(const nmm_double& degrees);
    virtual void threshold(const nmm_double& threshold);
    virtual void transform(const string& image_geometry, const string& crop_geometry);
    virtual void transparent(const nmm_double& color_r, const nmm_double& color_g, const nmm_double& color_b);
    virtual void trim();
    virtual void unsharpmask(const nmm_double& radius, const nmm_double& sigma, const nmm_double& amount, const nmm_double& threshold);
    virtual void wave(const nmm_double& amplitude = 25.0, const nmm_double& wavelength = 150.0);
    virtual void zoom(const string& geometry);

  private:
    // Internal variables
    pair<int, int> image_resolution;       //!< The image resolution.
    pair<int, int> new_image_resolution;   //!< The new image resolution.
    int bit_per_pixel;                     //!< The number of bits per pixel.
    double border_r;                       //!< The red border color component.
    double border_g;                       //!< The green border color component.
    double border_b;                       //!< The blue border color component.
    list<Manipulator*> manipulators;       //!< The manipulator list.
  };
}

#endif

