/* Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  
  This program is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License version 2
  as published by the Free Software Foundation.


  This software is provided AS-IS with no warranty, either express or
  implied. That is, this program is distributed in the hope that it will 
  be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  59 Temple Place, Suite 330, Boston, MA, 02111-1307.
  
  For more information about licensing, please refer to
  http://www.ghostscript.com/licensing/. For information on
  commercial licensing, go to http://www.artifex.com/licensing/ or
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
*/

/* $Id: gdevtifs.h,v 1.6 2002/06/16 07:25:26 lpd Exp $ */
/* Definitions for writing TIFF file formats. */

#ifndef gdevtifs_INCLUDED
#  define gdevtifs_INCLUDED

/* ================ TIFF specification ================ */

/* Based on TIFF specification version 6.0 obtained from */
/* sgi.com:graphics/tiff/TIFF6.ps.Z. */

/*
 * The sizes of TIFF data types are system-independent.  Therefore,
 * we cannot use short, long, etc., but must use types of known sizes.
 */
#if arch_sizeof_short == 2
typedef short TIFF_short;	/* no plausible alternative */
typedef unsigned short TIFF_ushort;

#endif
#if arch_sizeof_int == 4
typedef int TIFF_long;
typedef unsigned int TIFF_ulong;

#else
# if arch_sizeof_long == 4
typedef long TIFF_long;
typedef unsigned long TIFF_ulong;

# endif
#endif

/*
 * Define the TIFF file header.
 */
typedef struct TIFF_header_s {
    TIFF_ushort magic;		/* magic number (defines byte order) */
    TIFF_ushort version;	/* TIFF version number */
    TIFF_ulong diroff;		/* byte offset to first directory */
} TIFF_header;

#define	TIFF_magic_big_endian		0x4d4d	/* 'MM' */
#define	TIFF_magic_little_endian	0x4949	/* 'II' */

#define	TIFF_version_value	42

/*
 * Define an individual entry in a TIFF directory.  Within a directory,
 * the entries must be sorted by increasing tag value.
 *
 * The value field contains either the offset of the field data in the file,
 * or, if the value fits in 32 bits, the value itself, left-justified.
 * Field data may appear anywhere in the file, so long as each data block is
 * aligned on a 32-bit boundary and is disjoint from all other data blocks.
 */
typedef struct TIFF_dir_entry_s {
    TIFF_ushort tag;		/* TIFF_tag */
    TIFF_ushort type;		/* TIFF_data_type */
    TIFF_ulong count;		/* number of items (spec calls this 'length') */
    TIFF_ulong value;		/* byte offset to field data, */
    /* or actual value if <=4 bytes */
} TIFF_dir_entry;

/*
 * Define the tag data type values.
 */
typedef enum {
    TIFF_BYTE = 1,		/* 8-bit unsigned integer */
    TIFF_ASCII = 2,		/* 8-bit bytes with last byte null */
    TIFF_SHORT = 3,		/* 16-bit unsigned integer */
    TIFF_LONG = 4,		/* 32-bit unsigned integer */
    TIFF_RATIONAL = 5,		/* 64-bit unsigned fraction */
    /* (ratio of two 32-bit unsigned integers) */
    TIFF_SBYTE = 6,		/* 8-bit signed integer */
    TIFF_UNDEFINED = 7,		/* 8-bit untyped data */
    TIFF_SSHORT = 8,		/* 16-bit signed integer */
    TIFF_SLONG = 9,		/* 32-bit signed integer */
    TIFF_SRATIONAL = 10,	/* 64-bit signed fraction */
    /* (ratio of two 32-bit signed integers) */
    TIFF_FLOAT = 11,		/* 32-bit IEEE floating point */
    TIFF_DOUBLE = 12,		/* 64-bit IEEE floating point */
    /* A flag to indicate the value is indirect. */
    /* This is only used internally; it is not part of the */
    /* TIFF specification (although it should be!). */
    TIFF_INDIRECT = 128
} TIFF_data_type;

/*
 * Define the tag values we need.  Note that this is only a very small subset
 * of all the values defined in the TIFF specification; we will add more
 * as the need arises.
 */
typedef enum {
    TIFFTAG_SubFileType = 254,	/* subfile data descriptor */
#define	    SubFileType_reduced_image	0x1	/* reduced resolution version */
#define	    SubFileType_page		0x2	/* one page of many */
#define	    SubFileType_mask		0x4	/* transparency mask */
    TIFFTAG_ImageWidth = 256,	/* image width in pixels */
    TIFFTAG_ImageLength = 257,	/* image height in pixels */
    TIFFTAG_BitsPerSample = 258,	/* bits per channel (sample) */
    TIFFTAG_Compression = 259,	/* data compression technique */
#define	    Compression_none		1	/* dump mode */
#define	    Compression_CCITT_RLE	2	/* CCITT modified Huffman RLE */
#define	    Compression_CCITT_T4	3	/* CCITT T.4 fax encoding */
#define	    Compression_CCITT_T6	4	/* CCITT T.6 fax encoding */
#define	    Compression_LZW		5	/* Lempel-Ziv  & Welch */
#define	    Compression_JPEG		6	/* !JPEG compression */
#define	    Compression_NeXT		32766	/* NeXT 2-bit RLE */
#define	    Compression_CCITT_RLEW	32771	/* #1 w/ word alignment */
#define	    Compression_PackBits	32773	/* Macintosh RLE */
#define	    Compression_Thunderscan	32809	/* ThunderScan RLE */
    TIFFTAG_Photometric = 262,	/* photometric interpretation */
#define	    Photometric_min_is_white	0	/* min value is white */
#define	    Photometric_min_is_black	1	/* min value is black */
#define	    Photometric_RGB		2	/* RGB color model */
#define	    Photometric_palette		3	/* color map indexed */
#define	    Photometric_mask		4	/* $holdout mask */
#define	    Photometric_separated	5	/* !color separations */
#define	    Photometric_YCbCr		6	/* !CCIR 601 */
#define	    Photometric_CIE_Lab		8	/* !1976 CIE L*a*b* */
    TIFFTAG_FillOrder = 266,	/* data order within a byte */
#define	    FillOrder_MSB2LSB		1	/* most significant -> least */
#define	    FillOrder_LSB2MSB		2	/* least significant -> most */
    TIFFTAG_StripOffsets = 273,	/* offsets to data strips */
    TIFFTAG_Orientation = 274,	/* +image Orientation */
#define	    Orientation_top_left	1	/* row 0 top, col 0 lhs */
#define	    Orientation_top_right	2	/* row 0 top, col 0 rhs */
#define	    Orientation_bot_right	3	/* row 0 bottom, col 0 rhs */
#define	    Orientation_bot_left	4	/* row 0 bottom, col 0 lhs */
#define	    Orientation_left_top	5	/* row 0 lhs, col 0 top */
#define	    Orientation_right_top	6	/* row 0 rhs, col 0 top */
#define	    Orientation_right_bot	7	/* row 0 rhs, col 0 bottom */
#define	    Orientation_left_bot	8	/* row 0 lhs, col 0 bottom */
    TIFFTAG_SamplesPerPixel = 277,	/* samples per pixel */
    TIFFTAG_RowsPerStrip = 278,	/* rows per strip of data */
    TIFFTAG_StripByteCounts = 279,	/* bytes counts for strips */
    TIFFTAG_XResolution = 282,	/* pixels/resolution in x */
    TIFFTAG_YResolution = 283,	/* pixels/resolution in y */
    TIFFTAG_PlanarConfig = 284,	/* storage organization */
#define	    PlanarConfig_contig		1	/* single image plane */
#define	    PlanarConfig_separate	2	/* separate planes of data */
    TIFFTAG_T4Options = 292,	/* 32 flag bits */
#define	    T4Options_2D_encoding	0x1	/* 2-dimensional coding */
#define	    T4Options_uncompressed	0x2	/* data not compressed */
#define	    T4Options_fill_bits		0x4	/* fill to byte boundary */
    TIFFTAG_T6Options = 293,	/* 32 flag bits */
#define	    T6Options_uncompressed	0x2	/* data not compressed */
    TIFFTAG_ResolutionUnit = 296,	/* units of resolutions */
#define	    ResolutionUnit_none		1	/* no meaningful units */
#define	    ResolutionUnit_inch		2	/* english */
#define	    ResolutionUnit_centimeter	3	/* metric */
    TIFFTAG_PageNumber = 297,	/* page number if multi-page */
    TIFFTAG_Software = 305,	/* software name & release */
    TIFFTAG_DateTime = 306,	/* creation date and time */
    /*
     * The CleanFaxData tag isn't in the TIFF 6 documentation, and many
     * TIFF-reading applications don't recognize it.  Don't use it!
     */
    TIFFTAG_CleanFaxData = 327	/* regenerated line info */
#define	    CleanFaxData_clean		0	/* no errors detected */
#define	    CleanFaxData_regenerated	1	/* receiver regenerated lines */
#define	    CleanFaxData_unclean	2	/* uncorrected errors exist */
} TIFF_tag;

/* ================ Implementation ================ */

/*
 * Define the added driver state for TIFF writing.  Note that we provide
 * no GC descriptor, so this structure must exist only on the stack,
 * never in allocated storage.
 */
typedef struct gdev_tiff_state_s {
    gs_memory_t *mem;
    long prev_dir;		/* file offset of previous directory offset */
    long dir_off;		/* file offset of next write */
    int ntags;			/* # of tags in directory */
    long strip_index;		/* current strip being output, 0 = first */
    long strip_count;		
    long rows;		
    /* Record offsets of values - these may be indirect if more than one strip */
    int offset_StripOffsets; 
    int offset_StripByteCounts;
    TIFF_ulong *StripOffsets;
    TIFF_ulong *StripByteCounts;
} gdev_tiff_state;

/*
 * Begin writing a TIFF page.  This procedure supplies a standard set of
 * tags; the client can provide additional tags (pre-sorted) and
 * indirect values.
 */
int gdev_tiff_begin_page(gx_device_printer * pdev, gdev_tiff_state * tifs,
			 FILE * fp,
			 const TIFF_dir_entry * entries, int entry_count,
			 const byte * values, int value_size,
			 long max_strip_size);

/*
 * Finish writing a TIFF strip.  All data written since begin or last
 * end_strip is considered to be a single strip.
 */
int gdev_tiff_end_strip(gdev_tiff_state * tifs, FILE * fp);

/*
 * Finish writing a TIFF page.  StripOffsets and StripByteCounts are
 * patched into the file.
 */
int gdev_tiff_end_page(gdev_tiff_state * tifs, FILE * fp);

#endif /* gdevtifs_INCLUDED */
