/*
Copyright (c) 2005-2008, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  its contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

/**	@file dkbif.h API to access bitmap images.
	This module provides a simple unique API to access bitmap
	image files. This module does not open the files directly, it
	uses other libraries (libpng, jpeglib, tifflib and NetPBM).

	Two steps are necessary to read a file:
	- Read image header information.
	  The image header typically contains width, height, number of
	  channels, number of bits per component...
	- Read image data.

	An alpha channel in the image can be used to either mix against
	a background color and/or to create an image mask. You can provide
	a default background color. If the input image contains background
	color information you can choose to eigher use background information
	from input file or to use a default color you have specified.

	If you want to change the number of bits per component the dkbif
	library can do this for you.
*/

#ifndef DKBIF_H_INCLUDED
#define DKBIF_H_INCLUDED 1

#include <stdio.h>
#include "dk.h"
#include "dkstream.h"
#include "dkapp.h"



/**	Pointer to structure representing an image file.
*/
typedef void *dk_bif_ptr;

/**	Pointer to structure representing an image frame.
*/
typedef void *dk_bif_frame_ptr;



/**	JPEG/JFIF SOF type.
*/
typedef unsigned dk_bif_sof_t;



/**	Structure for direct analysis of JPEG files.
*/
typedef struct {
  /* input variables */
  FILE		*inputfile;	/**< Name of file to anlayze/convert. */
  /* output variables */
  int		 is_jfif;	/**< JFIF_RESULT_xxx, result of analysis. */
  dk_stream_t	*os;		/**< Output stream. */
  dk_app_t	*a;		/**< Application, used for error messages. */
  unsigned char	 vers_major;	/**< Major version number. */
  unsigned char	 vers_minor;	/**< Minor version number. */
  unsigned char	 dpi_setting;	/**< Flag, resolution in dpi found. */
  unsigned char	 bpc;		/**< Number of bits per component. */
  unsigned char	 components;	/**< Number of components. */
  unsigned char	 adobe_marker_found;	/**< Flag, Adobe marker found. */
  unsigned	 width;		/**< Image width. */
  unsigned	 height;	/**< Image height. */
  unsigned	 xres;		/**< X resolution. */
  unsigned	 yres;		/**< Y resolution. */
  dk_bif_sof_t	 used_sofs;	/**< SOF markers used in the image. */
  unsigned long	 n_sofs;	/**< Number of SOFs in the image. */
  unsigned long	 n_images;	/**< Number of frames. */
} dk_bif_jfif_analyze_t;

#if defined(EXTERN)
#undef EXTERN
#endif
#if DKBIF_C
#define EXTERN /* nix */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif



/**	Check whether the dkbif library can handle a file.
	The test is only based on a file name suffix inspection.
	@param	n	File name.
	@return	Flag to indicate whether the file can be handled.
*/
EXTERN int
dkbif_can_handle_name DK_PR((char *n));



/**	Create new image structure.
	The image structure is created in dynamically allocated memory.
	Call dkbif_close() to destroy the structure and release memory
	after usage.
	@return	Pointer to new image structure.
*/
EXTERN dk_bif_ptr
dkbif_open DK_PR((void));



/**	Destroy image structure and release memory.
	@param	i	Pointer to image structure.
*/
EXTERN void
dkbif_close DK_PR((dk_bif_ptr i));



/**	Get numeric key to represent the image type based on the file
	name suffix.
	@param	n	Image file name.
	@return	Image type (DKBIF_TYPE_PNG, DKBIF_TYPE_JPG, DKBIF_TYPE_NETPBM
			or DKBIF_TYPE_TIFF) on success, DKBIF_TYPE_UNKNOWN
			on error (Failed to find image type).
*/
EXTERN int
dkbif_get_type DK_PR((char *n));



/**	Check whether an image file type can be handled.
	@param	s	Image file type as obtained from dkbif_get_type().
	@return	Flag to indicate whether the file type can be handled.
*/
EXTERN int
dkbif_can_handle DK_PR((int s));



/**	Set "width and height sufficient" flag for image structure.
	If this flag is set, in the following call(s) to dkbif_read_header() 
	it is sufficient to find width and height of the image, no other
	information is needed. This might be useful for applications
	showing bounding box information only or printing placeholders
	in document drafts.
	@param	i	Pointer to image structure.
	@param	f	New flag value.
*/
EXTERN void
dkbif_set_width_height_sufficient DK_PR((dk_bif_ptr i, int f));



/**	Read image file header into image structure.
	Some image libraries provide functions to read an image from
	using a FILE * pointer, other image libraries have functions
	taking a file name as argument. If necessary
	the contents of \a f is transferred into a new file \a t,
	and the file name \a t is passed to functions requiring a file name.
	@param	i	Pointer to image structure.
	@param	f	Input file, must be opened in binary mode.
	@param	n	Input file name.
	@param	s	Suffix type as returned from dkbif_get_type().
	@param	t	File name for a temporary file.
	@return	Flag to indicate success.
*/
EXTERN int
dkbif_read_header DK_PR((\
dk_bif_ptr i, FILE *f, char *n, int s, char *t));



/**	Read image data.
	Call this function after dkbif_read_header() and only if
	dkbif_read_header() returned successfully.
	@param	i	Pointer to image structure.
	@param	f	Pointer to input file.
	@return	Flag to indicate success.
*/
EXTERN int
dkbif_read_data DK_PR((dk_bif_ptr i, FILE *f));



/**	Get number of frames in image.
	@param	i	Pointer to image structure.
	@return	The number of frames (pictures) in the image file.
*/
EXTERN unsigned long
dkbif_number_of_frames DK_PR((dk_bif_ptr i));



/**	Set current frame.
	All subsequent functions to get pixel information or width/height
	will access the frame.
	The first frames index is 0.
	@param	i	Pointer to image structure.
	@param	f	Frame index.
	@return	Flag to indicate success.
*/
EXTERN int
dkbif_set_frame DK_PR((dk_bif_ptr i, unsigned long f));



/**	Get number of color channels in the current frame.
	- 1 = gray
	- 2 = gray + alpha
	- 3 = rgb
	- 4 = rgb + alpha
	@param	i	Pointer to image structure.
	@return	The number of color channels in the current frame of the image.
*/
EXTERN int
dkbif_get_channels DK_PR((dk_bif_ptr i));



/**	Get width of current frame in pixels.
	@param	i	Pointer to image structure.
	@return	The width of the current frame in pixels.
*/
EXTERN unsigned long
dkbif_get_width DK_PR((dk_bif_ptr i));



/**	Get height of current frame in pixels.
	@param	i	Pointer to image structure.
	@return	The image height in pixels.
*/
EXTERN unsigned long
dkbif_get_height DK_PR((dk_bif_ptr i));



/**	Check whether the image contains resolution information.
	@param	i	Pointer to image structure.
	@return	Flag to indicate the presence of resolution information.
*/
EXTERN int
dkbif_get_must_scale DK_PR((dk_bif_ptr i));



/**	Get width of current frame.
	@param	i	Pointer to image structure.
	@return	The width of the current frame, either in:
	- PS points\n
	  if the image contains resolution information or
	- pixels.
*/
EXTERN double
dkbif_get_real_width DK_PR((dk_bif_ptr i));



/**	Get height of current frame.
	@param	i	Pointer to image structure.
	@return	The width of the current frame, either in:
	- PS points\n
	  if the image contains resolution informaton or
	- pixels.
*/
EXTERN double
dkbif_get_real_height DK_PR((dk_bif_ptr i));



/**	Get number of bits per component for current frame.
	@param	i	Pointer to image structure.
	@return	Number of bits per component.
*/
EXTERN unsigned short
dkbif_get_bits_per_component DK_PR((dk_bif_ptr i));



/**	Set number of bits per component.
	If your application requires another number of bits per component
	than available in the image file, use this function to require
	a conversion.
	@param	i	Pointer to image structure.
	@param	b	Number of bits per component required.
	@return	Flag to indicate success.
*/
EXTERN int
dkbif_set_bits_per_component DK_PR((dk_bif_ptr i, unsigned short b));



/**	Set background color for mixing.
	@param	i	Pointer to image structure.
	@param	f	Mix decision:
	- 0\n
	  no mixing,
	- 1\n
	  mixing, prefer image background information over the colors
	  specified here or
	- 2\n
	  mixing, always use the background color specified here.
	@param	r	Red component of background color.
	@param	g	Green component of background color.
	@param	b	Blue component of background color.
	@return	Flag to indicate success.
*/
EXTERN int
dkbif_set_mixing DK_PR((dk_bif_ptr i, int f, double r, double g, double b));



/**	Set trigger level to create an image mask.
	@param	i	Pointer to image structure.
	@param	l	Trigger level (0.0-1.0).
	@return	Flag to indicate success.
*/
EXTERN int
dkbif_set_mask_trigger_level DK_PR((dk_bif_ptr i, double l));



/**	Get red value for pixel.
	@param	i	Pointer to image structure.
	@param	x	X position of the pixel.
	@param	y	Y position of the pixel.
	@return	Red component of the pixel.
*/
EXTERN unsigned short
dkbif_get_red DK_PR((dk_bif_ptr i, unsigned long x, unsigned long y));




/**	Get green value for pixel.
	@param	i	Pointer to image structure.
	@param	x	X position of the pixel.
	@param	y	Y position of the pixel.
	@return	Green component of the pixel.
*/
EXTERN unsigned short
dkbif_get_green DK_PR((dk_bif_ptr i, unsigned long x, unsigned long y));



/**	Get blue value for pixel.
	@param	i	Pointer to image structure.
	@param	x	X position of the pixel.
	@param	y	Y position of the pixel.
	@return	Blue component of the pixel.
*/
EXTERN unsigned short
dkbif_get_blue DK_PR((dk_bif_ptr i, unsigned long x, unsigned long y));



/**	Get gray value for pixel.
	@param	i	Pointer to image structure.
	@param	x	X position of the pixel.
	@param	y	Y position of the pixel.
	@return	Gray component of the pixel.
*/
EXTERN unsigned short
dkbif_get_gray DK_PR((dk_bif_ptr i, unsigned long x, unsigned long y));



/**	Get alpha value for pixel.
	@param	i	Pointer to image structure.
	@param	x	X position of the pixel.
	@param	y	Y position of the pixel.
	@return	Alpha component of the pixel.
*/
EXTERN unsigned short
dkbif_get_alpha DK_PR((dk_bif_ptr i, unsigned long x, unsigned long y));



/**	Get mask value for pixel.
	@param	i	Pointer to image structure.
	@param	x	X position of the pixel.
	@param	y	Y position of the pixel.
	@return	Mask value of the pixel.
*/
EXTERN unsigned short
dkbif_get_mask DK_PR((dk_bif_ptr i, unsigned long x, unsigned long y));



/**	Allow/deny the use of fast NTSC color to grayscale conversion.
	By default the formula\n
	g = 0.3 * r + 0.59 * g + 0.11 b\n
	in floating point arithmetics is used to convert colors to grayscale.
	The formula\n
	g = (54 * r + 183 * g + 19 * b) >> 8\n
	in integer arithmetics is probably faster but results may differ
	from the floating point result.
	@param	i	Pointer to image structure.
	@param	f	Flag to enable fast integer calculation.
*/
EXTERN void
dkbif_allow_fast_ntsc DK_PR((dk_bif_ptr i, int f));



/**	Get horizontal scale factor.
	@param	i	Pointer to image structure.
	@return	The horizontal scale factor needed to fit PS output into
	an area specified by the resolution information in the image file.
*/
EXTERN double
dkbif_get_sf_x DK_PR((dk_bif_ptr i));



/**	Get vertical scale factor.
	@param	i	Pointer to image structure.
	@return	The vertical scale factor needed to fit PS
	output into an area specified by the resolution information in
	the image file.
*/
EXTERN double
dkbif_get_sf_y DK_PR((dk_bif_ptr i));



/**	Get license information and information about used libraries.
	@return	Pointer to array of pointers to strings.
	The last pointer in the array is a NULL pointer.
*/
EXTERN char **
dkbif_lic_get DK_PR((void));



#if defined(__cplusplus)
}
#endif

#if defined(EXTERN)
#undef EXTERN
#endif

#if defined(DKBIFJA_C)
#define EXTERN /* nix */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif



/**	Attempt to analyze JPEG/JFIF file.
	@param	a	Pointer to JFIF analysis structure.
	Before starting an analysis the inputfile component of the structure
	must be set.
	
	After a successful analysis the is_jfif component is set
	to JFIF_RESULT_OK (or JFIF_RESULT_PROBLEMATIC if SOF markers
	other than SOF_0 or SOF_1 were found),
	the other components are set as follows:
	- vers_major\n
	  Major version number, (must be 0x01).
	- vers_minor\n
	  Minor version number, (must be 0x01 or 0x02).
	- width\n
	  Image width in pixels.
	- height\n
	  Image height in pixels.
	- dpi_setting\n
	  Flag to indicate whether resolution information was found.
	- xres\n
	  X resolution in dpi (only if dpi_setting is set).
	- yres
	  Y resolution in dpi (only if dpi_setting is set).
	- bpc\n
	  Number of bits per component.
	- components\n
	  Number of components (color channels), must be
	  - 1 for grayscaled images,
	  - 3 for RGB images or
	  - 4 for CMYK images.
	- adobe_marker_found\n
	  Flag to indicate the string ``Adobe'' was found in an application
	  tag 14.
	- used_sofs\n
	  Flag set to indicate which SOF(s) type(s) are used in the image.
	- n_sofs\n
	  Number of SOF markers found (must be 1, otherwise the analysis
	  fails).
	- n_images\n
	  Number of frames (must be 1, otherwise the analysis fails).
	
*/
EXTERN void
dkbif_jfif_analyze DK_PR((dk_bif_jfif_analyze_t *a));



/**	Test bit for a SOF marker in a SOF marker flag set.
	@param	f	SOF marker flag set.
	@param	s	SOF type to test (0-15).
	@return	Flag to indicate the bit was set.
*/
EXTERN int
dkbif_jfif_get_sof DK_PR((dk_bif_sof_t f, int s));



/**	Set bit for a SOF marker in a SOF marker flag set.
	@param	f	SOF marker flag set.
	@param	s	SOF type to add.
	@return	New SOF marker flag set.
*/
EXTERN dk_bif_sof_t
dkbif_jfif_set_sof DK_PR((dk_bif_sof_t f, int s));



/**	Transfer contents of JFIF file to stream.
	@param	o	Destination stream.
	@param	i	Source file.
*/
EXTERN void
dkbif_jfif_transfer DK_PR((dk_stream_t *o, FILE *i));



#if defined(__cplusplus)
}
#endif


/** Unknown file type */
#define DKBIF_TYPE_UNKNOWN		0

/** File type PNG */
#define DKBIF_TYPE_PNG			1

/** File type JPEG */
#define DKBIF_TYPE_JPG			2

/** File type NetPBM */
#define DKBIF_TYPE_NETPBM		3

/** File type TIFF */
#define DKBIF_TYPE_TIFF			4


/** Flag for SOF_0 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF0	0x0001

/** Flag for SOF_1 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF1	0x0002

/** Flag for SOF_2 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF2	0x0004

/** Flag for SOF_3 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF3	0x0008

/** Flag for SOF_5 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF5	0x0010

/** Flag for SOF_6 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF6	0x0020

/** Flag for SOF_7 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF7	0x0040

/** Flag for SOF_8 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF8	0x0080

/** Flag for SOF_9 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF9	0x0100

/** Flag for SOF_10 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF10	0x0200

/** Flag for SOF_11 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF11	0x0400

/** Flag for SOF_13 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF13	0x0800

/** Flag for SOF_14 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF14	0x1000

/** Flag for SOF_15 in dk_bif_sof_t */
#define DKBIF_JFIF_SOF15	0x2000

/** Marker for SOF_0 in JPEG/JFIF file */
#define	DKBIF_I_SOF0		0x00C0

/** Marker for SOF_1 in JPEG/JFIF file */
#define	DKBIF_I_SOF1		0x00C1

/** Marker for SOF_2 in JPEG/JFIF file */
#define	DKBIF_I_SOF2		0x00C2

/** Marker for SOF_3 in JPEG/JFIF file */
#define	DKBIF_I_SOF3		0x00C3

/** Marker for SOF_5 in JPEG/JFIF file */
#define	DKBIF_I_SOF5		0x00C5

/** Marker for SOF_6 in JPEG/JFIF file */
#define	DKBIF_I_SOF6		0x00C6

/** Marker for SOF_7 in JPEG/JFIF file */
#define	DKBIF_I_SOF7		0x00C7

/** Marker for SOF_8 in JPEG/JFIF file */
#define	DKBIF_I_SOF8		0x00C8

/** Marker for SOF_9 in JPEG/JFIF file */
#define	DKBIF_I_SOF9		0x00C9

/** Marker for SOF_10 in JPEG/JFIF file */
#define	DKBIF_I_SOF10		0x00CA

/** Marker for SOF_11 in JPEG/JFIF file */
#define	DKBIF_I_SOF11		0x00CB

/** Marker for SOF_13 in JPEG/JFIF file */
#define	DKBIF_I_SOF13		0x00CD

/** Marker for SOF_14 in JPEG/JFIF file */
#define	DKBIF_I_SOF14		0x00CE

/** Marker for SOF_15 in JPEG/JFIF file */
#define	DKBIF_I_SOF15		0x00CF

#endif

