/**************************************************************************
 *{@C
 *      Copyright:      1988-2023 Paul Obermeier (obermeier@poSoft.de)
 *
 *      Module:         FileFormats
 *      Filename:       FF_Image.h
 *
 *      Author:         Paul Obermeier
 *
 *      Description:    Functions for reading and writing image files.
 *
 *      Additional documentation:
 *                      None.
 *
 **************************************************************************/

#ifndef __FF_IMAGE_H__
#define __FF_IMAGE_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "UT_Compat.h"
#include "UT_Image.h"
#include "UT_Error.h"

/* Error codes specific to the pixel file library. */

extern POIMG_IMPORT_EXPORT UT_ErrBase FF_ImgErrList;

#define FF_ImgErrNoImgFile      (FF_ImgErrList.base + 0)
#define FF_ImgErrSyntax         (FF_ImgErrList.base + 1)
#define FF_ImgErrFormat         (FF_ImgErrList.base + 2)

/* Maximum length of file format names */

#define FF_ImgMaxNameLen 30

/* Description of an image and of the frame buffer / monitor
used to display the image. */

typedef struct {
    Int32       width, height;  /* Width and height of the image, in pixels */
    Float32     aspect;         /* Image width in mm / image height in mm */
    CIE_hue     red,            /* Hue of the monitor's red phospor */
                green,          /* Hue of the monitor's green phospor */
                blue,           /* Hue of the monitor's blue phospor */
                white;          /* Hue of the monitor's white point */
        Float32 gamma;          /* Frame buffer/monitor gamma */
} FF_ImgHdr;

/* Format of the pixel data */

typedef enum {
    FF_ImgFmtTypeNone  = 0,     /* None, channel does not exist */
    FF_ImgFmtTypeUByte = 1,     /* Unsigned 8-bit integers */
    FF_ImgFmtTypeFloat = 2      /* 32-bit floating point numbers */
} FF_ImgFmtType;

#define FF_NumImgFmtTypes 3     /* Number of different pixel formats */

/* Channel types in a image file */

typedef enum {
    FF_ImgChanTypeNone        = -1,  /* Invalid channel type */
    FF_ImgChanTypeGray        =  0,  /* Brightness for grayscale images */
    FF_ImgChanTypeRed         =  1,  /* Red   for color images */
    FF_ImgChanTypeGreen       =  2,  /* Green for color images */
    FF_ImgChanTypeBlue        =  3,  /* Blue  for color images */
    FF_ImgChanTypeMatte       =  4,  /* Transparency without color information */
    FF_ImgChanTypeRedMatte    =  5,  /* Transparency for red light */
    FF_ImgChanTypeGreenMatte  =  6,  /* Transparency for green light */
    FF_ImgChanTypeBlueMatte   =  7,  /* Transparency for blue light */
    FF_ImgChanTypeHoriSnr     =  8,  /* Direction of face normal, horizontal */
    FF_ImgChanTypeVertSnr     =  9,  /* Direction of face normal, vertical */
    FF_ImgChanTypeDepth       = 10,  /* Distance from the eye point */
    FF_ImgChanTypeTemperature = 11,  /* Temperature */
    FF_ImgChanTypeRadiance    = 12   /* Integrated radiance */
} FF_ImgChanType;

#define FF_NumImgChanTypes 13   /* Number of different channel types.
                                   Note: Do not count FF_ImgChanTypeNone. */

/* A structure to store an image */

typedef struct {
    FF_ImgHdr     desc;         /* Size and colors */
    FF_ImgFmtType channel[FF_NumImgChanTypes];  /* Flags indicating which
                                                   channels are available
                                                   in the image, and in which
                                                   format they are stored */
    Int32 firstscan, lastscan;  /* Index of the first and last scan line in the
                                   image for which pixel storage is allocated */
    union {                     /* Pointers to pixel data */
        UInt8   **ubytes;
        Float32 **floats;
    } pixelptr[FF_NumImgChanTypes];
} FF_ImgDesc;

/* Data compression method */

typedef enum {
    FF_ImgComprTypeNone = 0,    /* No compression */
    FF_ImgComprTypeRle =  1     /* Run length encoding */
} FF_ImgComprType;

#define FF_NumImgComprTypes 2   /* Number of different compression methods */

/* Ordering of the scan lines in the pixel file */

typedef enum {
    FF_ImgOrderTypeBottomUp,    /* Bottom scan line comes first in the file */
    FF_ImgOrderTypeTopDown,     /* Top scan line comes first in the file */
    FF_ImgOrderTypeRandom       /* Read/write in random order is possible */
} FF_ImgOrderType;

/* A pixel file header */

typedef struct {
    FF_ImgHdr   desc;                   /* Size and colors of the
                                                   image stored in the file */
    FF_ImgFmtType       channel[FF_NumImgChanTypes];    /* Flags indicating which
                                                   channels are stored in the
                                                   file and in which format */
    FF_ImgComprType     compression[FF_NumImgChanTypes];        /* Data compression method
                                                   for each channel */
    FF_ImgOrderType     scanorder;              /* Ordering of the scan lines
                                                   in the file */
    void                *pixprivate;            /* Private data maintained
                                                   by the pixel file library */
    char                format[FF_ImgMaxNameLen],       /* File format */
                        version[FF_ImgMaxNameLen];      /* File format version */
} FF_ImgFileDesc;

/* Functions to access the pixels in an image */

#if !defined (USE_IMG_MACROS)
        extern POIMG_IMPORT_EXPORT UInt8 *FF_ImgUBytePixel (FF_ImgDesc *, FF_ImgChanType, Int32, Int32);
        extern POIMG_IMPORT_EXPORT UInt8 *FF_ImgUByteRow (FF_ImgDesc *, FF_ImgChanType, Int32);
        extern POIMG_IMPORT_EXPORT Float32 *FF_ImgFloatPixel (FF_ImgDesc *, FF_ImgChanType, Int32, Int32);
        extern POIMG_IMPORT_EXPORT Float32 *FF_ImgFloatRow (FF_ImgDesc *, FF_ImgChanType, Int32);
#else
        #define FF_ImgUBytePixel(img, chan, x, y) \
                ((img)->pixelptr[(Int32)(chan)].ubytes[(y)] + (x))
        #define FF_ImgUByteRow(img, chan, y) \
                ((img)->pixelptr[(Int32)(chan)].ubytes[(y)])
        #define FF_ImgFloatPixel(img, chan, x, y) \
                ((img)->pixelptr[(Int32)(chan)].floats[(y)] + (x))
        #define FF_ImgFloatRow(img, chan, y) \
                ((img)->pixelptr[(Int32)(chan)].floats[(y)])
#endif

/* Functions to allocate memory for the pixel data of an image */

extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgNew (FF_ImgDesc *);
extern POIMG_IMPORT_EXPORT void FF_ImgDelete (FF_ImgDesc *);

/* Functions to allocate to read and write pixel files */

extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgOpenWrite (const char *, FF_ImgFileDesc *);
extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgOpenRead (const char *, FF_ImgFileDesc *);
extern POIMG_IMPORT_EXPORT void FF_ImgClose (FF_ImgFileDesc *);
extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgSetSrcImg (FF_ImgFileDesc *, FF_ImgDesc *, UT_Bool, UT_Bool);
extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgSetDestImg (FF_ImgFileDesc *, FF_ImgDesc *, UT_Bool, UT_Bool, UT_Bool);
extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgWriteRow (FF_ImgFileDesc *, Int32, Int32);
extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgReadRow (FF_ImgFileDesc *, Int32, Int32);

extern POIMG_IMPORT_EXPORT const char *FF_ImgGetFmtTypeName   (FF_ImgFmtType   fmtType);
extern POIMG_IMPORT_EXPORT const char *FF_ImgGetChanTypeName  (FF_ImgChanType  chanType);
extern POIMG_IMPORT_EXPORT const char *FF_ImgGetComprTypeName (FF_ImgComprType comprType);

extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgGetFmtType (const char *fmtName, FF_ImgFmtType *fmtType);
extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgGetChanType (const char *chanName, FF_ImgChanType *chanType);
extern POIMG_IMPORT_EXPORT UT_Bool FF_ImgGetComprType (const char *comprName, FF_ImgComprType *comprType);

#ifdef __cplusplus
}
#endif

#endif /* __FF_IMAGE_H__ */
