/*
 * class ColorBuffer
 *
 * $Date$
 * $Revision$
 *
 */

#ifndef COLOR_BUFFER_HH__
#define COLOR_BUFFER_HH__

#include "WImage/Image.hh"

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

/**
 * An abstract wrapper for color images and videos.
 */
class
ColorBuffer
{
public:
  /** Constructor. Creates objects and sets actual start values.
   * @param xysize
   * the overall size of each channel (rows * cols)
   * @param colors
   * the number of colors, and therefore the array's length
   * @param cmodel
   * the color model */
  ColorBuffer (int xysize, int colors = 3, clrmodel cmodel = cm_rgb);

  /** Destructor. Frees allocated objects. */
  virtual ~ColorBuffer (void);

  /** Swap two color channels.
   * @exception invalid_argument if the channel specs are out of bounds
   * @param ch1 the first channel
   * @param ch2 the second channel */
  virtual void swapColors (int ch1, int ch2);

  /** Return the current colormodel
   * @exception invalid_argument
   * number of colors is not 3, or unsupported format / conversion
   * @return the colormodel */
  inline clrmodel colormodel (void) const { return m_cmodel; }
  /** Return the current number of colors
   * @return the number of colors */
  inline int colors (void) const { return m_colors; }
  /** Convert the image to a new colormodel. Note: this operation
   * is not completely invertable. Thus it should only be applied
   * if no further transforms and no back-conversion are desired.
   * @param model
   * the new colormodel ({\em cm_rgb} or {\em cm_yuv}) */
  virtual void colormodel (clrmodel model);

  /** Returns the maximum value. Signs will be considered.
   * @exception invalid_argument
   * empty image
   * @return
   * the maximum */
  virtual coeff smax (void) const;
  /** Returns the maximum value. Signs will be considered.
   * @exception invalid_argument
   * empty image
   * @return
   * the maximum */
  virtual coeff smin (void) const;

#ifndef _WIN32_WCE
  /** Returns the size in bytes of the file on the file system.
   * @param fname the file name
   * @return the file size */
  virtual int fileSize (char const *fname) const;
#endif

  /** Compares two images. Return {\em true} if both are equal.
   * @param buf
   * The other {\em ColorBuffer} object
   * @return
   * if equals: {\em true}, else {\em false} */
  virtual bool equals (ColorBuffer &buf) const;
  /** Rough comparison. See if two images are similar according to a given
   * {\em epsilon} (important for floating-point comparisons).
   * @param buf
   * the other {\em ColorBuffer} object
   * @param epsilon
   * the epsilon
   * @return
   * if both are identical: {\em true}, else {\em false} */
  virtual bool epsilons (ColorBuffer &buf, coeff epsilon) const;

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

  /** 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 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
   * @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 */
  virtual void beautify (int yoffs = 0, int xoffs = 0,
                         int ysize = 0, int xsize = 0) = 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
   * @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 averageColor (int fromY = 0, int fromX = 0,
                              int toY = -1, int toX = -1);

  /** Export the image for other applications. This only works if the image
   * has three channels!
   * @exception invalid_argument if the current colormodel or the one
   * passed as parameter is unsupported.
   * @param cmodel the color model in which the image is exported. Currently
   * {\em cm_rgb} and {\em cm_yuv} are supported.
   * @return a new buffer containing the image pixels in the format according
   * on the cmodel parameter */
  virtual unsigned char *toPixmap (clrmodel cmodel);

  /** Return the number of rows.
   * @return
   * the number of rows */
  inline int rows (void) const { return m_images[0]->rows (); }
  /** Return the number of columns.
   * @return
   * the number of columns */
  inline int cols (void) const { return m_images[0]->cols (); }
  /** Return the overall size.
   * @return
   * the overall size */
  inline int size (void) const { return m_images[0]->size (); }

protected:
  /* The way the current image's colors are encoded. */
  clrmodel m_cmodel;
  /** The number of pixel cols */
  int m_xsize;
  /** The number of pixel rows */
  int m_ysize;
  /** The overall number of pixels */
  int m_xysize;
  /** The number of colors */
  int m_colors;
  /** An array of {\em colors} Image objects */
  Image **m_images;
  /** True if the images are references and should not be deleted. */
  bool m_isReference;
  /** Allocate objects and set standard values.
   * @param colors
   * the number of colors
   * @param cmodel
   * the initial color model */
  void init (int colors, clrmodel cmodel = cm_rgb);
  /** Deletes allocated objects. */
  virtual void destroy (void);
  /** Adjust the coefficients to make them pixelizable. */
  virtual void valadjust (void);
}; /* class ColorBuffer */

/** @} */

#endif /* COLOR_BUFFER_HH__ */

