/** IMAGE STRIPER **********************************************************/
/*                                                                         */
/*  img_striper.cpp                                                        */
/*                                                                         */
/***************************************************************************/

/** INCLUDES ***************************************************************/
//- OWN ---------------------------------------------------------------------
#include "img_striper.h"
      // "im.h"
      // "im_image.h"
#include "structured_color.h"

#include "stdio.h"




/** LOCAL FUNCTIONS ********************************************************/
bool valid_pos_color ( int base, int r, int g, int b )
{
   if ( base == StC_BASE_32 )
   {
      if ( ( r==255 && g==0   && b==0   )
         ||( r==0   && g==255 && b==0   )
         ||( r==0   && g==0   && b==255 ) )
      {
         return true ;
      }
   }
   else
   if ( base == StC_BASE_42 )
   {
      if ( ( r==255 && g==0   && b==0   )
         ||( r==0   && g==255 && b==0   )
         ||( r==0   && g==0   && b==255 )
         ||( r==255 && g==0   && b==255 ) )
      {
         return true ;
      }
   }
   else
   if ( base == StC_BASE_62 )
   {
      if ( ( r==255 && g==0   && b==0   )
         ||( r==0   && g==255 && b==0   )
         ||( r==0   && g==0   && b==255 )
         ||( r==255 && g==0   && b==255 )
         ||( r==255 && g==255 && b==0   )
         ||( r==0   && g==255 && b==255 ) )
      {
         return true ;
      }
   }
   return false ;
}
//===========================================================================
void find_trans_colors_V_stripe( int base, int w_trans, int h_trans, int width, int height, unsigned  char*data, int max_t_dist, int *c_esq, int *c_dir )
{
   int dim = width*height ;

   int w ;

   int r, g, b ;

   *c_esq = -1 ;
   *c_dir = -1 ;
   
   w = w_trans-1 ;
   while(  w>=0 && w>=w_trans-max_t_dist && (*c_esq)==-1 )
   {
      r = (int)data[         h_trans*width + w ] ;
      g = (int)data[   dim + h_trans*width + w ] ;
      b = (int)data[ 2*dim + h_trans*width + w ] ;

      if( valid_pos_color( base, r, g, b ) )
      {
         *c_esq = StC_ColorIndex( base, r, g, b );
      }
      w-- ;
   }

   w = w_trans+1 ;
   while(  w<width && w<=w_trans+max_t_dist && (*c_dir)==-1 )
   {
      r = (int)data[         h_trans*width + w ] ;
      g = (int)data[   dim + h_trans*width + w ] ;
      b = (int)data[ 2*dim + h_trans*width + w ] ;

      if( valid_pos_color( base, r, g, b ) )
      {
         *c_dir = StC_ColorIndex( base, r, g, b );
      }
      w++ ;
   }   
}
//===========================================================================
void find_trans_colors_H_stripe( int base, int h_trans, int w_trans, int width, int height, unsigned  char*data, int max_t_dist, int *c_ant, int *c_dep )
{
   int dim = width*height ;

   int h ;

   int r, g, b ;

   *c_ant = -1 ;
   *c_dep = -1 ;
   
   h = h_trans-1 ;
   while(  h>=0 && h>=h_trans-max_t_dist && (*c_ant)==-1 )
   {
      r = (int)data[         h*width + w_trans ] ;
      g = (int)data[   dim + h*width + w_trans ] ;
      b = (int)data[ 2*dim + h*width + w_trans ] ;

      if( valid_pos_color( base, r, g, b ) )
      {
         *c_ant = StC_ColorIndex( base, r, g, b );
      }
      h-- ;
   }

   h = h_trans+1 ;
   while(  h<height && h<=h_trans+max_t_dist && (*c_dep)==-1 )
   {
      r = (int)data[         h*width + w_trans  ] ;
      g = (int)data[   dim + h*width + w_trans  ] ;
      b = (int)data[ 2*dim + h*width + w_trans  ] ;

      if( valid_pos_color( base, r, g, b ) )
      {
         *c_dep = StC_ColorIndex( base, r, g, b );
      }
      h++ ;
   }   
}
/***************************************************************************/


/** EXPORTED FUNCTIONS *****************************************************/
void ImgS_Discretize ( imImage *img_pos, imImage *img_neg, imImage *img_out ) 
{
// Inicializing variables
   unsigned int width  = (unsigned int)( ( img_pos->width  == img_neg->width  ) ? img_pos->width  : 0 ) ;
   unsigned int height = (unsigned int)( ( img_pos->height == img_neg->height ) ? img_pos->height : 0 ) ;

   unsigned int dim = width*height ;

   unsigned char *pos = (unsigned char *)img_pos->data[0] ;
   unsigned char *neg = (unsigned char *)img_neg->data[0] ;
   unsigned char *out = (unsigned char *)img_out->data[0] ;

// if images differ in at least one dimensions, no process is done
   if ( !dim )
      return ;

// processing...
   unsigned int w, h ;

   for ( h=0 ; h<height ; h++ )
   {
      for ( w=0 ; w<width ; w++ )
      {
         int r = (int)pos[         h*width + w ] - (int)neg[         h*width + w ];
         int g = (int)pos[   dim + h*width + w ] - (int)neg[   dim + h*width + w ] ;
         int b = (int)pos[ 2*dim + h*width + w ] - (int)neg[ 2*dim + h*width + w ] ;


         r = ( r<0 ) ? 0 : ( ( r>0 ) ? 255 : 128 ) ;
         g = ( g<0 ) ? 0 : ( ( g>0 ) ? 255 : 128 ) ;
         b = ( b<0 ) ? 0 : ( ( b>0 ) ? 255 : 128 ) ;

         out[         h*width + w ] = (unsigned char)r ;
         out[   dim + h*width + w ] = (unsigned char)g ;
         out[ 2*dim + h*width + w ] = (unsigned char)b ;
      }
   }
}
//===========================================================================
void ImgS_TransitionsV ( int base, imImage *img_cand1, imImage *img_cand2, imImage *img_out, int max_t_len, int max_t_dist )
{
// Inicializing variables
   unsigned int width  = (unsigned int)( ( img_cand1->width  == img_cand2->width  ) ? img_cand1->width  : 0 ) ;
   unsigned int height = (unsigned int)( ( img_cand1->height == img_cand2->height ) ? img_cand1->height : 0 ) ;

   unsigned int dim = width*height ;

   unsigned char *dt1 = (unsigned char *)img_cand1->data[0] ;
   unsigned char *dt2 = (unsigned char *)img_cand2->data[0] ;
   unsigned char *out = (unsigned char *)img_out->data[0] ;

// if images differ in at least one dimensions, no process is done
   if ( !dim )
      return ;


// processing...
   unsigned int w1, h1, w2, h2 ;
   for ( h1=0 ; h1<height ; h1++ )
   {
      for ( w1=0 ; w1<width ; w1++ )
      {  
         out[         h1*width + w1 ] = 0 ;
         out[   dim + h1*width + w1 ] = 0 ;
         out[ 2*dim + h1*width + w1 ] = 0 ;
      }
   }

   for ( h1=0 ; h1<height ; h1++ )
   {
      for ( w1=0 ; w1<width ; w1++ )
      {  
         int r = (int)dt1[         h1*width + w1 ] ;
         int g = (int)dt1[   dim + h1*width + w1 ] ;
         int b = (int)dt1[ 2*dim + h1*width + w1 ] ;

         if( r==0 && g==0 && b==0 )
         {


            h2 = h1 ;
            w2 = 0 ;
            unsigned int w = ( w1-max_t_dist >=0 ) ? (w1-max_t_dist) : 0 ;

            unsigned int dist = (unsigned int )max_t_dist + 10 ;

            while( w < w1+max_t_dist && w<width )
            {
               int r2 = (int)dt2[         h2*width + w ] ;
               int g2 = (int)dt2[   dim + h2*width + w ] ;
               int b2 = (int)dt2[ 2*dim + h2*width + w ] ;

               if( r2==0 && g2==0 && b2==0 )
               {
                  if( ((w>w1) && ((w-w1) < dist)) || ((w1>=w) && ((w1-w) < dist)) )
                  {
                     w2 = w ;
                  }
               }
               w++;
            }
            if( w2 != 0 )
            {
               int c_esq1, c_esq2, c_dir1, c_dir2 ;
               find_trans_colors_V_stripe( base, w1, h1, width, height, dt1, max_t_dist, &c_esq1, &c_dir1 ) ;
               find_trans_colors_V_stripe( base, w2, h2, width, height, dt2, max_t_dist, &c_esq2, &c_dir2 ) ;
               int i = StC_TansitionIndex( base, c_esq1, c_dir1, c_esq2, c_dir2 ) ;
   
               out[         h1*width + (w1+w2)/2 ] = 255 ;
               out[   dim + h1*width + (w1+w2)/2 ] = 255 ;
               out[ 2*dim + h1*width + (w1+w2)/2 ] = (unsigned char)i ;
            }

         }
      }
   }
}

//===========================================================================
void ImgS_TransCandidateV ( int base, imImage *img_in, imImage *img_out, int max_t_len )
{
// Inicializing variables
   unsigned int width  = (unsigned int)img_in->width  ;
   unsigned int height = (unsigned int)img_in->height ;

   unsigned int dim = width*height ;

   unsigned char *in  = (unsigned char *)img_in ->data[0] ;
   unsigned char *out = (unsigned char *)img_out->data[0] ;

   if ( !dim )
      return ;

// processing...
   unsigned int w, h ;

   for ( h=0 ; h<height ; h++ )
   {
      bool prev_valid = false ;
      int prev_r = 128, prev_g = 128, prev_b =  128 ;
      int trans_start_w = 0 ;
      int trans_count = 0 ;

      for ( w=0 ; w<width ; w++ )
      {       
         int r = (int)in[         h*width + w ] ;
         int g = (int)in[   dim + h*width + w ] ;
         int b = (int)in[ 2*dim + h*width + w ] ;

         out[         h*width + w ] = r ;
         out[   dim + h*width + w ] = g ;
         out[ 2*dim + h*width + w ] = b ;

         if( valid_pos_color( base, r, g, b ) )
         {
            if( prev_valid )
            {
               if( prev_r != r || prev_g!=g || prev_b != b )
               {
                  out[         h*width + w ] = 0 ;
                  out[   dim + h*width + w ] = 0 ;
                  out[ 2*dim + h*width + w ] = 0 ;
                  prev_r = r ;
                  prev_g = g ;
                  prev_b = b ;
               }
            }
            else
            {
               if( ( prev_r != r || prev_g!=g || prev_b != b ) && ( trans_count <= max_t_len ) )
               {
                     out[         h*width + (trans_start_w+w)/2 ] = 0 ;
                     out[   dim + h*width + (trans_start_w+w)/2 ] = 0 ;
                     out[ 2*dim + h*width + (trans_start_w+w)/2 ] = 0 ;
               }

            }
            prev_r = r ;
            prev_g = g ;
            prev_b = b ;
            prev_valid = true ;
            
         }
         else
         {
            if( prev_valid )
            {
               trans_count = 1 ;
               trans_start_w = w ;
            }
            else
            {
               trans_count++ ;
            }
            prev_valid = false ;
         }
      }
   }
}

//===========================================================================
void ImgS_ValidateV ( int base, imImage *img_in, imImage *img_out, int min_s_len )
{
// Inicializing variables
   unsigned int width  = (unsigned int)img_in->width  ;
   unsigned int height = (unsigned int)img_in->height ;

   unsigned int dim = width*height ;

   unsigned char *in  = (unsigned char *)img_in ->data[0] ;
   unsigned char *out = (unsigned char *)img_out->data[0] ;

   if ( !dim )
      return ;

   int prev_r = -1,
       prev_g = -1,
       prev_b = -1 ;

// processing...
   unsigned int w, h ;

   for ( h=0 ; h<height ; h++ )
   {
      for ( w=0 ; w<width ; w++ )
      {
         int r =  (int)in[         h*width + w ] ;
         int g =  (int)in[   dim + h*width + w ] ;
         int b =  (int)in[ 2*dim + h*width + w ] ;

         if( !valid_pos_color( base, r, g, b ) )
         {
            prev_r = out[         h*width + w ] = 128 ;
            prev_g = out[   dim + h*width + w ] = 128 ;
            prev_b = out[ 2*dim + h*width + w ] = 128 ;
         }
         else
         {
            if( r==prev_r && g==prev_g && b==prev_b)
            {
               out[         h*width + w ] = r ;
               out[   dim + h*width + w ] = g ;
               out[ 2*dim + h*width + w ] = b ;
            }
            else
            {
               // finds out if has enougth equal pixels after this
               bool has_enougth = true ;
               unsigned int temp_w = w+1 ;               
               while( temp_w<w+min_s_len && temp_w<width && has_enougth )
               {
                  if( r != (int)in[         h*width + temp_w ] ||
                      g != (int)in[   dim + h*width + temp_w ] ||
                      b != (int)in[ 2*dim + h*width + temp_w ] )
                  {
                     has_enougth = false ;
                  }
                  temp_w ++ ;
               }
               if( has_enougth )
               {
                  prev_r = out[         h*width + w ] = r ;
                  prev_g = out[   dim + h*width + w ] = g ;
                  prev_b = out[ 2*dim + h*width + w ] = b ;
               }
               else
               {
                  prev_r = out[         h*width + w ] = 128 ;
                  prev_g = out[   dim + h*width + w ] = 128 ;
                  prev_b = out[ 2*dim + h*width + w ] = 128 ;
               }
            }
         }
      }
   }
}

//===========================================================================
void ImgS_TransitionsH ( int base, imImage *img_cand1, imImage *img_cand2, imImage *img_out, int max_t_len, int max_t_dist )
{
// Inicializing variables
   unsigned int width  = (unsigned int)( ( img_cand1->width  == img_cand2->width  ) ? img_cand1->width  : 0 ) ;
   unsigned int height = (unsigned int)( ( img_cand1->height == img_cand2->height ) ? img_cand1->height : 0 ) ;

   unsigned int dim = width*height ;

   unsigned char *dt1 = (unsigned char *)img_cand1->data[0] ;
   unsigned char *dt2 = (unsigned char *)img_cand2->data[0] ;
   unsigned char *out = (unsigned char *)img_out->data[0] ;

// if images differ in at least one dimensions, no process is done
   if ( !dim )
      return ;


// processing...
   unsigned int w1, h1, w2, h2 ; 
   for ( w1=0 ; w1<width ; w1++ )
   {
      for ( h1=0 ; h1<height ; h1++ )
      {  
         out[         h1*width + w1 ] = 0 ;
         out[   dim + h1*width + w1 ] = 0 ;
         out[ 2*dim + h1*width + w1 ] = 0 ;
      }
   }

   for ( w1=0 ; w1<width ; w1++ )
   {
      for ( h1=0 ; h1<height ; h1++ )
      {  
         int r = (int)dt1[         h1*width + w1 ] ;
         int g = (int)dt1[   dim + h1*width + w1 ] ;
         int b = (int)dt1[ 2*dim + h1*width + w1 ] ;

         if( r==0 && g==0 && b==0 )
         {
            h2 = 0 ;
            w2 = w1 ;
            unsigned int h = ( h1-max_t_dist >=0 ) ? (h1-max_t_dist) : 0 ;

            unsigned int dist = (unsigned int )max_t_dist + 10 ;

            while( h < h1+max_t_dist && h<height )
            {
               int r2 = (int)dt2[         h*width + w2 ] ;
               int g2 = (int)dt2[   dim + h*width + w2 ] ;
               int b2 = (int)dt2[ 2*dim + h*width + w2 ] ;

               if( r2==0 && g2==0 && b2==0 )
               {
                  if( ((h>h1) && ((h-h1) < dist)) || ((h1>=h) && ((h1-h) < dist)) )
                  {
                     h2 = h ;
                  }
               }
               h++;
            }
            if( h2 != 0 )
            {
               int c_ant1, c_ant2, c_dep1, c_dep2 ;
               find_trans_colors_H_stripe( base, w1, h1, width, height, dt1, max_t_dist, &c_ant1, &c_dep1 ) ;
               find_trans_colors_H_stripe( base, w2, h2, width, height, dt2, max_t_dist, &c_ant2, &c_dep2 ) ;
               int i = StC_TansitionIndex( base, c_ant1, c_dep1, c_ant2, c_dep2 ) ;
   
               out[         ((h1+h2/2))*width + w1 ] = 255 ;
               out[   dim + ((h1+h2/2))*width + w1 ] = 255 ;
               out[ 2*dim + ((h1+h2/2))*width + w1 ] = (unsigned char)i ;
            }
         }
      }
   }
}

//===========================================================================
void ImgS_TransCandidateH ( int base, imImage *img_in, imImage *img_out, int max_t_len )
{
// Inicializing variables
   unsigned int width  = (unsigned int)img_in->width  ;
   unsigned int height = (unsigned int)img_in->height ;

   unsigned int dim = width*height ;

   unsigned char *in  = (unsigned char *)img_in ->data[0] ;
   unsigned char *out = (unsigned char *)img_out->data[0] ;

   if ( !dim )
      return ;

// processing...
   unsigned int w, h ;

   for ( w=0 ; w<width ; w++ )
   {
      bool prev_valid = false ;
      int prev_r = 128, prev_g = 128, prev_b =  128 ;
      int trans_start_h = 0 ;
      int trans_count = 0 ;

      for ( h=0 ; h<height ; h++ )
      {       
         int r = (int)in[         h*width + w ] ;
         int g = (int)in[   dim + h*width + w ] ;
         int b = (int)in[ 2*dim + h*width + w ] ;

         out[         h*width + w ] = r ;
         out[   dim + h*width + w ] = g ;
         out[ 2*dim + h*width + w ] = b ;

         if( valid_pos_color( base, r, g, b ) )
         {
            if( prev_valid )
            {
               if( prev_r != r || prev_g!=g || prev_b != b )
               {
                  out[         h*width + w ] = 0 ;
                  out[   dim + h*width + w ] = 0 ;
                  out[ 2*dim + h*width + w ] = 0 ;
                  prev_r = r ;
                  prev_g = g ;
                  prev_b = b ;
               }
            }
            else
            {
               if( ( prev_r != r || prev_g!=g || prev_b != b ) && ( trans_count <= max_t_len ) )
               {
                     out[         ((trans_start_h+h)/2)*width + w ] = 0 ;
                     out[   dim + ((trans_start_h+h)/2)*width + w ] = 0 ;
                     out[ 2*dim + ((trans_start_h+h)/2)*width + w ] = 0 ;
               }
            }
            prev_r = r ;
            prev_g = g ;
            prev_b = b ;
            prev_valid = true ;
            
         }
         else
         {
            if( prev_valid )
            {
               trans_count = 1 ;
               trans_start_h = h ;
            }
            else
            {
               trans_count++ ;
            }
            prev_valid = false ;
         }
      }
   }
}

//===========================================================================
void ImgS_ValidateH ( int base, imImage *img_in, imImage *img_out, int min_s_len )
{
// Inicializing variables
   unsigned int width  = (unsigned int)img_in->width  ;
   unsigned int height = (unsigned int)img_in->height ;

   unsigned int dim = width*height ;

   unsigned char *in  = (unsigned char *)img_in ->data[0] ;
   unsigned char *out = (unsigned char *)img_out->data[0] ;

   if ( !dim )
      return ;

   int prev_r, prev_g, prev_b ;

// processing...
   unsigned int w, h ;

   for ( w=0 ; w<width ; w++ )
   {
      for ( h=0 ; h<height ; h++ )
      {
         int r =  (int)in[         h*width + w ] ;
         int g =  (int)in[   dim + h*width + w ] ;
         int b =  (int)in[ 2*dim + h*width + w ] ;

         if( !valid_pos_color( base, r, g, b ) )
         {
            prev_r = out[         h*width + w ] = 128 ;
            prev_g = out[   dim + h*width + w ] = 128 ;
            prev_b = out[ 2*dim + h*width + w ] = 128 ;
         }
         else
         {
            if( r==prev_r && g==prev_g && b==prev_b)
            {
               out[         h*width + w ] = r ;
               out[   dim + h*width + w ] = g ;
               out[ 2*dim + h*width + w ] = b ;
            }
            else
            {
               // finds out if has 4 equal pixels after this
               bool has_enougth = true ;
               unsigned int temp_h = h+1 ;               
               while( temp_h<h+min_s_len && temp_h<height && has_enougth )
               {
                  if( r != (int)in[         temp_h*width + w ] ||
                      g != (int)in[   dim + temp_h*width + w ] ||
                      b != (int)in[ 2*dim + temp_h*width + w ] )
                  {
                     has_enougth = false ;
                  }
                  temp_h ++ ;
               }
               if( has_enougth )
               {
                  prev_r = out[         h*width + w ] = r ;
                  prev_g = out[   dim + h*width + w ] = g ;
                  prev_b = out[ 2*dim + h*width + w ] = b ;
               }
               else
               {
                  prev_r = out[         h*width + w ] = 128 ;
                  prev_g = out[   dim + h*width + w ] = 128 ;
                  prev_b = out[ 2*dim + h*width + w ] = 128 ;
               }
            }
         }
      }
   }
}

//***************************************************************************