package visual.statik.sampled;

/**
 * An enumeration of the different convolutions
 * that are supported in the BufferedImageOpFactory
 *
 * Note that this class has package visibility because it
 * should only be used by classes in this package.
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
enum Convolutions
{
   BLUR {float[] getKernelValues(int size)
         {
            return getBlurValues(size);            
         } 
        },
   EDGE {float[] getKernelValues(int size)
         {
            return getEdgeValues(size);            
         }
        },
   EMBOSS {float[] getKernelValues(int size)
         {
            return getEmbossValues(size);            
         }
        },
   IDENTITY {float[] getKernelValues(int size)
         {
            return getIdentityValues(size);            
         }
        },
   SHARPEN {float[] getKernelValues(int size)
         {
            return getSharpenValues(size);            
         }
        };
   

   
   /**
    * Note that this method has package visibility
    */
   abstract float[] getKernelValues(int size);
   
   
   /**
    * Get the kernel values for a blurring convolution
    *
    * @param size   The size of the kernel
    * @return       The array of kernel values
    */
   private static float[] getBlurValues(int size)
   {
      float       denom;      
      float[]     result;
      
      denom  = (float)(size*size);      
      result = new float[size*size];

      for (int row=0; row<size; row++)
         for (int col=0; col<size; col++)
            result[indexFor(row,col,size)] = 1.0f/denom;      

      return result;      
   }


   /**
    * Get the kernel values for an edge detecting convolution
    *
    * @param size   The size of the kernel
    * @return       The array of kernel values
    */
   private static float[] getEdgeValues(int size)
   {
      float[]     result;
      int         center;
      
      
      center = size/2;
      result = new float[size*size];

      result[indexFor(center-1, center  , size)] = -1.0f;      
      result[indexFor(center  , center-1, size)] = -1.0f;      
      result[indexFor(center  , center  , size)] =  4.0f;      
      result[indexFor(center  , center+1, size)] = -1.0f;      
      result[indexFor(center+1, center  , size)] = -1.0f;      

      return result;      
   }


   /**
    * Get the kernel values for an embossing convolution
    *
    * @param size   The size of the kernel
    * @return       The array of kernel values
    */
   private static float[] getEmbossValues(int size)
   {
      float[]     result;
      int         center;
      
      
      center = size/2;
      result = new float[size*size];

      result[indexFor(center-1, center-1, size)] = -2.0f;      
      result[indexFor(center  , center  , size)] =  1.0f;      
      result[indexFor(center+1, center+1, size)] =  2.0f;      

      return result;      
   }
   
   

   /**
    * Get the kernel values for an identity convolution
    *
    * @param size   The size of the kernel
    * @return       The array of kernel values
    */
   private static float[] getIdentityValues(int size)
   {
      float[]     result;
      int         center;
      
      center = size/2;
      result = new float[size*size];
      result[indexFor(center,center,size)] = 1.0f;
      
      return result;      
   }


   /**
    * Get the kernel values for an sharpening convolution
    *
    * @param size   The size of the kernel
    * @return       The array of kernel values
    */
   private static float[] getSharpenValues(int size)
   {
      float[]     result;
      int         center;
      
      
      center = size/2;
      result = getEdgeValues(size);
      result[indexFor(center  , center  , size)] +=  1.0f;      

      return result;      
   }
   

   /**
    * Convert row and column indexes (i.e., matrix indices)
    * into a linear index (i.e., vector index)
    *
    * @param row   The row index
    * @param col   The column index
    * @param size  The size of the square matrix
    */
   private static int indexFor(int row, int col, int size)
   {
      return row*size + col;      
   }
   
}
