/** @file  psPixels.h
 *
 *  @brief Contains psPixel related functions
 *
 *  @author Paul Price, IfA
 *  @author Robert DeSonia, MHPCC
 *
 *  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2007-01-23 22:47:23 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 */

#ifndef PS_PIXELS_H
#define PS_PIXELS_H

#include "psImage.h"
#include "psVector.h"
#include "psRegion.h"

/// @addtogroup DataContainer Data Containers
/// @{

/** Data structure for storing psPixel coordinates  */
typedef struct
{
    float x;                             ///< x coordinate
    float y;                             ///< y coordinate
}
psPixelCoord;

/** list of pixel coordinates
 *
 *  Usually an image mask is the best way to carry information about what
 *  pixels mean what. However, in the case where the number of pixels in which
 *  we are interested is limited, it is more efficient to simply carry a list
 *  of pixels. An example of this is in the image combination code, where we
 *  want to perform an operation on a relatively small fraction of pixels, and
 *  it is inefficient to go through an entire mask image checking each pixel.
 *
 */
typedef struct
{
    long n;                            ///< Number in use
    const long nalloc;                 ///< Number allocated
    psPixelCoord* data;                ///< The pixel coordinates
    void *lock;                        ///< Option lock for thread safety
}
psPixels;

#define P_PSPIXELS_SET_NALLOC(pix,n) *(long*)&pix->nalloc = n


        /** Allocates a new psPixels structure
         *
         *  @return psPixels*   new psPixels
         */
        psPixels* psPixelsAlloc(
            long nalloc                       ///< the size of the coordinate vectors
        )
        ;

/** Checks the type of a particular pointer.
 *
 *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
 *
 *  @return bool:       True if the pointer matches a psPixels structure, false otherwise.
 */
bool psMemCheckPixels(
    psPtr ptr                          ///< the pointer whose type to check
);


/** resizes a psPixels structure
 *
 *  @return psPixels*   resized psPixels
 */
psPixels* psPixelsRealloc(
    psPixels* pixels,                  ///< psPixels to resize, or NULL to create new psPixels
    long nalloc                        ///< the size of the coordinate vectors
);

/** Add a pixel location to a psPixels
 *
 *  Grow the psPixels input by growth.  If growth is less that 1, 10 is used.  If a NULL
 *  psPixels is given, a new one is created.
 *
 *  @return psPixels*       psPixels with the value appended.
 */
psPixels* p_psPixelsAppend(
    psPixels* pixels,                  ///< psPixels to append new coordinate to.
    long growth,                       ///< Number of elements to grow the pixels list if necessary.
    float x,                           ///< x coordinate to append
    float y                            ///< y coordinate to append
);

/** Copies a psPixels object
 *
 *  Makes a deep copy of the data in a psPixels object.  Any data in the OUT
 *  parameter will be destroyed and OUT will be resized, if necessary.
 *
 *  @return psPixels*   a new psPixels that is a duplicate to IN
 */
psPixels* psPixelsCopy(
    psPixels* out,                     ///< psPixels struct to recycle, or NULL
    const psPixels* pixels             ///< psPixels struct to copy
);

/** Generate a psImage from a psPixels
 *
 *  psPixelsToMask shall return an image of type U8 with the pixels lying
 *  within the specified region set to the maskVal. The out image shall be
 *  modified if supplied, or allocated and returned if NULL. The size of the
 *  output image shall be region->x1 - region->x0 by region->y1 - region->y0,
 *  with out->x0 = region->x0 and out->y0 = region->y0. In the event that
 *  either of pixels or region are NULL, the function shall generate an
 *  error and return NULL.
 *
 *  @return psImage*    generated mask image
 */
psImage* psPixelsToMask(
    psImage* out,                      ///< psImage to recycle, or NULL
    const psPixels* pixels,            ///< list of pixels to use
    psRegion region,                   ///< region to define the output mask image
    psMaskType maskVal                 ///< the mask bit-values to act upon
);

/** Generate a psPixels from a mask psImage
 *
 *  psMaskToPixels shall return a psPixels consisting of the coordinates in
 *  the mask that match the maskVal. The out pixel list shall be modified if
 *  supplied, or allocated and returned if NULL. In hte event that mask is
 *  NULL, the function shall generate an error and return NULL.
 *
 *  @return psPixels*   generated psPixels pixel list
 */
psPixels* psPixelsFromMask(
    psPixels *out,                     ///< psPixels to recycle, or NULL
    const psImage *mask,               ///< the input mask psImage
    psMaskType maskVal                 ///< the mask bit-values to act upon
);

/** Concatenates two psPixels
 *
 *  psPixelsConcatenate shall concatenate pixels onto out. In the event that
 *  out is NULL, a new psPixels shall be allocated, and the contents of
 *  pixels simply copied in. If pixels is NULL, the function shall generate
 *  an error and return NULL. The function shall take care to ensure that
 *  there are no duplicate pixels in out.
 *
 *  @return psPixels         Concatenated psPixel list
 */
psPixels* psPixelsConcatenate(
    psPixels *out,                     ///< psPixels to recycle, or NULL
    const psPixels *pixels             ///< psPixels to append to OUT
);

/** Prints a psPixels to specified destination.
 *
 *  @return bool:    True if successful.
*/
bool p_psPixelsPrint(
    FILE *fd,                          ///< destination file descriptor
    psPixels* pixels,                  ///< psPixels to print
    const char *name                   ///< printf-style format of header line
);

/** Sets the value of the the pixels array at the specified position to value.
 *
 *  A negative position means index from the end.
 *
 *  @return bool:       True if Successful, otherwise false.
*/
bool psPixelsSet(
    psPixels *pixels,                  ///< pixels to set
    long position,                     ///< position to set
    psPixelCoord value                 ///< pixels value to be set
);

/** Returns the value of the pixels array at the specified position.
 *
 *  A negative position means index from the end.
 *
 *  @return psPixelCoord:       The value of the pixels at the specified position.
*/
psPixelCoord psPixelsGet(
    const psPixels *pixels,            ///< input pixels from which to get
    long position                      ///< position to get
);

/** Get the number of elements in use from a specified psPixels. (pixels.n)
 *
 *  @return long:       The number of elements in use.
 */
long psPixelsLength(
    const psPixels *pixels             ///< input psPixels
);

/// @}
#endif // #ifndef PS_PIXELS_H
