/* AISAiboYCrCbColorSeg: a color segmentation class developped for Sony Aibo. */
/* Copyright (C) <2006>  <Gilberto Decaro> */

/* This program 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; either version 2 of the License, or */
/* (at your option) any later version. */

/* This program 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 this program; if not, write to the Free Software Foundation, */
/* Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */

#ifndef AISAIBOYCRCBCOLORSEG_H_DEFINED
#define AISAIBOYCRCBCOLORSEG_H_DEFINED

#include <unistd.h>

/**
   Implementa il color detection su 32 colori via software per Sony
   Aibo. Permette di riconoscere fino a 32 colori data un immagine
   nello spazio colore YCrCb in cui ogni pixel e' composto da tre byte
   (y cr cb). Il tempo di esecuzione dato n il numero di colori
   impostati da riconoscere e' O(1).
   
   Il metodo processImage() effettua il color detection, come
   parametro richiede l'immagine della telecamera in formato RAW,
   quindi il valore ritornato dal metodo
   OFbkImageVectorData::getData().
   
 */
class AISAiboYCrCbColorSeg{
 public:
  /**
     Colori riconscibili dalla classe. Una volta impostati i colori e'
     possibile controllare il riconoscimento dell'i-esimo colore
     effettuando un and logico tra il pixel dell'immagine e l'i-esimo
     colore.
   */
  enum Colors
    {
      l0 =0x01,	    
      l1 =0x02,	    
      l2 =0x04,	    
      l3 =0x08,	    
      l4 =0x10,	    
      l5 =0x20,	    
      l6 =0x40,	    
      l7 =0x80,	    
      l8 =0x0100,   
      l9 =0x0200,    
      l10=0x0400,   
      l11=0x0800,   
      l12=0x1000,   
      l13=0x2000,   
      l14=0x4000,   
      l15=0x8000,   
      l16=0x010000, 
      l17=0x020000, 
      l18=0x040000, 
      l19=0x080000, 
      l20=0x100000, 
      l21=0x200000, 
      l22=0x400000, 
      l23=0x800000, 
      l24=0x01000000,
      l25=0x02000000,
      l26=0x04000000,
      l27=0x08000000,
      l28=0x10000000,
      l29=0x20000000,
      l30=0x40000000,
      l31=0x80000000
    };
 public:
  /**
     Costruisce un oggetto per il riconoscimento dei colori data un
     immagine di dimensioni in pixel widthxheigh.

     @param width larghezza dell'immagine.

     @param height altezza dell'immagine.
   */
  AISAiboYCrCbColorSeg(int width, int height);
  
  /**
     Costruttore di default. Costuisce un oggetto non valido.
   */
  AISAiboYCrCbColorSeg() : mIAmValid(false), mProcessedImage(0) {};
  
  /**
     Costruttore di copia. Copia dell'oggetto permessa.
   */
  AISAiboYCrCbColorSeg(const AISAiboYCrCbColorSeg& other);
  
  /**
     Distruttore.
   */
  ~AISAiboYCrCbColorSeg();
  
  /**
     Operatore di copia. Copia per assegnamento dell'oggetto permessa.
   */
  AISAiboYCrCbColorSeg& operator=(const AISAiboYCrCbColorSeg& other);
  
  /**
     Processa l'immagine passanta come parametro. Restistuisce
     un'array di int di dimensione width x heigh contenente l'immagine
     con i colori individutati.q

     @param pImage puntatore all'immagine Raw da
     processare. L'immagine Aibo in formato RAW e' il valore ritornato
     dal metodo OFbkImageVectorData::getData() applicato sul layer
     voluto.
     
     @return puntatore const all'immagine processata. E' un array di
     unsigned int di dimensione width x height.
   */
  const unsigned int* processImage(unsigned char* pImage);
  
  /**
     Imposta i valori y,cr,cb per il riconoscimento di un dato colore.

     @param selectedLayer colore da impostare.

     @param y valore di y da impostare.
     
     @param crMin valore minimo di cr.
     
     @param crMax valore massimo di cr.

     @param cbMin valore minimo di cb.
     
     @param cbMax valore massimo di cb.

     @return true se l'impostazione e' andata a buon fine, false
     altrimenti.
   */

  bool setColor(Colors selectedLayer,
		unsigned char y,
		unsigned char crMin, unsigned char crMax,
		unsigned char cbMin, unsigned char cbMax);

  /**
     Ritorna il numero di pixel riconosciuti in un dato layer. Da
     eseguire dopo il metodo processImage per avere valori aggiornati.

     @param selectedLayer layer di cui si vuole conoscere il numero di
     pixel riconosciuti.

     @return int numero di pixel riconosciuti, -1 in caso di errore.
   */
  int getNumberOfRecognizedPixel(Colors selectedLayer){
    return mIAmValid ? mNumberOfRecognizedPixel[ pseudoLog2(selectedLayer) ] : -1;
  }

  /**
     Controlla se l'oggeto e' valido, quindi puo' essere utilizzato
     per la segmentazione, o meno.

     @return true se l'oggetto e' valido, false altrimenti.
   */
  inline bool isValid() {
    return mIAmValid;
  }
 protected:

  /**
     Calcola lo pseudo logaritmo in base due di n. Ritorna la
     posizione del primo bit a partire dal basso uguale a 1.

     @param n valore su cui applicare lo pseudo logaritmo.

     @return posizione del primo bit a partire dal piu' basso uguale a
     1.
   */
  inline unsigned int pseudoLog2(register unsigned int n) {
    register unsigned int k;
    for (k = 0; n != 1; n >>= 1)
      ++k;
    return k;
  };  
  
 protected:
  /**
     Flag a true se l'oggetto e' valido (quindi utilizzabile), false
     se inutilizzabile.
   */
  bool mIAmValid;
  
  /**
     Larghezza dell'immagine.
   */
  int mWidth;
  /**
     Altezza dell'immagine.
   */
  int mHeight;
  
  /**
     Dimensione dell'immagine in numero di pixel.
   */
  size_t mImageSize;
  
  /**
     Array per il riconoscimento dei colori. Per ogni valore di y
     (indice dell'array) contiene un unsigned int in cui ogni bit
     rappresenta l'i-esimo colore.
   */
  unsigned int mYValue[256];
  /**
     Array per il riconoscimento dei colori. Per ogni valore di cr
     (indice dell'array) contiene un unsigned int in cui ogni bit
     rappresenta l'i-esimo colore.
   */
  unsigned int mCrValue[256];
  /**
     Array per il riconoscimento dei colori. Per ogni valore di cb
     (indice dell'array) contiene un unsigned int in cui ogni bit
     rappresenta l'i-esimo colore.
   */
  unsigned int mCbValue[256];


  /**
     Array contenente per ogni layer il numero di pixel riconosciuti.
   */
  int mNumberOfRecognizedPixel[32];
  
  /**
     Array di int contenente l'immagine con i colori riconosciuti.
   */
  unsigned int* mProcessedImage;

  /**
     Due volte il width dell'immagine (per ottimizzare l'algoritmo).
   */
  int mDoubleWidth;

  /**
     Coefficiente 5 * width +1 (per ottimizzare l'algoritmo).
   */
  int mSomeWidth;

};

#endif
