/*  This file is part of SAIL (https://github.com/HappySeaFox/sail)

    Copyright (c) 2020 Dmitry Baryshev

    The MIT License

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
*/

#pragma once

#include <sail-common/export.h>
#include <sail-common/status.h>

/*
 * Common data structures and functions used across SAIL, both in libsail and in image codecs.
 */

/* Pixel format */
enum SailPixelFormat
{
    /*
     * Unknown or unsupported pixel format that cannot be parsed by SAIL.
     */
    SAIL_PIXEL_FORMAT_UNKNOWN,

    /*
     * Formats with unknown pixel representation/model.
     */
    SAIL_PIXEL_FORMAT_BPP1,
    SAIL_PIXEL_FORMAT_BPP2,
    SAIL_PIXEL_FORMAT_BPP4,
    SAIL_PIXEL_FORMAT_BPP8,
    SAIL_PIXEL_FORMAT_BPP16,
    SAIL_PIXEL_FORMAT_BPP24,
    SAIL_PIXEL_FORMAT_BPP32,
    SAIL_PIXEL_FORMAT_BPP48,
    SAIL_PIXEL_FORMAT_BPP64,
    SAIL_PIXEL_FORMAT_BPP72,
    SAIL_PIXEL_FORMAT_BPP96,
    SAIL_PIXEL_FORMAT_BPP128,

    /*
     * Indexed formats with palette.
     */
    SAIL_PIXEL_FORMAT_BPP1_INDEXED,
    SAIL_PIXEL_FORMAT_BPP2_INDEXED,
    SAIL_PIXEL_FORMAT_BPP4_INDEXED,
    SAIL_PIXEL_FORMAT_BPP8_INDEXED,
    SAIL_PIXEL_FORMAT_BPP16_INDEXED,

    /*
     * Grayscale formats.
     */
    SAIL_PIXEL_FORMAT_BPP1_GRAYSCALE,
    SAIL_PIXEL_FORMAT_BPP2_GRAYSCALE,
    SAIL_PIXEL_FORMAT_BPP4_GRAYSCALE,
    SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE,
    SAIL_PIXEL_FORMAT_BPP16_GRAYSCALE,

    SAIL_PIXEL_FORMAT_BPP4_GRAYSCALE_ALPHA,
    SAIL_PIXEL_FORMAT_BPP8_GRAYSCALE_ALPHA,
    SAIL_PIXEL_FORMAT_BPP16_GRAYSCALE_ALPHA,
    SAIL_PIXEL_FORMAT_BPP32_GRAYSCALE_ALPHA,

    /*
     * Packed formats.
     */
    SAIL_PIXEL_FORMAT_BPP16_RGB555,
    SAIL_PIXEL_FORMAT_BPP16_BGR555,
    SAIL_PIXEL_FORMAT_BPP16_RGB565,
    SAIL_PIXEL_FORMAT_BPP16_BGR565,

    /*
     * RGB formats.
     */
    SAIL_PIXEL_FORMAT_BPP24_RGB,
    SAIL_PIXEL_FORMAT_BPP24_BGR,

    SAIL_PIXEL_FORMAT_BPP48_RGB,
    SAIL_PIXEL_FORMAT_BPP48_BGR,

    /*
     * RGBA/X formats. X = unused color channel.
     */
    SAIL_PIXEL_FORMAT_BPP16_RGBX,
    SAIL_PIXEL_FORMAT_BPP16_BGRX,
    SAIL_PIXEL_FORMAT_BPP16_XRGB,
    SAIL_PIXEL_FORMAT_BPP16_XBGR,
    SAIL_PIXEL_FORMAT_BPP16_RGBA,
    SAIL_PIXEL_FORMAT_BPP16_BGRA,
    SAIL_PIXEL_FORMAT_BPP16_ARGB,
    SAIL_PIXEL_FORMAT_BPP16_ABGR,

    SAIL_PIXEL_FORMAT_BPP32_RGBX,
    SAIL_PIXEL_FORMAT_BPP32_BGRX,
    SAIL_PIXEL_FORMAT_BPP32_XRGB,
    SAIL_PIXEL_FORMAT_BPP32_XBGR,
    SAIL_PIXEL_FORMAT_BPP32_RGBA,
    SAIL_PIXEL_FORMAT_BPP32_BGRA,
    SAIL_PIXEL_FORMAT_BPP32_ARGB,
    SAIL_PIXEL_FORMAT_BPP32_ABGR,

    SAIL_PIXEL_FORMAT_BPP64_RGBX,
    SAIL_PIXEL_FORMAT_BPP64_BGRX,
    SAIL_PIXEL_FORMAT_BPP64_XRGB,
    SAIL_PIXEL_FORMAT_BPP64_XBGR,
    SAIL_PIXEL_FORMAT_BPP64_RGBA,
    SAIL_PIXEL_FORMAT_BPP64_BGRA,
    SAIL_PIXEL_FORMAT_BPP64_ARGB,
    SAIL_PIXEL_FORMAT_BPP64_ABGR,

    /*
     * CMYK formats.
     */
    SAIL_PIXEL_FORMAT_BPP32_CMYK,
    SAIL_PIXEL_FORMAT_BPP64_CMYK,

    SAIL_PIXEL_FORMAT_BPP40_CMYKA,
    SAIL_PIXEL_FORMAT_BPP80_CMYKA,

    /*
     * YCbCr formats.
     */
    SAIL_PIXEL_FORMAT_BPP24_YCBCR,

    /*
     * YCCK formats.
     */
    SAIL_PIXEL_FORMAT_BPP32_YCCK,

    /*
     * CIE LAB formats.
     */
    SAIL_PIXEL_FORMAT_BPP24_CIE_LAB, /* 8/8/8   */
    SAIL_PIXEL_FORMAT_BPP40_CIE_LAB, /* 8/16/16 */

    /*
     * CIE LUV formats.
     */
    SAIL_PIXEL_FORMAT_BPP24_CIE_LUV, /* 8/8/8   */
    SAIL_PIXEL_FORMAT_BPP40_CIE_LUV, /* 8/16/16 */

    /*
     * YUV formats.
     */
    SAIL_PIXEL_FORMAT_BPP24_YUV, /* 8-bit  */
    SAIL_PIXEL_FORMAT_BPP30_YUV, /* 10-bit */
    SAIL_PIXEL_FORMAT_BPP36_YUV, /* 12-bit */
    SAIL_PIXEL_FORMAT_BPP48_YUV, /* 16-bit */

    SAIL_PIXEL_FORMAT_BPP32_YUVA,
    SAIL_PIXEL_FORMAT_BPP40_YUVA,
    SAIL_PIXEL_FORMAT_BPP48_YUVA,
    SAIL_PIXEL_FORMAT_BPP64_YUVA,

    /* Since 1.0.0 */
    SAIL_PIXEL_FORMAT_BPP32_CIE_LABA, /* 8/8/8/8     */
    SAIL_PIXEL_FORMAT_BPP64_CIE_LABA, /* 16/16/16/16 */

    SAIL_PIXEL_FORMAT_BPP32_AYUV, /* 8-bit per channel  */
    SAIL_PIXEL_FORMAT_BPP64_AYUV, /* 16-bit per channel */

    SAIL_PIXEL_FORMAT_BPP24_CIE_XYZ,  /* 8/8/8       */
    SAIL_PIXEL_FORMAT_BPP48_CIE_XYZ,  /* 16/16/16    */
    SAIL_PIXEL_FORMAT_BPP32_CIE_XYZA, /* 8/8/8/8     */
    SAIL_PIXEL_FORMAT_BPP64_CIE_XYZA, /* 16/16/16/16 */

    SAIL_PIXEL_FORMAT_BPP24_HSV, /* 8-bit per channel  */
    SAIL_PIXEL_FORMAT_BPP24_HSL, /* 8-bit per channel  */
    SAIL_PIXEL_FORMAT_BPP48_HSV, /* 16-bit per channel */
    SAIL_PIXEL_FORMAT_BPP48_HSL, /* 16-bit per channel */

    SAIL_PIXEL_FORMAT_BPP30_RGB,          /* RGB 10-bit per channel (R10G10B10) */
    SAIL_PIXEL_FORMAT_BPP30_BGR,          /* BGR 10-bit per channel */
    SAIL_PIXEL_FORMAT_BPP32_RGBA_1010102, /* RGBA with 10-bit RGB + 2-bit alpha */
    SAIL_PIXEL_FORMAT_BPP32_BGRA_1010102, /* BGRA with 10-bit BGR + 2-bit alpha */

    SAIL_PIXEL_FORMAT_BPP16_GRAYSCALE_HALF,       /* Half-precision grayscale */
    SAIL_PIXEL_FORMAT_BPP32_GRAYSCALE_ALPHA_HALF, /* Half-precision grayscale + alpha */
    SAIL_PIXEL_FORMAT_BPP32_GRAYSCALE_FLOAT,      /* Single-precision grayscale */
    SAIL_PIXEL_FORMAT_BPP64_GRAYSCALE_ALPHA_FLOAT,/* Single-precision grayscale + alpha */
    SAIL_PIXEL_FORMAT_BPP48_RGB_HALF,             /* Half-precision RGB (16-bit per channel) */
    SAIL_PIXEL_FORMAT_BPP64_RGBA_HALF,            /* Half-precision RGBA */
    SAIL_PIXEL_FORMAT_BPP96_RGB_FLOAT,            /* Single-precision RGB (32-bit per channel) */
    SAIL_PIXEL_FORMAT_BPP128_RGBA_FLOAT,          /* Single-precision RGBA */
    SAIL_PIXEL_FORMAT_BPP32_GRAYSCALE_UINT,       /* 32-bit unsigned int grayscale */
    SAIL_PIXEL_FORMAT_BPP64_GRAYSCALE_ALPHA_UINT, /* 32-bit unsigned int grayscale + alpha */
    SAIL_PIXEL_FORMAT_BPP96_RGB_UINT,             /* 32-bit unsigned int RGB */
    SAIL_PIXEL_FORMAT_BPP128_RGBA_UINT,           /* 32-bit unsigned int RGBA */
};

/* Chroma subsampling. See https://en.wikipedia.org/wiki/Chroma_subsampling */
enum SailChromaSubsampling
{
    SAIL_CHROMA_SUBSAMPLING_UNKNOWN,
    SAIL_CHROMA_SUBSAMPLING_311,
    SAIL_CHROMA_SUBSAMPLING_400,
    SAIL_CHROMA_SUBSAMPLING_410,
    SAIL_CHROMA_SUBSAMPLING_411,
    SAIL_CHROMA_SUBSAMPLING_420,
    SAIL_CHROMA_SUBSAMPLING_421,
    SAIL_CHROMA_SUBSAMPLING_422,
    SAIL_CHROMA_SUBSAMPLING_444,
};

/* Orientation. */
enum SailOrientation
{
    SAIL_ORIENTATION_NORMAL,
    SAIL_ORIENTATION_ROTATED_90,
    SAIL_ORIENTATION_ROTATED_180,
    SAIL_ORIENTATION_ROTATED_270,
    SAIL_ORIENTATION_MIRRORED_HORIZONTALLY,
    SAIL_ORIENTATION_MIRRORED_VERTICALLY,
    SAIL_ORIENTATION_MIRRORED_HORIZONTALLY_ROTATED_90,
    SAIL_ORIENTATION_MIRRORED_HORIZONTALLY_ROTATED_270,
};

/* Pixels compression types. */
enum SailCompression
{
    SAIL_COMPRESSION_UNKNOWN,       /* Unknown compression. */
    SAIL_COMPRESSION_NONE,          /* No compression at all. */

    SAIL_COMPRESSION_ADOBE_DEFLATE, /* Deflate compression, as recognized by Adobe. */
    SAIL_COMPRESSION_AV1,           /* AOMedia Video 1. */
    SAIL_COMPRESSION_CCITT_FAX3,    /* CCITT Group 3 fax encoding. */
    SAIL_COMPRESSION_CCITT_FAX4,    /* CCITT Group 4 fax encoding. */
    SAIL_COMPRESSION_CCITT_RLE,     /* CCITT modified Huffman RLE. */
    SAIL_COMPRESSION_CCITT_RLEW,    /* #1 w/ word alignment. */
    SAIL_COMPRESSION_CCITT_T4,      /* CCITT T.4 (TIFF 6 name). */
    SAIL_COMPRESSION_CCITT_T6,      /* CCITT T.6 (TIFF 6 name). */
    SAIL_COMPRESSION_DCS,           /* Kodak DCS encoding. */
    SAIL_COMPRESSION_DEFLATE,       /* Deflate compression. */
    SAIL_COMPRESSION_IT8_BL,        /* IT8 Binary line art. */
    SAIL_COMPRESSION_IT8_CTPAD,     /* IT8 CT w/padding. */
    SAIL_COMPRESSION_IT8_LW,        /* IT8 Linework RLE. */
    SAIL_COMPRESSION_IT8_MP,        /* IT8 Monochrome picture. */
    SAIL_COMPRESSION_JBIG,          /* ISO JBIG. */
    SAIL_COMPRESSION_JPEG,          /* JPEG DCT compression. */
    SAIL_COMPRESSION_JPEG_2000,     /* Leadtools JPEG 2000. */
    SAIL_COMPRESSION_JPEG_XL,       /* JPEG XL. */
    SAIL_COMPRESSION_JPEG_XR,       /* JPEG XR. */
    SAIL_COMPRESSION_LERC,          /* ESRI Lerc codec. */
    SAIL_COMPRESSION_LZMA,          /* LZMA2. */
    SAIL_COMPRESSION_LZW,           /* Lempel-Ziv & Welch. */
    SAIL_COMPRESSION_NEXT,          /* NeXT 2-bit RLE. */
    SAIL_COMPRESSION_OJPEG,         /* !6.0 JPEG. */
    SAIL_COMPRESSION_PACKBITS,      /* Macintosh RLE. */
    SAIL_COMPRESSION_PIXAR_FILM,    /* Pixar companded 10bit LZW. */
    SAIL_COMPRESSION_PIXAR_LOG,     /* Pixar companded 11bit ZIP. */
    SAIL_COMPRESSION_QOI,           /* Quite OK Image. */
    SAIL_COMPRESSION_RLE,           /* RLE compression. */
    SAIL_COMPRESSION_SGI_LOG,       /* SGI Log Luminance RLE. */
    SAIL_COMPRESSION_SGI_LOG24,     /* SGI Log 24-bit packed. */
    SAIL_COMPRESSION_T43,           /* !TIFF/FX T.43 colour by layered JBIG compression. */
    SAIL_COMPRESSION_T85,           /* !TIFF/FX T.85 JBIG compression. */
    SAIL_COMPRESSION_THUNDERSCAN,   /* ThunderScan RLE. */
    SAIL_COMPRESSION_WEBP,          /* WEBP. */
    SAIL_COMPRESSION_ZIP,           /* ZIP. */
    SAIL_COMPRESSION_ZSTD,          /* ZSTD. */

    /* Since 1.0.0 */
    SAIL_COMPRESSION_ASTC,          /* Adaptive Scalable Texture Compression. */
    SAIL_COMPRESSION_ATC,           /* AMD Texture Compression (Qualcomm Adreno). */
    SAIL_COMPRESSION_B44,           /* Lossy 4x4 pixel block compression (OpenEXR). */
    SAIL_COMPRESSION_B44A,          /* B44 with flat fields (OpenEXR). */
    SAIL_COMPRESSION_BC4,           /* Single channel compression. */
    SAIL_COMPRESSION_BC5,           /* Two channel compression (normal maps). */
    SAIL_COMPRESSION_BC6H,          /* HDR compression (RGB float). */
    SAIL_COMPRESSION_BC7,           /* High quality RGB/RGBA compression. */
    SAIL_COMPRESSION_BPG,           /* Better Portable Graphics (based on HEVC). */
    SAIL_COMPRESSION_BROTLI,        /* Brotli compression. */
    SAIL_COMPRESSION_DWAA,          /* Lossy DCT-based compression (OpenEXR). */
    SAIL_COMPRESSION_DWAB,          /* DWAA with better compression (OpenEXR). */
    SAIL_COMPRESSION_DXT1,          /* S3TC BC1 - RGB or RGB+1bit alpha. */
    SAIL_COMPRESSION_DXT3,          /* S3TC BC2 - RGBA with explicit alpha. */
    SAIL_COMPRESSION_DXT5,          /* S3TC BC3 - RGBA with interpolated alpha. */
    SAIL_COMPRESSION_EAC,           /* ETC2 Alpha Compression. */
    SAIL_COMPRESSION_ETC1,          /* Ericsson Texture Compression (Android, OpenGL ES). */
    SAIL_COMPRESSION_ETC2,          /* Improved ETC for OpenGL ES 3.0+. */
    SAIL_COMPRESSION_HEVC,          /* High Efficiency Video Coding (H.265). */
    SAIL_COMPRESSION_JPEG_LS,       /* Lossless/near-lossless JPEG (ISO-14495). */
    SAIL_COMPRESSION_LZ4,           /* Extremely fast compression. */
    SAIL_COMPRESSION_PIZ,           /* Wavelet compression (OpenEXR). */
    SAIL_COMPRESSION_PVRTC,         /* PowerVR Texture Compression (iOS). */
    SAIL_COMPRESSION_PVRTC2,        /* PowerVR Texture Compression v2. */
    SAIL_COMPRESSION_PXR24,         /* Lossy 24-bit float compression (Pixar/OpenEXR). */
    SAIL_COMPRESSION_SNAPPY,        /* Fast compression by Google. */
    SAIL_COMPRESSION_VVC,           /* Versatile Video Coding (H.266). */
    SAIL_COMPRESSION_ZIPS,          /* ZIP single scanline (OpenEXR). */
};

/* Meta data. */
enum SailMetaData
{
    /* Unknown meta data type. */
    SAIL_META_DATA_UNKNOWN,

    SAIL_META_DATA_ARTIST,
    SAIL_META_DATA_AUTHOR,
    SAIL_META_DATA_COMMENT,
    SAIL_META_DATA_COMPUTER,
    SAIL_META_DATA_COPYRIGHT,
    SAIL_META_DATA_CREATION_TIME,
    SAIL_META_DATA_DESCRIPTION,
    SAIL_META_DATA_DISCLAIMER,
    SAIL_META_DATA_DOCUMENT,
    SAIL_META_DATA_EXIF, /* This one may or may not start with "Exif\0\0". */
    SAIL_META_DATA_ID,
    SAIL_META_DATA_IPTC,
    SAIL_META_DATA_JOB,
    SAIL_META_DATA_JUMBF,
    SAIL_META_DATA_LABEL,
    SAIL_META_DATA_MAKE,
    SAIL_META_DATA_MODEL,
    SAIL_META_DATA_NAME,
    SAIL_META_DATA_PRINTER,
    SAIL_META_DATA_SOFTWARE,
    SAIL_META_DATA_SOFTWARE_VERSION,
    SAIL_META_DATA_SOURCE,
    SAIL_META_DATA_TIME_CONSUMED,
    SAIL_META_DATA_TITLE,
    SAIL_META_DATA_URL,
    SAIL_META_DATA_WARNING,
    SAIL_META_DATA_XMP,
};

/* Resolution units. */
enum SailResolutionUnit
{
    SAIL_RESOLUTION_UNIT_UNKNOWN,
    SAIL_RESOLUTION_UNIT_MICROMETER,
    SAIL_RESOLUTION_UNIT_CENTIMETER,
    SAIL_RESOLUTION_UNIT_METER,
    SAIL_RESOLUTION_UNIT_INCH,
};

/* Codec features. */
enum SailCodecFeature
{
    /* Unknown codec feature used to indicate an error in parsing functions. */
    SAIL_CODEC_FEATURE_UNKNOWN = 1 << 0,

    /* Can load or save static images. */
    SAIL_CODEC_FEATURE_STATIC = 1 << 1,

    /* Can load or save animated images. */
    SAIL_CODEC_FEATURE_ANIMATED = 1 << 2,

    /* Can load or save multi-paged (but not animated) images. */
    SAIL_CODEC_FEATURE_MULTI_PAGED = 1 << 3,

    /* Can load or save image meta data like JPEG comments or EXIF. */
    SAIL_CODEC_FEATURE_META_DATA = 1 << 4,

    /* Can load or save interlaced images. */
    SAIL_CODEC_FEATURE_INTERLACED = 1 << 5,

    /* Can load or save embedded ICC profiles. */
    SAIL_CODEC_FEATURE_ICCP = 1 << 6,

    /* Can preserve the source image information. */
    SAIL_CODEC_FEATURE_SOURCE_IMAGE = 1 << 7,
};

/* Load or save options. */
enum SailOption
{
    /*
     * Instruction to load or save image meta data like JPEG comments or EXIF.
     * Populating special properties in source images is also affected by this option.
     */
    SAIL_OPTION_META_DATA = 1 << 0,

    /* Instruction to save interlaced images. Specifying this option for loading operations has no effect. */
    SAIL_OPTION_INTERLACED = 1 << 1,

    /* Instruction to load or save embedded ICC profile. */
    SAIL_OPTION_ICCP = 1 << 2,

    /*
     * Instruction to preserve the source image information in loading operations.
     * Specifying this option for saving operations has no effect.
     */
    SAIL_OPTION_SOURCE_IMAGE = 1 << 3,
};
