
/** @file  psImageManip.h
 *
 *  @brief Contains basic image pixel and geometry manipulation operations, as
 *         specified in the PSLIB SDRS sections "Image Pixel Manipulations" and
 *         "Image Geometry Manipulations".
 *
 *  @ingroup Image
 *
 *  @author Robert DeSonia, MHPCC
 *  @author Ross Harman, MHPCC
 *
 *  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2005-03-22 21:52:49 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 */
#ifndef PS_IMAGE_MANIP_H
#define PS_IMAGE_MANIP_H

#include "psImage.h"
#include "psCoord.h"

/// @addtogroup Image
/// @{

/** Clip image values outside of range to given values
 *
 *  All pixels with values less than min are set to the value vmin.  all pixels
 *  with values greater than max are set to the value vmax. This function is
 *  defined for psU8, psU16, psS8, psS16, psF32, psF64, psC32, and psC64.
 *
 *  @return psS32     The number of clipped pixels
 */
psS32 psImageClip(
    psImage* input,                    ///< the image to clip
    psF64 min,                         ///< the minimum image value allowed
    psF64 vmin,                        ///< the value pixels < min are set to
    psF64 max,                         ///< the maximum image value allowed
    psF64 vmax                         ///< the value pixels > max are set to
);

/** Clip image values outside of a specified complex region
 *
 *  All pixels outside of the rectangular region in complex space formed by
 *  the min and max input parameters are set to the value vmax (if either
 *  the real or imaginary portion exceeds the respective max values), or vmin.
 *  This function is defined for psC32, and psC64 imagery only.
 *
 *  @return psS32     The number of clipped pixels
 */
psS32 psImageClipComplexRegion(
    psImage* input,                    ///< the image to clip
    psC64 min,                         ///< the minimum image value allowed
    psC64 vmin,                        ///< the value pixels < min are set to
    psC64 max,                         ///< the maximum image value allowed
    psC64 vmax                         ///< the value pixels > max are set to
);

/** Clip NaN image pixels to given value.
 *
 *  Pixels with NaN, +Inf, or -Inf values are set to the specified value. This
 *  function is defined for psF32, psF64, psC32, and psC64.
 *
 *  @return psS32     The number of clipped pixels
 */
psS32 psImageClipNaN(
    psImage* input,                    ///< the image to clip
    psF64 value                        ///< the value to set all NaN/Inf values to
);

/** Overlay subregion of image with another image
 *
 *  Replace the pixels in the image which correspond to the pixels in OVERLAY
 *  with values derived from the IMAGE and OVERLAY based on the given operator
 *  OP.  Valid operators are "=" (set image value to OVERLAY value), "+" (add
 *  OVERLAY value to image value), "-" (subtract OVERLAY from image), "*"
 *  (multiply OVERLAY times image), "/" (divide image by OVERLAY).  This
 *  function is defined for psU8, psS8, psS16, psF32, psF64, psC32, and psC64.
 *
 *  @return psS32         0 if success, non-zero if failed.
 */
psS32 psImageOverlaySection(
    psImage* image,                    ///< target image
    const psImage* overlay,            ///< the overlay image
    psS32 col0,                        ///< the column to start overlay
    psS32 row0,                        ///< the row to start overlay
    const char *op                     ///< the operation to perform for overlay
);

/** Rebin image to new scale.
 *
 *  A new image is constructed in which the dimensions are reduced by a factor of
 *  1/scale.  The scale, always a positive number, is equal in each dimension and
 *  specified the number of pixels used to define a new pixel in the output image.
 *  The output image is generated from all input image pixels. This function is
 *  defined for psU8, psS8, psS16, psF32, psF64, psC32, and psC64.
 *
 *  @return psImage    new image formed by rebinning input image.
 */
psImage* psImageRebin(
    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
    const psImage* in,                 ///< input image
    const psImage* mask,               ///< mask for input image.  If NULL, no masking is done.
    psMaskType maskVal,                ///< the bits to check in mask.
    psU32 scale,                       ///< the scale to rebin for each dimension
    const psStats* stats
    ///< the statistic to perform when rebinning.  Only one method should be set.
);

/** Resample image to new scale.
 *
 *  A new image is constructed in which the dimensions are increased by a
 *  factor of scale. The scale, always a positive number, is equal in each
 *  dimension. The output image is generated from all input image pixels.
 *  Each pixel in the output image is derived by interpolating between
 *  neighboring pixels using the specified interpolation method (mode).
 *
 *  @return psImage*    resampled image result
 */
psImage* psImageResample(
    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
    const psImage* in,                 ///< input image
    psS32 scale,                       ///< resample scaling factor
    psImageInterpolateMode mode        ///< the interpolation mode used in resampling
);

/** Rotate the input image by given angle, specified in degrees.
 *
 *  The output image must contain all of the pixels from the input image in
 *  their new frame. Pixels in the output image which do not map to input
 *  pixels should be set to exposed. The center of rotation is always the
 *  center pixel of the image. The rotation is specified in the sense that a
 *  positive angle is an anti-clockwise rotation. This function must be
 *  defined for the following types: psU8, psU16, psS8, psS16, psF32, psF64,
 *  psC32, psC64.
 *
 *  @return psImage*     the rotated image result.
 */
psImage* psImageRotate(
    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
    const psImage* in,                 ///< input image
    float angle,                       ///< the rotation angle in radians.
    psC64 unexposedValue,              ///< the output image pixel values for non-imagery areas
    psImageInterpolateMode mode        ///< the interpolation mode used
);

/** Shift image by an arbitrary number of pixels (dx,dy) in either direction.
 *
 *  If the shift values are fractional, the output pixel values should
 *  interpolate between the input pixel values. The output image has the same
 *  dimensions as the input image. Pixels which fall off the edge of the
 *  output image are lost. Newly exposed pixels are set to the value given by
 *  exposed. This function must be defined for the following types: psU8,
 *  psU16, psS8, psS16, psF32, psF64, psC32, psC64.
 *
 *  @return psImage*     the shifted image result.
 */
psImage* psImageShift(
    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
    const psImage* in,                 ///< input image
    float dx,                          ///< the shift in x direction.
    float dy,                          ///< the shift in y direction.
    psC64 unexposedValue,              ///< the output image pixel values for non-imagery areas
    psImageInterpolateMode mode        ///< the interpolation mode to use
);

/** Roll image by an integer number of pixels in either direction.
 *
 *  The output image is the same dimensions as the input image.  Edge pixels
 *  wrap to the other side (no values are lost).  This function is
 *  defined for psU8, psS8, psS16, psF32, psF64, psC32, and psC64.
 *
 *  @return psImage* the rolled version of the input image.
 */
psImage* psImageRoll(
    psImage* out,                      ///< an psImage to recycle.  If NULL, a new image is created
    const psImage* in,                 ///< input image
    psS32 dx,                          ///< number of pixels to roll in the x-dimension
    psS32 dy                           ///< number of pixels to roll in the y-dimension
);

/** Transform the input image according the supplied transformation.
 *
 *  Transform the input image according the supplied transformation. In the
 *  event that the output is NULL, the smallest possible image capable of
 *  containing the entire transformed input image is to be returned; otherwise
 *  only the image size specified in the output image is to be used. If the
 *  inputMask is not NULL, those pixels in the inputMask matching inputMaskVal
 *  are to be ignored in the transformation. The inputMask must be of type
 *  psU8, and of the same size as the input, otherwise the function shall
 *  generate an error and return NULL. The transformation outToIn specifies
 *  the coordinates in the input image of a pixel in the output image - note
 *  that this is the reverse of what might be naively expected, but it is what
 *  is required in order to use psImagePixelInterpolate. If combineMask is not
 *  NULL, then those pixels that match combineMaskVal are not transformed.
 *  combineMask must be of type psU8 and of the same size as the output,
 *  otherwise the function shall generate an error and return NULL. This
 *  function must be capable of handling the following types for the input
 *  (with corresponding types for the output): psF32, psF64.
 *
 *  @return psImage*    The transformed image.
 */
psImage* psImageTransform(
    psImage *output,                   ///< psImage to recycle, or NULL
    const psImage *input,              ///< psImage to apply transform to
    const psImage *inputMask,          ///< if not NULL, mask of input psImage
    int inputMaskVal,                  ///< masking value for inputMask
    const psPlaneTransform *outToIn,   ///< the transform to apply
    const psImage *combineMask,        ///< if not NULL, mask of pixels not to be transformed
    int combineMaskVal                 ///< masking value for combineMask
);

#endif
