/*
 * class Image
 *
 * $Date$
 * $Revision$
 *
 */

#ifndef IMAGE_HH__
#define IMAGE_HH__

#include "WImage/ColumnVector.hh"
#include "WImage/RowVector.hh"
#include "WImage/FullVector.hh"
#ifndef _WIN32_WCE
#include "WImage/GreymapReader.hh"
#include "WImage/GreymapWriter.hh"
#endif
#include "WImage/FileName.hh"

/**
 * @addtogroup WImage
 * @{ */

class Image;

/**
 * An abstract functor for filling empty regions when resizing images.
 */
/* abstract */
class ResizeFillFunc {
public:
  /**
   * Destructor, does nothing.
   */
  virtual ~ResizeFillFunc (void) {}
  /**
   * Calculate the falue for an otherwise empty position.
   * @param scaled
   * the scaled image (yet to fill with values)
   * @param factor
   * the factor
   * @param y
   * the row in the image
   * @param x
   * the column in the image
   * @param newRows
   * the number of rows in the scaled image
   * @param newCols
   * the number of columns in the scaled image
   * @param yOffset
   * the empty region to the image's top (if any)
   * @param xOffset
   * the empty region to the image's left (if any)
   */
  virtual coeff operator() (const Image &scaled, double factor, int y, int x,
			    int newY, int newX, int yOffset, int xOffset) = 0;
};

/**
 * Enumeration on built-in extension functions (implementations of the
 * ResizeFillFunc type above).
 */
enum ExtendFunc { ef_mirror, ef_outerBorder };

/**
 * An image (abstract). A (grey-scale) more-than-one-dimensional image.
 */
/*abstract*/
class
Image
{
public:

  /** Constructor. Only sets standard values. */
  Image (void);
  /** Destructor. Does nothing. */
  virtual ~Image (void) {}

  /** Return the number of rows.
   * @return
   * the number of rows */
  inline int rows (void) const { return m_ysize; }
  /** Return the number of columns.
   * @return
   * the number of columns */
  inline int cols (void) const { return m_xsize; }
  /** Return the overall size.
   * @return
   * the overall size */
  inline int size (void) const { return m_xysize; }

  /** Return a column reference. Returns a pseudo-vector that provides
   * a reference to one column of the image.
   * @param x
   * The number of the column to be returned
   * @return
   * the column reference */
  inline ColumnVector &col (int x = 0) { m_acol->go (x); return *m_acol; }
  /** Return a row reference. Returns a pseudo-vector that provides
   * a reference to one row of the image.
   * @param y
   * The number of the row to be returned
   * @return
   * the row reference */
  inline RowVector &row (int y = 0) { m_arow->go (y); return *m_arow; }

  /** Return a full reference. Returns a pseudo-vector that provides
   * a reference to the image as a big vector.
   * @param xy
   * The position where to start
   * @return
   * the full reference */
  inline FullVector &full (int xy = 0) { m_afull->go (xy); return *m_afull; }

  /** Get a value. Returns the value at row {\em y} and col {\em x}.
   * @param y
   * the row
   * @param x
   * the col
   * @return
   * the value */
  virtual coeff at (int y, int x) const = 0;
  /** Get a value. Returns the value at absolute position {\em abs}.
   * @param abs
   * the position
   * @return
   * the value */
  virtual coeff at (int abs) const = 0;
  /** Set a value. Sets the value at row {\em y} and col {\em x}.
   * @param y
   * the row
   * @param x
   * the col
   * @param val
   * the new value
   * @return
   * the value */
  virtual void to (int y, int x, coeff val) = 0;
  /** Set a value. Sets the value at absolute position {\em abs}.
   * @param abs
   * the position
   * @param val
   * the new value */
  virtual void to (int abs, coeff val) = 0;

  /** Return the absolute offset of a position.
   * @param y
   * the position's row
   * @param x
   * the position's col
   * @return
   * the absolute offset */
  virtual int abs (int y, int x) const = 0;

  /** Rough comparison. See if two images are similar according to a given
   * {\em epsilon} (important for floating-point comparisons).
   * @param img
   * the other {\em Image} object
   * @param epsilon
   * the epsilon
   * @return
   * if both are identical: {\em true}, else {\em false} */
  virtual bool epsilons (Image &img, coeff epsilon) const = 0;
  /** Rough comparison. See if an image value is equal to some value according
   * to a given {\em epsilon} (important for floating-point comparisons).
   * @param y
   * the row
   * @param x
   * the col
   * @param value
   * the value to compare to
   * @param epsilon
   * the epsilon
   * @return
   * if both are identical: {\em true}, else {\em false} */
  bool epsilonsAt (int y, int x, coeff value, coeff epsilon) const;
  /** Rough comparison. See if an image value is equal to some value according
   * to a given {\em epsilon} (important for floating-point comparisons).
   * @param abs
   * the absolute position
   * @param value
   * the value to compare to
   * @param epsilon
   * the epsilon
   * @return
   * if both are identical: {\em true}, else {\em false} */
  bool epsilonsAt (int abs, coeff value, coeff epsilon) const;
  /** Compares two images. Return {\em true} if both are equal.
   * @param img
   * The other {\em Image} object
   * @return
   * if equals: {\em true}, else {\em false} */
  virtual bool equals (Image &img) const = 0;

  /** Computes the inner product between this and another image.
   * Both images have to have identical dimensions.
   * @exception invalid_argument
   * The images don't have identical dimensions
   * @param img
   * The other {\em Image} object
   * @return
   * the inner product */
  virtual double iproduct (Image &img) const;

  /** Normalize coefficients.
   * @param factor
   * the normalization factor */
  virtual void normalize (coeff factor);

  /** Unnormalize coefficients.
   * @param factor
   * the unnormalization factor */
  virtual void unnormalize (coeff factor);

  /** Perform a gamma correction. Since this is normally only defined for the
   * spatial domain (the pixels need to be normalized) the normalization factor
   * is set to 255 by default, if values are found in the image outside the
   * specified [0..norm] range, the range will be increased.
   * If the range is increased a new normalization factor is
   * automatically calculated as the difference between the image's maximum
   * (if more than norm) and minimum (if less than 0) coefficient value.
   * @param factor
   * the gamma factor (0..1.0)
   * @param ysize
   * the horizontal size of the region to process
   * @param xsize
   * the vertical size of the region to process
   * @param yoffs
   * the horizontal offset of the region to process
   * @param xoffs
   * the vertical offset of the region to process
   * @param norm
   * the normalization factor ( default = 255 )*/
  virtual void gammaCorrection (double factor, int yoffs = 0, int xoffs = 0,
                                int ysize = -1, int xsize = -1,
				int norm = 255);

  /** Does a automatic gamma correction. This function breaks the image up into
   *  smaller matrices and then calculates their averages. The highest and
   *  lowest average is then used to calculate a gamma value which is used
   *  to a parameter in a call to gammaCorrection().
   *  @note
   *  If the image can not be split into the required sub-areas without a
   *  remainder the nearest solution (down) is used.
   *  @param rows
   *  Split image horizontly into subsections
   *  @param columns
   *  Split image vertically into subsections
   *  @param yoffs
   *  Vertical offset
   *  @param xoffs
   *  Horizontal offset
   *  @param ysize
   *  Vertical size
   *  @param xsize
   *  Horizontal size
   *  @param norm
   *  the normalization factor ( default = 255 )
   *  @return
   *  the gamma value - (use it to undo operation if needed) */
  double gammaCorrectionAuto (int rows, int columns, int yoffs = 0,
			      int xoffs = 0, int ysize = -1,int xsize = -1,
			      int norm = 255);

  /** Perform a histogram equalisation.
   * The operation performs a floating-point to int quantisation and uses
   * a given color range if 0..255 is not desired. Explicit values for the
   * color range can be necessary e.g. for Wavelet-decomposed images; for
   * example for Haar LL Level 1 a good choice would be 0..1023 and -512..511
   * for Haar non LL Level 1.
   * Code provided by Johan Ehlers.
   * @warning
   * Use unnormalised coefficients else the operation has un-determinable
   * results.
   * @param ysize
   * the horizontal size of the region to process
   * @param xsize
   * the vertical size of the region to process
   * @param yoffs
   * the horizontal offset of the region to process
   * @param xoffs
   * the vertical offset of the region to process
   * @param startH
   * the start value for range of histogram default = 0
   * @param endH
   * the end value for the range of the histogram default = 255*/
  virtual void histEqualization (int yoffs = 0, int xoffs = 0,
				 int ysize = -1, int xsize = -1,
				 int startH = 0, int endH = 255);

  /** Do an intelligent kind of beautification considering previous
   * transform steps. The original data will be overwritten, so this
   * should only be used on clones or if the image is not going to be
   * transformed afterwise. One region inside the image could be the
   * low-pass subband and should thus be handled separately. If that is
   * desired, the {\em ysize} and {\em xsize} parameters should be set
   * to nonzero values.
   * @param yoffs
   * the horizontal offset of the region that should be handled separately
   * @param xoffs
   * the vertical offset of the region that should be handled separately
   * @param ysize
   * the horizontal size of the region that should be handled separately
   * @param xsize
   * the vertical size of the region that should be handled separately */
  virtual void beautify (int yoffs = 0, int xoffs = 0,
                         int ysize = 0, int xsize = 0);

  /** Do a dumb kind of beautification by just truncating values to
   * their possible maxima depending on the image format or whatever.
   * The original data will be overwritten, so this should only be
   * used on clones or if the original data is not needed anymore.
   * @param min
   * the minimum allowed value
   * @param max
   * the maximum allowed value */
  virtual void truncate (coeff min = 0, coeff max = 255);

  /** First truncate the values to the [0..255] range, and then round
   * them to integer numbers. */
  virtual void pixelize (void);

  /** Adjust the coefficients to make them pixelizable. */
  void valadjust (void);

#ifndef _WIN32_WCE
  /** Read an image (abstract). Reads an image from a file guessing the
   * file type from the file name's extension.
   * @param fname
   * the file name, if {\em NULL}, then {\em stdin}
   * @param rawy
   * the number of rows (only needed for RAW format)
   * @param rawx
   * the number of cols (only needed for RAW format) */
  virtual void read (char const *fname, int rawy = 0, int rawx = 0) = 0;
  /** Read an image (abstract). Reads an image from a file using the
   * specified file type.
   * @param fname
   * the file name, if {\em NULL}, then {\em stdin}
   * @param ftype
   * the file type (image format)
   * @param rawy
   * the number of rows (only needed for RAW format)
   * @param rawx
   * the number of cols (only needed for RAW format) */
  virtual void read (char const *fname, filetype ftype,
                     int rawy = 0, int rawx = 0) = 0;

  /** Write an image (abstract). Writes an image to a file guessing the
   * file type from the file name's extension.
   * @param fname
   * the file name, if {\em NULL}, then {\em stdout}
   * @param beautify
   * beautify images that have not had more analysis than synthesis steps? */
  virtual void write (char const *fname, bool beautify = false) = 0;
  /** Write an image (abstract). Writes an image to a file using the
   * specified file type.
   * @param ftype
   * the file type
   * @param fname
   * the file name, if {\em NULL}, then {\em stdout}
   * @param beautify
   * beautify images that have not had more analysis than synthesis steps? */
  virtual void write (char const *fname, filetype ftype,
                      bool beautify = false) = 0;
#endif

  /** Import an image. The values will be copied.
   * @param rows the number of image rows (logical)
   * @param cols the number of image cols (logical)
   * @param buf the buffer holding the image coefficients (consists of
   *  rows * cols elements) */
  virtual void importCoeffs (int rows, int cols, coeff *buf);

  /** Exports an image.
   * @return a new buffer holding the image coefficients (consists of
   *  rows * cols elements) */
  virtual coeff * exportCoeffs (void);

  /** Import a raw image. The values will be copied.
   * @param rows the number of image rows (logical)
   * @param cols the number of image cols (logical)
   * @param buf the buffer holding the image pixels (consists of
   *  rows * cols elements) */
  virtual void importPixels (int rows, int cols, pixel *buf);

  /** Exports a raw image. Values exceeding the 0..255 range will be
   * truncated.
   * @return a new buffer holding the image pixels (consists of
   *  rows * cols elements) */
  virtual pixel * exportPixels (void) const;

  /** Produce a copy (abstract). Every dynamically object will be cloned
   * rather than passing on the reference.
   * @return
   * the new, copied object. */
  virtual Image *clone (void) const = 0;
  /** Copy all data from a source image.
   * @param img
   * the source image */
  virtual void copy (Image &img);

  /** Returns a subimage.
   * @param yoffs
   * the row where to start
   * @param xoffs
   * the col where to start
   * @param ysize
   * the vertical size
   * @param xsize
   * the horizontal size
   * @return
   * the new image */
  Image *crop (int yoffs, int xoffs, int ysize, int xsize) const;
  /** Inserts a subimage.
   * @param yoffs
   * the row where to start
   * @param xoffs
   * the col where to start
   * @param img
   * the image to insert */
  virtual void paste (int yoffs, int xoffs, Image &img);
  /** Shift an Image.
   * @param yoffs
   * the rows to shift
   * @param xoffs
   * the cols to shift */
  virtual void shift (int yoffs, int xoffs);

  /** Returns the number of analysis steps performed so far.
   * @return
   * the number of steps */
  int anasteps (void) const { return m_asteps; }
  /** Returns the number of synthesis steps performed so far.
   * @return
   * the number of steps */
  int synsteps (void)  const { return m_ssteps; }
  /** Sets the number of analysis steps performed so far.
   * @param steps
   * the number of steps */
  void anasteps (int steps) { m_asteps = steps; }
  /** Sets the number of synthesis steps performed so far.
   * @param steps
   * the number of steps */
  void synsteps (int steps) { m_ssteps = steps; }

  /** Fills an image (or regions of it) with a given value
   * @param val the new value for the selected positions
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   */
  void fill (coeff value, int fromY = 0, int fromX = 0,
	     int toY = -1, int toX = -1);

  /** Returns the maximum value in a region. Signs will be considered.
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @return
   * the maximum */
  virtual coeff smax (int fromY = 0, int fromX = 0,
                      int toY = -1, int toX = -1) const = 0;
  /** Returns the maximum value in a region. Signs will be considered.
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @return
   * the maximum */
  virtual coeff smin (int fromY = 0, int fromX = 0,
                      int toY = -1, int toX = -1) const = 0;
  /** Returns the minimum absolute value in a region. Signs will be discarded.
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @return
   * the maximum */
  virtual coeff amax (int fromY = 0, int fromX = 0,
                      int toY = -1, int toX = -1) const = 0;
  /** Returns the minimum absolute value in a region. Signs will be discarded.
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @return
   * the minimum */
  virtual coeff amin (int fromY = 0, int fromX = 0,
                      int toY = -1, int toX = -1) const = 0;
  /** Return the average color for a rectangular region inside the image
   * drawn from one point within and the second point just outside the
   * region. The coefficients' signedness will be considered.
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @return the average color */
  virtual coeff saverage (int fromY = 0, int fromX = 0,
                          int toY = -1, int toX = -1) const = 0;

  /** Return the average color for a rectangular region inside the image
   * drawn from one point within and the second point just outside the
   * region. The coefficients' signedness will be discarded.
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @return the average color */
  virtual coeff aaverage (int fromY = 0, int fromX = 0,
                          int toY = -1, int toX = -1) const = 0;

  /** Return the square variance for a rectangular region inside the image
   * drawn from one point within and the second point just outside the
   * region. Signs will be considered. Use this method if you want
   * statistics on a region in the image. For other cases you may want
   * to use ImageInformation::sqvariance().
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @return the square variance */
  virtual coeff sqvariance (int fromY = 0, int fromX = 0,
                            int toY = -1, int toX = -1) const;

  /** Return the variance for a rectangular region inside the image
   * drawn from one point within and the second point just outside the
   * region. Use this method if you want statistics on a region in the
   * image. For other cases you may want to use ImageInformation::variance().
   * This version of the method takes the average (either absolute or signed) as
   * argument so that it does not need to be calculated again.
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @param avg the average for the region
   * @param abs true if signs are discarded
   * @return the square variance */
  virtual coeff variance (int fromY, int fromX, int toY, int toX,
			  coeff avg, bool abs) const;

  /** Return the variance for a rectangular region inside the image
   * drawn from one point within and the second point just outside the
   * region. Use this method if you want statistics on a region in the
   * image. For other cases you may want to use ImageInformation::variance().
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @param abs true if signs are discarded
   * @return the square variance */
  virtual coeff variance (int fromY = 0, int fromX = 0, int toY = -1,
                          int toX = -1, bool abs = false) const;

  /** Returns the standard deviation for a rectangular region inside the
   * image drawn from one point within and the second point just outside
   * the region. Signs will be considered. Use this method if you want
   * statistics on a region in the image. For other cases you may want
   * to use ImageInformation::sdeviation().
   * @param fromY the first point's row
   * @param fromX the first point's col
   * @param toY the second point's row (-1 if lower image border)
   * @param toX the second point's col (-1 if right image border)
   * @param abs true if signs are discarded
   * @return the standard deviation. */
  virtual coeff sdeviation (int fromY = 0, int fromX = 0, int toY = -1,
                            int toX = -1, bool abs = false) const;

  /** Resize the image's x/y dimensions. The old values will remain
   * as far as they fit in the new dimensions. The new dimensions must
   * all be greater than zero.
   * @exception invalid_argument
   * one or both dimensions are either negative or zero
   * @param rows
   * the new number of rows
   * @param cols
   * the new number of cols */
  virtual void resize (int rows, int cols) = 0;

  /** Produce a scaled version of the image which just fits into
   * the given dimensions. If the aspect ratio does not fit into
   * the new dimensions the remaining areas can be filled with a
   * given color or alternatively the resulting image will be smaller
   * than the target dimensions keeping its aspect ratio.
   * @exception invalid_argument
   * the factor is negative or the function argument is invalid
   * @param rows the target number of rows
   * @param cols the target number of columns
   * @param fill if not less than zero use this to fill remaining space
   * (else the a smaller image size will be chosen if the aspect ratio
   * does not match)
   * @param function interpolation function (0: bilinear interpolation,
   * 1: average, 2: nearest neighbour).
   * @return a new rescaled image */
  virtual Image *fitInto (int rows, int cols,
			  int fill = -1, int function = 0) const;

  /** Produce a scaled version of the image which just fits into
   * the given dimensions. If the aspect ratio does not fit into
   * the new dimensions the remaining areas can be filled with a
   * given color or alternatively the resulting image will be smaller
   * than the target dimensions keeping its aspect ratio.
   * This method is deprecad. Use the one with the enumeration ar instead.
   * @exception invalid_argument
   * the factor is negative or the function argument is invalid
   * @param rows the target number of rows
   * @param cols the target number of columns
   * @param mirrorExtend if true, the otherwise empty regions of the image
   * are extended by a mirroring function
   * (else the a smaller image size will be chosen if the aspect ratio
   * does not match)
   * @param function interpolation function (0: bilinear interpolation,
   * 1: average, 2: nearest neighbour).
   * @return a new rescaled image
   */
  virtual Image *fitInto (int rows, int cols, bool mirrorExtend,
			  int function = 0) const;

  /** Produce a scaled version of the image which just fits into
   * the given dimensions. If the aspect ratio does not fit into
   * the new dimensions the remaining areas can be filled with a
   * given color or alternatively the resulting image will be smaller
   * than the target dimensions keeping its aspect ratio.
   * @exception invalid_argument
   * the factor is negative or the function argument is invalid
   * @param rows the target number of rows
   * @param cols the target number of columns
   * @param extend the type of extension function used if the aspect
   * ratio does not match
   * (else the a smaller image size will be chosen if the aspect ratio
   * does not match)
   * @param function interpolation function (0: bilinear interpolation,
   * 1: average, 2: nearest neighbour).
   * @return a new rescaled image */
  virtual Image *fitInto (int rows, int cols, ExtendFunc extend,
			  int function = 0) const;

  /** Produce a scaled version of the image which just fits into
   * the given dimensions. If the aspect ratio does not fit into
   * the new dimensions the remaining areas can be filled with a
   * given color or alternatively the resulting image will be smaller
   * than the target dimensions keeping its aspect ratio.
   * @exception invalid_argument
   * the factor is negative or the function argument is invalid
   * @param rows the target number of rows
   * @param cols the target number of columns
   * @param fillFunc if not NULL a function for filling otherwise empty regions
   * (else the a smaller image size will be chosen if the aspect ratio
   * does not match)
   * @param function interpolation function (0: bilinear interpolation,
   * 1: average, 2: nearest neighbour).
   * @return a new rescaled image */
  virtual Image *fitInto (int rows, int cols, ResizeFillFunc *fillFunc,
			  int function = 0) const;

  /** Produce a scaled version of the image. The aspect ratio will remain
   * the same.
   * @exception invalid_argument
   * the factor is negative or the function argument is invalid
   * @param factor
   * the scale factor (>= 0, 1 for no change)
   * @param function interpolation function (0: bilinear interpolation,
   * 1: average, 2: nearest neighbour).
   * @return a new rescaled image */
  virtual Image *scale (double factor, int function = 0) const;

  /** Produce a scaled version of the image. The aspect ratio depends on the
   * two scale factors
   * @exception invalid_argument
   * the factor is negative or the function argument is invalid
   * @param yFactor
   * the vertical scale factor (>= 0, 1 for no change)
   * @param xFactor
   * the horizontal scale factor (>= 0, 1 for no change)
   * @param function interpolation function (0: bilinear interpolation,
   * 1: average, 2: nearest neighbour).
   * @return a new rescaled image */
  virtual Image *scale (double yFactor, double xFactor, int function = 0) const;

#ifdef USE_DEPRECATED_API
  /** Rough comparison. See if two images are similar according to a given
   * {\em epsilon} (important for floating-point comparisons).
   * @param img
   * the other {\em Image} object
   * @param epsilon
   * the epsilon
   * @return
   * if both are identical: {\em true}, else {\em false} */
  inline bool epsilons (Image *img, coeff epsilon) const
  { return this->epsilons (*img, epsilon); }
  /** Compares two images. Return {\em true} if both are equal.
   * @param img
   * The other {\em Image} object
   * @return
   * if equals: {\em true}, else {\em false} */
  inline bool equals (Image *img) const { return this->equals (*img); }
#endif
protected:
  /** Column reference. A vector that can be set to any column to allow
   * iterating over its values. */
  ColumnVector *m_acol;
  /** Row reference. A vector that can be set to any row to allow
   * iterating over its values. */
  RowVector *m_arow;
  /** Full reference. A vector that can be set anywhere within the
   * pixels to iterating over its values. */
  FullVector *m_afull;
  /** Number of rows. */
  int m_ysize;
  /** Number of cols. */
  int m_xsize;
  /** Overall size. */
  int m_xysize;
  /** The number of steps performed in the last analysis. */
  int m_asteps;
  /** The number of steps performed in the last synthesis. */
  int m_ssteps;
  /** Make sure the other image's dimensions match.
   * @exception invalid_argument
   * The other image's dimensions differ
   * @param img
   * the other image */
  void dimcheck (const Image &img) const;
  /** Abstract factory method to get a new instance of a given size
   * filled with zeroes.
   * @param rows
   * the number of rows
   * @param cols
   * the number of cols
   * @return the new image */
  virtual Image *mkImage (int rows = 0, int cols = 0) const = 0;

}; /* class Image */

/** @} */

#endif /* IMAGE_HH__ */

