/** \file
 * \brief Utilities
 *
 * See Copyright Notice in im_lib.h
 * $Id: Exp $
 */

#ifndef __IM_UTIL_H
#define __IM_UTIL_H

#if	defined(__cplusplus)
extern "C" {
#endif


/** \defgroup util Utilities
 * \par
 * See \ref im_util.h
 * @{
 */

#define IM_MIN(_a, _b) (_a < _b? _a: _b)
#define IM_MAX(_a, _b) (_a > _b? _a: _b)

/** @} */


/** \defgroup str String Utilities
 * \par
 * See \ref im_util.h
 * \ingroup util */

/** Check if the two strings are equal.
 * \ingroup str */
int imStrEqual(const char* str1, const char* str2);

/** Calculate the size of the string but limited to max_len.
 * \ingroup str */
int imStrNLen(const char* str, int max_len);

/** Check if the data is a string.
 * \ingroup str */
int imStrCheck(const void* data, int count);



/** \defgroup imageutil Image Utilities
 * \par
 * See \ref im_util.h
 * \ingroup imagerep */

/** Returns the size of the data buffer.
 * \ingroup imageutil */
int imImageDataSize(int width, int height, int color_mode, int data_type);

/** Returns the size of one line of the data buffer. \n
 * This depends if the components are packed. If packed includes all components, if not includes only one.
 * \ingroup imageutil */
int imImageLineSize(int width, int color_mode, int data_type);

/** Returns the number of elements of one line of the data buffer. \n
 * This depends if the components are packed. If packed includes all components, if not includes only one.
 * \ingroup imageutil */
int imImageLineCount(int width, int color_mode);

/** Check the combination color_mode+data_type.
 * \ingroup imageutil */
int imImageCheckFormat(int color_mode, int data_type);



/** \defgroup colorutl Color Utilities
 * \par
 * See \ref im_util.h
 * \ingroup util */

/** Encode RGB components in a long for palete usage. \n
 * "long" definition is compatible with the CD library definition.
 * \ingroup colorutl */
long imColorEncode(unsigned char red, unsigned char green, unsigned char blue);

/** Decode RGB components from a long for palete usage. \n
 * "long" definition is compatible with the CD library definition.
 * \ingroup colorutl */
void imColorDecode(unsigned char *red, unsigned char *green, unsigned char *blue, long color);



/** \defgroup colormodeutl Color Mode Utilities
 * \par
 * See \ref im_util.h
 * \ingroup imagerep */

/** Returns the color mode name.
 * \ingroup colormodeutl */
const char* imColorModeSpaceName(int color_mode);

/** Returns the number of components of the color space including alpha.
 * \ingroup colormodeutl */
int imColorModeDepth(int color_mode);

/** Returns the color space of the color mode.
 * \ingroup colormodeutl */
#define imColorModeSpace(_cm) (_cm & 0xFF)

/** Check if the two color modes match. Only the color space is compared.
 * \ingroup colormodeutl */
#define imColorModeMatch(_cm1, _cm2) (imColorModeSpace(_cm1) == imColorModeSpace(_cm2))

/** Check if the color mode has an alpha channel.
 * \ingroup colormodeutl */
#define imColorModeHasAlpha(_cm) (_cm & IM_ALPHA)

/** Check if the color mode components are packed in one plane.
 * \ingroup colormodeutl */
#define imColorModeIsPacked(_cm) (_cm & IM_PACKED)

/** Check if the color mode orients the image from top down to bottom.
 * \ingroup colormodeutl */
#define imColorModeIsTopDown(_cm) (_cm & IM_TOPDOWN)

/** Returns the color mode of the equivalent display bitmap image. \n
 * Original packing and alpha are ignored. Returns IM_RGB, IM_GRAY, IM_MAP or IM_BINARY.
 * \ingroup colormodeutl */
int imColorModeToBitmap(int color_mode);

/** Check if the color mode and data_type defines a display bitmap image.
 * \ingroup colormodeutl */
int imColorModeIsBitmap(int color_mode, int data_type);



/** \defgroup datatypeutl Data Type Utilities
 * \par
 * See \ref im_util.h
 * \ingroup util
 * @{
 */

typedef unsigned char imbyte;
typedef unsigned short imushort;

#define IM_BYTECROP(_v) (_v < 0? 0: _v > 255? 255: _v)
#define IM_CROPMAX(_v, _max) (_v < 0? 0: _v > _max? _max: _v)

/** @} */

/** Returns the size in bytes of a specified numeric data type.
 * \ingroup datatypeutl */
int imDataTypeSize(int data_type);

/** Returns the numeric data type name given its identifier.
 * \ingroup datatypeutl */
const char* imDataTypeName(int data_type);

/** Returns the maximum value of an integer data type. For floating point returns 0.
 * \ingroup datatypeutl */
unsigned long imDataTypeIntMax(int data_type);

/** Returns the minimum value of an integer data type. For floating point returns 0. 
 * \ingroup datatypeutl */
long imDataTypeIntMin(int data_type);
           


/** \defgroup bin Binary Data Utilities
 * \par
 * See \ref im_util.h
 * \ingroup util */

/** CPU Byte Orders. 
  * \ingroup bin */
enum imByteOrder
{
  IM_LITTLEENDIAN, /**< Little Endian - The most significant byte is on the right end of a word. Used by Intel processors. */
  IM_BIGENDIAN     /**< Big Endian - The most significant byte is on the left end of a word. Used by Motorola processors, also is the network standard byte order. */
};

/** Returns the current CPU byte order.
 * \ingroup bin */
int imBinCPUByteOrder(void);

/** Changes the byte order of an array of 2, 4 or 8 byte values.
 * \ingroup bin */
void imBinSwapBytes(void *data, int count, int size);

/** Changes the byte order of an array of 2 byte values.
 * \ingroup bin */
void imBinSwapBytes2(void *data, int count);

/** Inverts the byte order of the 4 byte values 
 * \ingroup bin */
void imBinSwapBytes4(void *data, int count);
            
/** Inverts the byte order of the 8 byte values 
 * \ingroup bin */
void imBinSwapBytes8(void *data, int count);



/** \defgroup compress Data Compression Utilities
 * \par
 * See \ref im_util.h
 * \ingroup util */

/** Compresses the data using the ZLIB Deflate compression. \n
 * The destination buffer must be at least 0.1% larger than source_size plus 12 bytes. \n
 * It compresses raw byte data. zip_quality can be 1 to 9. \n
 * Returns the size of the compressed buffer.
 * \ingroup compress */
int imCompressDataZ(const void* src_data, int src_size, void* dst_data, int dst_size, int zip_quality);

/** Uncompresses the data compressed with the ZLIB Deflate compression.
 * \ingroup compress */
int imCompressDataUnZ(const void* src_data, int src_size, void* dst_data, int dst_size);


#if defined(__cplusplus)
}
#endif

#endif 
