/*---------------------------------------------------------
   ISImageFFT.h : part of the ImgSource library.
   
   Image processing functions

   This code copyright (c) 2000-2016, Smaller Animals Software, Inc..

   No portion of this code may be copied or distributed without 
   permission of Smaller Animals Software, Inc..
   http://www.smalleranimals.com

---------------------------------------------------------*/
#pragma once

#if !defined is6_SOURCEH && !defined is6_INTERNAL
#error Do not include this file directly. Include ISource.h
#endif

#ifdef __cplusplus
extern "C" {
#endif


/*---------------------------------------------------------
   is6_FFTAllocGrid

   Purpose : 
   Allocate a working space for the FFT functions. 

   Note:
   The dimensions you pass should be the dimensions of the image
   you are going to be working on. 

   Note:
   Image dimensions must be equal to a power of 2:
   (ex. 128, 256, 512, 1024, etc.). All FFT operations require 
   this. Use is6_NextPowerOfTwo to find the next largest power of
   two for each dimension. Then prepare your image accordingly (overlay
   onto a background of the correct size or resize the input image).

   Note:
   This buffer can be very large. (w * h * 16 BYTEs)

   Param             Use
   ------------------------------------
   uWidth            width in pixels
   uHeight           height

   Return
   ------
      HGLOBAL handle to FFT grid
      Caller must call GlobalFree to release this memory.
---------------------------------------------------------*/
_ISDeclSpec HGLOBAL    _ISCConv _ISFn( is6_FFTAllocGrid )(UINT32 uWidth, UINT32 uHeight);

/*---------------------------------------------------------
   is6_FFTTransform

   Purpose : 
   Fill the FFT grid based on a single channel (ie. grayscale) 
   input image. This is the first step in an FFT operation.

   See is6_FFTFilter, is6_FFTTransformInverse.

   This grid must be (w * h * 2) doubles. You can use 
   is6_FFTAllocGrid to allocate this if you wish.

   Note:
   The input image can be BYTEs or 64-bit doubles. See uFlags.

   Param             Use
   ------------------------------------
   pInput            input image (BYTE or double)
   uWidth            width in pixels
   uHeight           height

   uRowStride        number of components per pixel row 
   grid              FFT grid (caller allocates)

   uFlags            bit      purpose
                     ---      -------
                      10      input image is 64-bit doubles
                              else image is BYTEs

   Return
   ------
      FALSE on failure
---------------------------------------------------------*/
_ISDeclSpec BOOL    _ISCConv _ISFn( is6_FFTTransform )(const void *pInput, UINT32 uWidth, UINT32 uHeight, UINT32 uRowStride, double *grid, UINT32 uFlags);

/*---------------------------------------------------------
   is6_FFTFilter

   Purpose : 
   Apply one of the pre-defined FFT filters to the FFT grid.
   The FFT grid must have been filled with is6_FFTTransform.

   This is the second step in an FFT operation.

   See is6_FFTTransform, is6_FFTTransformInverse

   Note:
   The values required in the pParams array depend on the filter
   type you've chosen.

   Filter type                Parameter list
   ----------------------     --------------
   1 - low pass, ideal        pParam[0] = cutoff (d0)

   2 - high pass, ideal       pParam[0] = cutoff (d0)

   3 - band pass              pParam[0] = low cutoff
                              pParam[1] = high cutoff

   4 - 1/f^p filter           pParam[0] = power (p)

   5 - low pass butterworth   pParam[0] = cutoff
                              pParam[1] = order (try 2)

   6 - high pass butterworth  pParam[0] = cutoff
                              pParam[1] = order (try 2)

   7 - low pass gaussian      pParam[0] = cutoff (d0)

   8 - high pass gaussian     pParam[0] = cutoff (d0)

   9 - high-boost butterworth 
                              v = offset + factor * HighPassButterworth()
                              pParam[0] = cutoff (d0)
                              pParam[1] = offset (try .25 to .5) 
                              pParam[2] = factor (try 1.5 to 2.0)

   10 - high-boost gaussian   
                              v = offset + factor * HighPassGaussian()
                              pParam[0] = cutoff (d0)
                              pParam[1] = offset (try .25 to .5) 
                              pParam[2] = factor (try 1.5 to 2.0)

   Param             Use
   ------------------------------------
   grid              FFT grid (filled by is6_FFTTransform)
   uWidth            width in pixels
   uHeight           height

   uFilterType       see above

   pParams           array of doubles. these are the parameters
                     for the various filters.

   Return
   ------
      FALSE on failure
---------------------------------------------------------*/
_ISDeclSpec BOOL    _ISCConv _ISFn(is6_FFTFilter)(double *grid, UINT32 width, UINT32 height, UINT32 uFilterType, const double *params);

/*---------------------------------------------------------
   is6_FFTTransformInverse

   Purpose : 
   Apply the inverse FFT to the FFT grid. This prepares the
   grid for conversion back to the final grayscale image. This
   should be called AFTER all filtering operations.

   This is the third step in an FFT operation.

   See is6_FFTTransform, is6_FFTTransformInverse

   Param             Use
   ------------------------------------
   uWidth            width in pixels
   uHeight           height
   grid              FFT grid (caller allocates)

   Return
   ------
      FALSE on failure
---------------------------------------------------------*/
_ISDeclSpec BOOL    _ISCConv _ISFn( is6_FFTTransformInverse )(UINT32 uWidth, UINT32 uHeight, double *grid);

/*---------------------------------------------------------
   is6_FFTToGrayscale

   Purpose : 
   Generate a grayscale image from the FFT grid.

   This is generally the final step in an FFT operation.

   Note:
   This function can return images as BYTEs or as doubles.
   See uFlags.

   Note:
   If you haven't called is6_FFTTransformInverse yet,
   the grid will contain the image spectrum. You can
   get an image of the spectrum, if you want to display 
   it. If you do, you will probably want to set bShiftDC 
   to TRUE, in order to put the DC in the center of the 
   image.

   Param             Use
   ------------------------------------
   pOutB             output image
   grid              FFT grid (caller allocates)
   uWidth            width in pixels
   uHeight           height    
   uRowStride        number of components per pixel row

   uMode             0 : return grayscale image
                     1 : return real portion only
                     2 : return imaginary portion only

   bShiftDC          shift the quadrants to put DC 
                     in the center (see notes)

   uFlags            bit   purpose
                     ---   -------
                      10   output image is 64-bit doubles
                           else image is BYTEs

   Return
   ------
      FALSE on failure
---------------------------------------------------------*/
_ISDeclSpec BOOL    _ISCConv _ISFn( is6_FFTToGrayscale )(void * pOut, double *grid, UINT32 width, UINT32 height, UINT32 uRowStride, UINT32 uMode, BOOL bShiftDC, UINT32 uFlags);

/*---------------------------------------------------------
   is6_NextPowerOfTwo

   Purpose : 
   Find the next-highest power of two (2^x), from the input 
   value. 

   Ex.
   is6_NextPowerOfTwo(3) = 4
   is6_NextPowerOfTwo(18) = 32
   is6_NextPowerOfTwo(255) = 256
   is6_NextPowerOfTwo(256) = 512

   Use this to determine the appropriate input image size 
   for the FFT operations.

   Param             Use
   ------------------------------------
   val

   Return
   ------
      next highest power of 2
---------------------------------------------------------*/
_ISDeclSpec UINT32 _ISCConv _ISFn( is6_NextPowerOfTwo )(UINT32 val);

/*---------------------------------------------------------
   is6_DetermineImageTranslation

   Purpose : 
   Given two images, A and B, and assuming that A and B contain 
   an overlapping image area, attempt to find the horizontal and
   vertical offsets which would align the two images.

   For automated image stitching, for example.

   Param            Use
   ------------------------------------
   p8A              input grayscale image A
   wA               width of image A
   hA               height of image A
   rsA              number of components per pixel row, in A
   p8B              input grayscale image B
   wB               width of image B
   hB               height of image B
   rsB              number of components per pixel row, in B
   px               receives the x offset
   py               receives the y offset

   uFlags            bit      purpose
                     ---      -------
                      0       apply a Hamming window before
                              attempting to find the translation.
                              this can improve accuracy.

                     9-10     00 - images have 8 bits per component  (BYTE)      (val=0)
                              01 - images have 16 bits per component (ISUINT16)  (val=0x200)
                              10 - images have 64 bits per component (double)    (val=0x400)
                              11 - images have 32 bits per component (float)     (val=0x600)
   Return
   ------
      next highest power of 2
---------------------------------------------------------*/
_ISDeclSpec BOOL _ISCConv _ISFn(is6_DetermineImageTranslation)(const BYTE *p8A, UINT32 wA, UINT32 hA, UINT32 rsA,
                                                      const BYTE *p8B, UINT32 wB, UINT32 hB, UINT32 rsB,
                                                      int *px, int *py,
                                                      UINT32 uFlags);
#ifdef __cplusplus
}
#endif
