/*
Copyright (c) 2000-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
  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.
*/

#ifndef DKBIFI_H_INCLUDED
#define DKBIFI_H_INCLUDED

#include "dk.h"

#if DK_HAVE_STRING_H
#include <string.h>
#else
#if DK_HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include <stdio.h>
#if DK_HAVE_SETJMP_H
#if !DK_HAVE_PNG_H
#include <setjmp.h>
#endif
#endif
#if DK_HAVE_MATH_H
#include <math.h>
#endif

#if DK_HAVE_ZLIB_H
#include <zlib.h>
#if DK_HAVE_PNG_H
#include <png.h>
#endif
/* if DK_HAVE_PNG_H */
#endif
/* if DK_HAVE_ZLIB_H */
#if DK_HAVE_JPEGLIB_H
#include <jpeglib.h>
#endif
#if DK_HAVE_PNM_H
#include <pnm.h>
#else
#if DK_HAVE_NETPBM_PNM_H
#include <netpbm/pnm.h>
#endif
#endif
#if DK_HAVE_TIFF_H
#include <tiff.h>
#include <tiffio.h>
#endif

#include "dksf.h"
#include "dkerror.h"
#include "dkmem.h"
#include "dksto.h"
#include "dkma.h"
#include "dkstream.h"

#include "dkbif.h"



#if DK_HAVE_JPEGLIB_H
/*
	Data types for JPEGLIB error management
*/
struct _dkbif_jpg_error_mgr_ {
  struct jpeg_error_mgr pub;
#if DK_HAVE_SETJMP_H
  jmp_buf setjmp_buffer;
#endif
};
typedef struct _dkbif_jpg_error_mgr_  dkbif_jpg_error_mgr;
typedef struct _dkbif_jpg_error_mgr_ *dkbif_jpg_error_ptr;
#endif



#define JFIF_RESULT_OK			0
#define JFIF_RESULT_PROBLEMATIC		1
#define JFIF_RESULT_UNUSABLE		2


typedef struct {
  unsigned long		 n;	/* number of frame in file */
  unsigned long		 w;	/* width in pixels */
  unsigned long		 h;	/* height in pixels */
  int			 ch;	/* number of channels, 1=gray...4=rgb+alpha */
  unsigned short	 bpc;	/* bits per component */
  unsigned short	 vmask;	/* same as vmax, but unsigned short */
  double		 vmax;	/* maximum value for bits per pixel */
  double		 xdpi;	/* x resolution, <0 if not specified */
  double		 ydpi;	/* y resolution, <0 if not specified */
  double		 mr;	/* mix background red */
  double		 mg;
  double		 mb;
  union {			/* data */
    int dummy;
    /* ----- additional file types require modifications here ----- */
#if DK_HAVE_ZLIB_H	&& DK_HAVE_PNG_H
    struct {
      /* data retrieved from png_get_IHDR() */
      unsigned long	 wi;	/* width and height */
      unsigned long	 he;
      unsigned short	 vmask;	/* mask matching bit-depth bd */
      int		 bd;	/* from png_get_IHDR() */
      int		 ct;	/* color type */
      int		 it;
      int		 zt;
      int		 ft;
      int		 ch;
      png_color_16	 bg;	/* background from background chunk */
      png_color_16p	 bgp;	/* pointer to bg */
      png_uint_32	 ppm;
      png_uint_32	 xppm;
      png_uint_32	 yppm;
      int		 have_kgd;
      png_bytep		*rows;
      unsigned long	 rowbytes;
      png_colorp	 palp;	/* color palette */
      int		 paln;	/* elements in palette */
    } png;
#endif
#if DK_HAVE_JPEGLIB_H
    struct {
      JSAMPLE			**rowbuffer;
    } jpg;
#endif
#if DK_HAVE_PNM_H || DK_HAVE_NETPBM_PNM_H
    struct {
      int rows;
      int cols;
      int format;
      xel **array;
      xelval maxxelval;
      double maxxeldbl;
    } pnm;
#endif
#if DK_HAVE_TIFF_H
    struct {
      uint32	w;
      uint32	h;
      uint16	bpc;	/* bits per component */
      uint16	spp;	/* samples per pixel = ch */
      uint32	*raster;
      double	xres;
      double	yres;
      unsigned char rescm;	/* resolution in TIFF was in cm */
    } tif;
#endif
  } d;
} dk_bif_frame_t;

typedef struct {
  int			 t;	/* DKBIF_TYPE_... */
  int			 ec;	/* error code of last error occured */
  unsigned long		 nof;	/* number of frames in file */
  dk_storage_t		*f;
  dk_storage_iterator_t	*fi;
  unsigned long		 w_all;	/* maximum width */
  unsigned long		 h_all;	/* maximum height */
  dk_bif_frame_t	*cf;	/* current frame */
  double		 mtl;	/* mask creation trigger level */
  double		 vmax;	/* maximum value for bits per pixel */
  unsigned short	 obpc;	/* output bits per pixel */
  int			 m;	/* mix against background */
  double		 mr;	/* mixing background red */
  double		 mg;
  double		 mb;
  unsigned char		 fntsc;	/* allow fast rgb to gray conversion */
  unsigned char		 whs;	/* width and height sufficient */
  union {			/* data */
    int dummy;
    /* ----- additional file types require modifications here ----- */
#if DK_HAVE_ZLIB_H	&& DK_HAVE_PNG_H
    struct {
      png_structp	 pp;
      png_infop		 pi;
    } png;
#endif
#if DK_HAVE_JPEGLIB_H
    struct {
      /*
        0 ... no initialization yet
	1 ... decrompress structure initialized
	2 ... + input source defined
	3 ... + header was read
	4 ... + decompression was started
	5 ... + decompression was finished
      254 ... error occured, cleanup already done
      255 ... cinfo + all data (except rowbuffer) released
      */
      int state;
      struct jpeg_decompress_struct cinfo;
      dkbif_jpg_error_mgr	emgr;
      dk_bif_jfif_analyze_t	jpgana;
    } jpg;
#endif
#if DK_HAVE_PNM_H || DK_HAVE_NETPBM_PNM_H
#endif
#if DK_HAVE_TIFF_H
    struct {
      TIFF *tiff;
    } tif;
#endif
  } d;
  char *tmpfilename;
} dk_bif_t;



/*
	Internal library functions
*/

/* dkbif */
#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
EXTERN dk_bif_frame_t *
dkbif_frame_new DK_PR((dk_bif_t *b, unsigned long n));
EXTERN unsigned short
dkbif_max_for_bpc DK_PR((unsigned short b));
#if defined(__cplusplus)
}
#endif

/* dkbifpng */
#if DK_HAVE_ZLIB_H	&& DK_HAVE_PNG_H
#if defined(EXTERN)
#undef EXTERN
#endif
#if DKBIFPNG_C
#define EXTERN /* nix */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif
EXTERN int
dkbifpng_header DK_PR((dk_bif_t *p, FILE *f));
EXTERN int
dkbifpng_data DK_PR((dk_bif_t *p, FILE *f));
EXTERN unsigned short
dkbifpng_red DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifpng_green DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifpng_blue DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifpng_gray DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifpng_alpha DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN void
dkbifpng_release DK_PR((dk_bif_t *p));
EXTERN void
dkbifpng_frame_release DK_PR((dk_bif_t *p, dk_bif_frame_t *f));
#if defined(__cplusplus)
}
#endif
#endif

/* dkbifjpg */
#if DK_HAVE_JPEGLIB_H
#if defined(EXTERN)
#undef EXTERN
#endif
#if DKBIFJPG_C
#define EXTERN /* nix */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif
EXTERN int
dkbifjpg_header DK_PR((dk_bif_t *p, FILE *f));
EXTERN int
dkbifjpg_data DK_PR((dk_bif_t *p, FILE *f));
EXTERN unsigned short
dkbifjpg_red DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifjpg_green DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifjpg_blue DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifjpg_gray DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifjpg_alpha DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN void
dkbifjpg_release DK_PR((dk_bif_t *p));
EXTERN void
dkbifjpg_frame_release DK_PR((dk_bif_t *p, dk_bif_frame_t *f));
#if defined(__cplusplus)
}
#endif
#endif

/* dkbifpbm */
#if DK_HAVE_JPEGLIB_H
#if defined(EXTERN)
#undef EXTERN
#endif
#if DKBIFPBM_C
#define EXTERN /* nix */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif
EXTERN int
dkbifpbm_header DK_PR((dk_bif_t *p, FILE *f));
EXTERN int
dkbifpbm_data DK_PR((dk_bif_t *p, FILE *f));
EXTERN unsigned short
dkbifpbm_red DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifpbm_green DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifpbm_blue DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifpbm_gray DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbifpbm_alpha DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN void
dkbifpbm_release DK_PR((dk_bif_t *p));
EXTERN void
dkbifpbm_frame_release DK_PR((dk_bif_t *p, dk_bif_frame_t *f));
#if defined(__cplusplus)
}
#endif
#endif

/* dkbiftif */
#if DK_HAVE_TIFF_H
#if defined(EXTERN)
#undef EXTERN
#endif
#if DKBIFTIF_C
#define EXTERN /* nix */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif
EXTERN int
dkbiftif_header DK_PR((dk_bif_t *p, FILE *f));
EXTERN int
dkbiftif_data DK_PR((dk_bif_t *p, FILE *f));
EXTERN unsigned short
dkbiftif_red DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbiftif_green DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbiftif_blue DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbiftif_gray DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN unsigned short
dkbiftif_alpha DK_PR((dk_bif_t *p, unsigned long x, unsigned long y));
EXTERN void
dkbiftif_release DK_PR((dk_bif_t *p));
EXTERN void
dkbiftif_frame_release DK_PR((dk_bif_t *p, dk_bif_frame_t *f));
#if defined(__cplusplus)
}
#endif
#endif

#define DKBIF_ERR_FAILED_TO_PROCESS_INPUT		-1
#define DKBIF_ERR_FAILED_TO_CREATE_TEMPORARY_FILE	-2
#define DPI_EPSILON					0.00001

#endif

