/**
	\file
	\brief Class that can store and manipulate CCD images

	\author David Motl <dmotl@volny.cz>
	
	\par Copying
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation, version 2.
	
	$Id: cmpack_image.h,v 1.1 2015/07/06 08:33:22 dmotl Exp $
*/

#ifndef _CMPACK_IMAGE_H_INCLUDED
#define _CMPACK_IMAGE_H_INCLUDED

#include "cmpack_common.h"

/********************   Public data types   ********************************/

/**
	\brief CCD image context 
	\details This private structure is used to keep and manipulate CCD image 
	data in memory
*/
typedef struct _CmpackImage CmpackImage;

/******************************   CmpackImage methods   ********************************/

#ifdef __cplusplus
extern "C" {
#endif

/** 
	\brief Compute number of bytes that are required to store the image 
	\details The function computes size of memory buffer required
	to store image data in given size and format
	\param[in] width			width of image in pixels
	\param[in] height			height of image in pixels
	\param[in] format			image data format
	\return pointer to new reference or zero on failure
*/
	CMPACK_EXPORT(int, cmpack_image_size, (int width, int height, CmpackBitpix format));

/**
	\brief Create a new image with internal memory buffer
	\details The function creates a new CCD image and allocates it
	according to specified parameters. The content of the image is undefined.
	\param[in] width			width of image in pixels
	\param[in] height			height of image in pixels
	\param[in] format			image data format
	\return pointer to new reference or zero on failure
*/
	CMPACK_EXPORT(CmpackImage*, cmpack_image_new, (int width, int height, CmpackBitpix format));

/**
	\brief Create a new image that uses given memory buffer
	\details The function creates a new CCD image. The image will use given
	memory buffer which must be big enough to hold the image data. The buffer
	is not freed when the image is destroyed.
	\param[in] width			width of image in pixels
	\param[in] height			height of image in pixels
	\param[in] format			image data format
	\param[in] data				image buffer
	\param[in] datalen			size of image buffer in bytes
	\return pointer to new reference or zero on failure
*/
	CMPACK_EXPORT(CmpackImage*, cmpack_image_from_data, (int width, int height, CmpackBitpix format,
		void* data, int datalen));

/**
	\brief Create a new empty image.
	\details The function creates an empty new CCD image. The dimensions
	of the image are zero, the format is undefined.
	\return pointer to new reference or zero on failure
*/
	CMPACK_EXPORT(CmpackImage*, cmpack_image_new_empty, (void));

/**
	\brief Make a new reference to the CCD image
	\details The function makes a new reference to the image and returns a 
	pointer to it. The reference counter is incremented by one. The caller 
	is responsible to call cmpack_image_destroy() when the reference is 
	no longer needed.
	\param[in]	img				image context
	\return pointer to a new reference
*/
	CMPACK_EXPORT(CmpackImage*, cmpack_image_reference, (CmpackImage* img));

/**
	\brief Make copy of the image
	\details The function makes deep copy of the source image to 
	the target image.
	\param[in] src				source image context
	\return new CmpackImage object
*/
	CMPACK_EXPORT(CmpackImage*, cmpack_image_copy, (const CmpackImage* src));

/**
	\brief Release a reference to the CCD image
	\details The function releases a reference to the image. The reference 
	counter is decreased by one and when it was the last reference to the 
	image, the object is released from the memory.
	\param[in]	img				image context
*/
	CMPACK_EXPORT(void, cmpack_image_destroy, (CmpackImage* img));

/**
	\brief Get width of the image
	\details The function retrieves the width of the CCD frame in pixels.
	\param[in] img				image context
	\return image width in pixels
*/
	CMPACK_EXPORT(int, cmpack_image_width, (const CmpackImage* img));

/**
	\brief Get height of the image
	\details The function retrieves the height of the CCD frame in pixels.
	\param[in] img				image context
	\return image height in pixels
*/
	CMPACK_EXPORT(int, cmpack_image_height, (const CmpackImage* img));

/**
	\brief Get image data format
	\details The function returns a value (one of CMPACK_BITPIX_xxx constants)
	that indicates in which format the image data are stored in the memory.
	\param[in] img				image context
	\return image data type on success, zero on failure
*/
	CMPACK_EXPORT(CmpackBitpix, cmpack_image_bitpix, (const CmpackImage* img));

/**
	\brief Get pointer to the image data
	\details The function returns a pointer to the allocated memory block 
	that holds the image data. The pixels are stored row by row, without 
	padding.
	\param[in] img				image context
	\return pointer to image data or NULL if the image is empty
*/
	CMPACK_EXPORT(void*, cmpack_image_data, (CmpackImage* img));

/**
	\brief Get const pointer to the image data
	\details The function returns a pointer to the allocated memory block 
	that holds the image data. The pixels are stored row by row, without 
	padding.
	\param[in] img				image context
	\return pointer to image data or NULL if the image is empty
*/
	CMPACK_EXPORT(const void*, cmpack_image_const_data, (const CmpackImage* img));

/**
	\brief Get single pixel value
	\details The function retrieves value of a single pixel
	\return pixel value or zero on failure
*/
	CMPACK_EXPORT(double, cmpack_image_getpixel, (const CmpackImage* img, int x, int y));

/**
	\brief Convert image data to another format
	\details The function converts the source image to specified format
	\param[in] img				source image
	\param[in] format			new image format
	\return new CmpackImage object
*/
	CMPACK_EXPORT(CmpackImage*, cmpack_image_convert, (const CmpackImage* img, CmpackBitpix format));

/**
	\brief Pixel binning
	\details The function sums blocks of pixels in the source image
	and stores the output to the target image.
	\param[in] src				source image
	\param[in] hbin				number of columns merged together
	\param[in] vbin				number of rows merged together
	\return new CmpackImage object
*/
	CMPACK_EXPORT(CmpackImage*, cmpack_image_binning, (const CmpackImage* src, int hbin, int vbin));

/**
	\brief Image transformation using a matrix
	\details The function transforms an image
	\param[in] src				source image
	\param[in] nulvalue			pixel value below valid range
	\param[in] badvalue			pixel value above valid range
	\param[in] border			image border (can be NULL)
	\param[in] matrix			transformation matrix
	\return new CmpackImage object
*/
	CMPACK_EXPORT(CmpackImage*, cmpack_image_matrix_transform, (const CmpackImage* src, double nulvalue,
		double badvalue, const CmpackBorder* border, const CmpackMatrix* matrix));

/**
	\brief Transpose (flip) image
	\details The function transposes the source image and stores the 
	output to the same image. Both operations may be applied simultaneously.
	\param[in] img				image context
	\param[in] hflip			nonzero = horizontal flip
	\param[in] vflip			nonzero = vertical flip
	\return zero on success, error code on failure
*/
	CMPACK_EXPORT(int, cmpack_image_transpose, (CmpackImage* img, int hflip, int vflip));

/**
	\brief Set all pixels to specified value
	\details This function is used to initialize image data
	\param[in,out] img				image context
	\param[in] value				new pixel value
	\return zero on success, error code on failure
*/
	CMPACK_EXPORT(int, cmpack_image_fill, (CmpackImage* img, double value));

/**
	\brief Set pixels inside specified region to given value
	\details This function is used to set a region to given value.
	\param[in,out] img				image context
	\param[in] left					first column to be changed
	\param[in] top					first row to be changed
	\param[in] width				number of columns to be changed
	\param[in] height				number of rows to be changed
	\param[in] value				new pixel value
	\return zero on success, error code on failure
*/
	CMPACK_EXPORT(int, cmpack_image_fillrect, (CmpackImage* img, int left, int top, int width, int height,
		double value));

/**	
	\brief Automatic brightness/contrast
	\details The function determines suitable black and white values for 
	given image data. This function is used to determine the mapping before 
	the image is presented to the user.
	\param[in] img				image context
	\param[in] nulvalue			pixel value below valid range
	\param[in] badvalue			pixel value above valid range
	\param[out] blacklevel		lower mapping limit in ADU
	\param[out] whitelevel		upper mapping limit in ADU
*/
	CMPACK_EXPORT(int, cmpack_image_autogb, (CmpackImage* img, double nulvalue, double badvalue,
		double* blacklevel, double* whitelevel));

/**	
	\brief Compute minimum and maximum pixel values
	\details The function determines the minimum and maximum pixel values.
	\param[in] img				image context
	\param[in] nulvalue			pixel value that indicates invalid pixel
	\param[in] badvalue			ignored
	\param[out] minvalue		minimum pixel value in ADU
	\param[out] maxvalue		maximum pixel value in ADU
*/
	CMPACK_EXPORT(int, cmpack_image_minmax, (CmpackImage* img, double nulvalue, double badvalue,
		double* minvalue, double* maxvalue));

/**	
	\brief Compute mean and deviation
	\details The function determines the mean value and standard deviation
	using the robust mean algorithm.
	\param[in] img				image context
	\param[in] nulvalue			pixel value that indicates invalid pixel
	\param[in] badvalue			ignored
	\param[out] mean			mean value in ADU
	\param[out] stddev			standard deviation in ADU
*/
	CMPACK_EXPORT(int, cmpack_image_meandev, (CmpackImage* img, double nulvalue, double badvalue,
		double* mean, double* stddev));

/**	
	\brief Make histogram
	\details The function makes a histogram of pixel values. The caller
	must specify number of bins, minimum pixel value and bin width.
	\param[in] img				image context
	\param[in] channel_count	number of channels
	\param[in] channel_width	width of each channel in ADU
	\param[in] zero_offset		pixel value of the first channel in ADU
	\param[out] hist			histogram data
*/
	CMPACK_EXPORT(int, cmpack_image_histogram, (CmpackImage* img, int channel_count,
		double channel_width, double zero_offset, unsigned* hist));

#ifdef __cplusplus
}
#endif

#endif
