#ifndef _exif_h_
#define _exif_h_

#include <string.h>

#include "util.h"


#define	EXIF_MARKER 0x45786966UL /* followed by 0x0000 */
#define EXIF_MARKER_STRING "Exif\0\0"


/* some TIFF definitions */

enum TIFF_TYPE
{
	TIFF_IFD_TYPE_BYTE		=1,
	TIFF_IFD_TYPE_STRING	=2,
	TIFF_IFD_TYPE_USHORT	=3,
	TIFF_IFD_TYPE_ULONG		=4,
	TIFF_IFD_TYPE_URATIONAL	=5,
	TIFF_IFD_TYPE_SBYTE		=6,
	TIFF_IFD_TYPE_UNDEFINED	=7,
	TIFF_IFD_TYPE_SSHORT	=8,
	TIFF_IFD_TYPE_SLONG		=9,
	TIFF_IFD_TYPE_SRATIONAL	=10,
	TIFF_IFD_TYPE_FLOAT		=11,
	TIFF_IFD_TYPE_DOUBLE	=12,
	/* reserved */
	TIFF_IFD_TYPE_UNKNOWN	=-1
};

struct tiff_ifd_entry
{
	unsigned short int tag;
	unsigned short int type;
	unsigned long int count;
	unsigned long int value_offset;
};

struct tiff_ifd_type_size
{
	enum TIFF_TYPE	type;
	unsigned int	size;
};


/* TIFF types in fact, Exif types only represents a subset */

enum EXIF_IFD_CODE
{
	EXIF_IFD_IMAGE_WIDTH					=0x0100,
	EXIF_IFD_IMAGE_HEIGHT					=0x0101,
	EXIF_IFD_BITS_PER_SAMPLE				=0x0102,
	EXIF_IFD_COMPRESSION					=0x0103,
	EXIF_IFD_PHOTOMETRIC_INTERPRETATION 	=0x0106,
	EXIF_IFD_IMAGE_DESCR					=0x010e,
	EXIF_IFD_MAKE							=0x010f,
	EXIF_IFD_MODEL  						=0x0110,
	EXIF_IFD_STRIP_OFFSETS  				=0x0111,
	EXIF_IFD_ORIENTATION					=0x0112,
	EXIF_IFD_SAMPLES_PER_PIXEL  			=0x0115,
	EXIF_IFD_ROWS_PER_STRIP 				=0x0116,
	EXIF_IFD_STRIP_BYTE_COUNT				=0x0117,
	EXIF_IFD_XRES							=0x011a,
	EXIF_IFD_YRES							=0x011b,
	EXIF_IFD_RES_UNIT						=0x0128,
	EXIF_IFD_SOFTWARE						=0x0131,
	EXIF_IFD_DATE_TIME  					=0x0132,

	EXIF_IFD_JPEG_IF_OFFSET 				=0x0201,
	EXIF_IFD_JPEG_IF_BYTE_COUNT 			=0x0202,
	EXIF_IFD_YCBCR_POS  					=0x0213,

	EXIF_IFD_EXPOSURE_TIME					=0x829a,
	EXIF_IFD_F_NUMBER						=0x829d,
	EXIF_IFD_OFFSET							=0x8769,
	EXIF_IFD_LOCATION_OFFSET				=0x8787,
	EXIF_IFD_EXPOSURE_PROGRAM				=0x8822,
	EXIF_IFD_GPS_IFD_OFFSET					=0x8825,
	EXIF_IFD_ISO_SPEED_RATINGS				=0x8827,

	EXIF_IFD_EXIF_VERSION					=0x9000,
	EXIF_IFD_ORIG_DATE_TIME					=0x9003,
	EXIF_IFD_DIGIT_DATE_TIME				=0x9004,
	EXIF_IFD_COMPONENT_CONFIG				=0x9101,
	EXIF_IFD_COMPRESSION_RATE				=0x9102,
	EXIF_IFD_SHUTTER_SPEED					=0x9201,
	EXIF_IFD_APERTURE						=0x9202,
	EXIF_IFD_BRIGHTNESS						=0x9203,
	EXIF_IFD_EXPOSURE_BIAS					=0x9204,
	EXIF_IFD_MAX_APERTURE					=0x9205,
	EXIF_IFD_SUBJECT_DISTANCE				=0x9206,
	EXIF_IFD_METERING_MODE					=0x9207,
	EXIF_IFD_LIGHT_SOURCE					=0x9208,
	EXIF_IFD_FLASH							=0x9209,
	EXIF_IFD_FOCAL_LENGTH					=0x920a,
	EXIF_IFD_MAKER_NOTE						=0x927c,
	EXIF_IFD_USER_COMMENT					=0x9286,

	EXIF_IFD_FLASH_PIX_VERSION				=0xa000,
	EXIF_IFD_COLOR_SPACE					=0xa001,
	EXIF_IFD_EXIF_IMAGE_WIDTH				=0xa002,
	EXIF_IFD_EXIF_IMAGE_HEIGHT				=0xa003,
	EXIF_IFD_SOUND_FILE						=0xa004,
	EXIF_IFD_INTEROPE_OFFSET				=0xa005,
	EXIF_IFD_FOCAL_PLANE_XRES				=0xa20e,
	EXIF_IFD_FOCAL_PLANE_YRES				=0xa20f,
	EXIF_IFD_FOCAL_PLANE_RES_UNIT			=0xa210,
	EXIF_IFD_SENSING_METHOD					=0xa217,
	EXIF_IFD_FILE_SOURCE					=0xa300,
	EXIF_IFD_SCENE_TYPE						=0xa301,
	/* reserved */
	EXIF_IFD_EOT							=0xffff
};

enum EXIF_INTEROPE_CODE
{
	EXIF_INTEROPE_INDEX						=0x0001,
	EXIF_INTEROPE_VERSION					=0x0002,
	EXIF_INTEROPE_IMAGE_WIDTH				=0x1001,
	EXIF_INTEROPE_IMAGE_HEIGHT				=0x1002,
	/* reserved */
	EXIF_INTEROPE_EOT						=0xffff
};

enum EXIF_LOCATION_CODE
{
	EXIF_LOCATION_CONTINENT					=0x1000,
	EXIF_LOCATION_COUNTRY					=0x1001,
	EXIF_LOCATION_COUNTRY_OTHER				=0x1002,
	EXIF_LOCATION_REGION					=0x1003,
	EXIF_LOCATION_AREA						=0x1004,
	EXIF_LOCATION_SUB_AREA					=0x1005,
	EXIF_LOCATION_PLACE						=0x1006,
	EXIF_LOCATION_PLACE_AREA				=0x1007,
	EXIF_LOCATION_LOCATION					=0x1008,
	EXIF_LOCATION_ADDRESS					=0x1009,
	EXIF_LOCATION_POSTAL_CODE				=0x100a,
	EXIF_LOCATION_DESCRIPTION				=0x100b,
	/* reserved */
	EXIF_LOCATION_EOT						=0xffff
};

enum EXIF_CANON_CODE
{
	EXIF_CANON_MAKER_NOTE_UNKNOWN1				=0x0000,
	EXIF_CANON_MAKER_NOTE_UNKNOWN2				=0x0001,
	EXIF_CANON_MAKER_NOTE_UNKNOWN3				=0x0002,
	EXIF_CANON_MAKER_NOTE_UNKNOWN4				=0x0003,
	EXIF_CANON_MAKER_NOTE_UNKNOWN5				=0x0004,
	EXIF_CANON_MAKER_NOTE_IMAGE_TYPE			=0x0006,
	EXIF_CANON_MAKER_NOTE_FIRMWARE_VERSION		=0x0007,
	EXIF_CANON_MAKER_NOTE_IMAGE_NUMBER			=0x0008,
	EXIF_CANON_MAKER_NOTE_OWNER_NAME			=0x0009,
	EXIF_CANON_MAKER_NOTE_UNKNOWN6				=0x0010,
	/* reserved */
	EXIF_CANON_EOT								=0xffff
};

enum EXIF_FUJI_CODE
{
	EXIF_FUJI_MAKER_NOTE_VERSION				=0x0000,
	EXIF_FUJI_MAKER_NOTE_QUALITY				=0x1000,
	EXIF_FUJI_MAKER_NOTE_SHARPNESS				=0x1001,
	EXIF_FUJI_MAKER_NOTE_WHITE_BALANCE			=0x1002,
	EXIF_FUJI_MAKER_NOTE_FLASH_MODE				=0x1010,
	EXIF_FUJI_MAKER_NOTE_FLASH_STRENGTH			=0x1011,
	EXIF_FUJI_MAKER_NOTE_MACRO					=0x1020,
	EXIF_FUJI_MAKER_NOTE_FOCUS_MODE				=0x1021,
	EXIF_FUJI_MAKER_NOTE_SLOW_SYNC				=0x1030,
	EXIF_FUJI_MAKER_NOTE_PICTURE_MODE			=0x1031,
	EXIF_FUJI_MAKER_NOTE_CONT_TAKE_BRACKET		=0x1100,
	EXIF_FUJI_MAKER_NOTE_UNKNOWN				=0x1200,
	EXIF_FUJI_MAKER_NOTE_BLUR_WARNING			=0x1300,
	EXIF_FUJI_MAKER_NOTE_FOCUS_WARNING			=0x1301,
	EXIF_FUJI_MAKER_NOTE_AE_WARNING				=0x1302,
	/* reserved */
	EXIF_FUJI_EOT								=0xffff
};

enum EXIF_NIKON_CODE
{
	EXIF_NIKON_MAKER_NOTE_UNKNOWN1				=0x0002,
	EXIF_NIKON_MAKER_NOTE_UNKNOWN2				=0x0003,
	EXIF_NIKON_MAKER_NOTE_UNKNOWN3				=0x0004,
	EXIF_NIKON_MAKER_NOTE_UNKNOWN4				=0x0005,
	EXIF_NIKON_MAKER_NOTE_UNKNOWN5				=0x0006,
	EXIF_NIKON_MAKER_NOTE_UNKNOWN6				=0x0007,
	EXIF_NIKON_MAKER_NOTE_UNKNOWN7				=0x0008,
	EXIF_NIKON_MAKER_NOTE_UNKNOWN8				=0x0009,
	EXIF_NIKON_MAKER_NOTE_UNKNOWN9				=0x000a,
	EXIF_NIKON_MAKER_NOTE_UNKNOWN10				=0x000b,
	EXIF_NIKON_MAKER_NOTE_DATA_DUMP				=0x0f00,
	/* reserved */
	EXIF_NIKON_EOT								=0xffff
};

enum EXIF_SANYO_CODE /* Olympus, "and so on" */
{
	EXIF_SANYO_MAKER_NOTE_START_OFFSET				=0x00ff,
	EXIF_SANYO_MAKER_NOTE_JPEG_THUMBNAIL			=0x0100,
	EXIF_SANYO_MAKER_NOTE_SPECIAL_MODE				=0x0200,
	EXIF_SANYO_MAKER_NOTE_JPEQ_QUALITY				=0x0201,
	EXIF_SANYO_MAKER_NOTE_MACRO						=0x0202,
	EXIF_SANYO_MAKER_NOTE_UNKNOWN1					=0x0203,
	EXIF_SANYO_MAKER_NOTE_DIGITAL_ZOOM1				=0x0204,
	EXIF_SANYO_MAKER_NOTE_UNKNOWN2					=0x0205,
	EXIF_SANYO_MAKER_NOTE_UNKNOWN3					=0x0206,
	EXIF_SANYO_MAKER_NOTE_SOFTWARE_RELEASE			=0x0207,
	EXIF_SANYO_MAKER_NOTE_PICT_INFO					=0x0208,
	EXIF_SANYO_MAKER_NOTE_CAMERA_ID					=0x0209,
	EXIF_SANYO_MAKER_NOTE_SEQUENTIAL_SHOT_METHOD	=0x020e,
	EXIF_SANYO_MAKER_NOTE_WIDE_RANGE				=0x020f,
	EXIF_SANYO_MAKER_NOTE_COLOUR_ADJUSTMENT_MODE	=0x0210,
	EXIF_SANYO_MAKER_NOTE_QUICK_SHOT				=0x0213,
	EXIF_SANYO_MAKER_NOTE_SELF_TIMER				=0x0214,
	EXIF_SANYO_MAKER_NOTE_VOICE_MEMO				=0x0216,
	EXIF_SANYO_MAKER_NOTE_RECORD_SHUTTER_RELEASE	=0x0217,
	EXIF_SANYO_MAKER_NOTE_FLICKER_REDUCE			=0x0218,
	EXIF_SANYO_MAKER_NOTE_OPTICAL_ZOOM				=0x0219,
	EXIF_SANYO_MAKER_NOTE_DIGITAL_ZOOM2				=0x021b,
	EXIF_SANYO_MAKER_NOTE_LIGHT_SOURCE_SPECIAL		=0x021d,
	EXIF_SANYO_MAKER_NOTE_RESAVED					=0x021e,
	EXIF_SANYO_MAKER_NOTE_SCENE_SELECT				=0x021f,
	EXIF_SANYO_MAKER_NOTE_MANUAL_FOCAL_DISTANCE		=0x0223,
	EXIF_SANYO_MAKER_NOTE_SEQUENTIAL_SHOT_INTERVAL	=0x0224,
	EXIF_SANYO_MAKER_NOTE_FLASH_MODE				=0x0225,
	EXIF_SANYO_MAKER_NOTE_PRINTIM_FLAGS				=0x0e00,
	EXIF_SANYO_MAKER_NOTE_DATA_DUMP					=0x0f00,
	/* reserved */
	EXIF_SANYO_EOT									=0xffff
};

struct exif_ifd_field
{
	enum TIFF_TYPE		tag;
	enum EXIF_IFD_CODE	format;
	int					components;
	char*				entry;
};

struct exif_interope_field
{
	enum TIFF_TYPE			tag;
	enum EXIF_INTEROPE_CODE	format;
	int						components;
	char*					entry;
};

struct exif_location_field
{
	enum TIFF_TYPE			tag;
	enum EXIF_LOCATION_CODE	format;
	int						components;
	char*					entry;
};

struct exif_canon_field
{
	enum TIFF_TYPE			tag;
	enum EXIF_CANON_CODE	format;
	int						components;
	char*					entry;
};

struct exif_fuji_field
{
	enum TIFF_TYPE		tag;
	enum EXIF_FUJI_CODE	format;
	int					components;
	char*				entry;
};

struct exif_nikon_field
{
	enum TIFF_TYPE			tag;
	enum EXIF_NIKON_CODE	format;
	int						components;
	char*					entry;
};

struct exif_sanyo_field
{
	enum TIFF_TYPE			tag;
	enum EXIF_SANYO_CODE	format;
	int						components;
	char*					entry;
};


void exif_parse(unsigned char*, const unsigned int, struct parser_result*);
struct exif_ifd_field* exif_match_tag(const int);
void exif_dump_list(void);
unsigned int get_ifd_type_size(const enum TIFF_TYPE);

#endif
