/*
 * Copyright (c) 2014-2020 Hayaki Saito
 *
 * 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.
 */

#include <stddef.h>  /* for size_t */

#ifndef LIBSIXEL_SIXEL_H
#define LIBSIXEL_SIXEL_H

#ifdef _WIN32
# define SIXELAPI __declspec(dllexport)
#else
# define SIXELAPI
#endif

#define LIBSIXEL_VERSION "1.8.6"
#define LIBSIXEL_ABI_VERSION "1:6:0"

typedef unsigned char sixel_index_t;

/* limitations */
#define SIXEL_OUTPUT_PACKET_SIZE     16384
#define SIXEL_PALETTE_MIN            2
#define SIXEL_PALETTE_MAX            256
#define SIXEL_USE_DEPRECATED_SYMBOLS 1
#define SIXEL_ALLOCATE_BYTES_MAX     10248UL * 1024UL * 128UL   /* up to 128M */
#define SIXEL_WIDTH_LIMIT            1000000
#define SIXEL_HEIGHT_LIMIT           1000000

/* loader settings */
#define SIXEL_DEFALUT_GIF_DELAY         1

/* return value */
typedef int SIXELSTATUS;
#define SIXEL_OK                0x0000                          /* succeeded */
#define SIXEL_FALSE             0x1000                          /* failed */

#define SIXEL_RUNTIME_ERROR     (SIXEL_FALSE         | 0x0100)  /* runtime error */
#define SIXEL_LOGIC_ERROR       (SIXEL_FALSE         | 0x0200)  /* logic error */
#define SIXEL_FEATURE_ERROR     (SIXEL_FALSE         | 0x0300)  /* feature not enabled */
#define SIXEL_LIBC_ERROR        (SIXEL_FALSE         | 0x0400)  /* errors caused by curl */
#define SIXEL_CURL_ERROR        (SIXEL_FALSE         | 0x0500)  /* errors occures in libc functions */
#define SIXEL_JPEG_ERROR        (SIXEL_FALSE         | 0x0600)  /* errors occures in libjpeg functions */
#define SIXEL_PNG_ERROR         (SIXEL_FALSE         | 0x0700)  /* errors occures in libpng functions */
#define SIXEL_GDK_ERROR         (SIXEL_FALSE         | 0x0800)  /* errors occures in gdk functions */
#define SIXEL_GD_ERROR          (SIXEL_FALSE         | 0x0900)  /* errors occures in gd functions */
#define SIXEL_STBI_ERROR        (SIXEL_FALSE         | 0x0a00)  /* errors occures in stb_image functions */
#define SIXEL_STBIW_ERROR       (SIXEL_FALSE         | 0x0b00)  /* errors occures in stb_image_write functions */

#define SIXEL_INTERRUPTED       (SIXEL_OK            | 0x0001)  /* interrupted by a signal */

#define SIXEL_BAD_ALLOCATION    (SIXEL_RUNTIME_ERROR | 0x0001)  /* malloc() failed */
#define SIXEL_BAD_ARGUMENT      (SIXEL_RUNTIME_ERROR | 0x0002)  /* bad argument detected */
#define SIXEL_BAD_INPUT         (SIXEL_RUNTIME_ERROR | 0x0003)  /* bad input detected */
#define SIXEL_BAD_INTEGER_OVERFLOW (SIXEL_RUNTIME_ERROR | 0x0004)  /* integer overflow */

#define SIXEL_NOT_IMPLEMENTED   (SIXEL_FEATURE_ERROR | 0x0001)  /* feature not implemented */

#define SIXEL_SUCCEEDED(status) (((status) & 0x1000) == 0)
#define SIXEL_FAILED(status)    (((status) & 0x1000) != 0)

/* method for finding the largest dimension for splitting,
 * and sorting by that component */
#define SIXEL_LARGE_AUTO   0x0   /* choose automatically the method for finding the largest
                                    dimension */
#define SIXEL_LARGE_NORM   0x1   /* simply comparing the range in RGB space */
#define SIXEL_LARGE_LUM    0x2   /* transforming into luminosities before the comparison */

/* method for choosing a color from the box */
#define SIXEL_REP_AUTO            0x0  /* choose automatically the method for selecting
                                          representative color from each box */
#define SIXEL_REP_CENTER_BOX      0x1  /* choose the center of the box */
#define SIXEL_REP_AVERAGE_COLORS  0x2  /* choose the average all the color
                                          in the box (specified in Heckbert's paper) */
#define SIXEL_REP_AVERAGE_PIXELS  0x3  /* choose the average all the pixels in the box */

/* method for diffusing */
#define SIXEL_DIFFUSE_AUTO        0x0  /* choose diffusion type automatically */
#define SIXEL_DIFFUSE_NONE        0x1  /* don't diffuse */
#define SIXEL_DIFFUSE_ATKINSON    0x2  /* diffuse with Bill Atkinson's method */
#define SIXEL_DIFFUSE_FS          0x3  /* diffuse with Floyd-Steinberg method */
#define SIXEL_DIFFUSE_JAJUNI      0x4  /* diffuse with Jarvis, Judice & Ninke method */
#define SIXEL_DIFFUSE_STUCKI      0x5  /* diffuse with Stucki's method */
#define SIXEL_DIFFUSE_BURKES      0x6  /* diffuse with Burkes' method */
#define SIXEL_DIFFUSE_A_DITHER    0x7  /* positionally stable arithmetic dither */
#define SIXEL_DIFFUSE_X_DITHER    0x8  /* positionally stable arithmetic xor based dither */

/* quality modes */
#define SIXEL_QUALITY_AUTO        0x0  /* choose quality mode automatically */
#define SIXEL_QUALITY_HIGH        0x1  /* high quality palette construction */
#define SIXEL_QUALITY_LOW         0x2  /* low quality palette construction */
#define SIXEL_QUALITY_FULL        0x3  /* full quality palette construction */
#define SIXEL_QUALITY_HIGHCOLOR   0x4  /* high color */

/* built-in dither */
#define SIXEL_BUILTIN_MONO_DARK   0x0  /* monochrome terminal with dark background */
#define SIXEL_BUILTIN_MONO_LIGHT  0x1  /* monochrome terminal with light background */
#define SIXEL_BUILTIN_XTERM16     0x2  /* xterm 16color */
#define SIXEL_BUILTIN_XTERM256    0x3  /* xterm 256color */
#define SIXEL_BUILTIN_VT340_MONO  0x4  /* vt340 monochrome */
#define SIXEL_BUILTIN_VT340_COLOR 0x5  /* vt340 color */
#define SIXEL_BUILTIN_G1          0x6  /* 1bit grayscale */
#define SIXEL_BUILTIN_G2          0x7  /* 2bit grayscale */
#define SIXEL_BUILTIN_G4          0x8  /* 4bit grayscale */
#define SIXEL_BUILTIN_G8          0x9  /* 8bit grayscale */

/* offset value of pixelFormat */
#define SIXEL_FORMATTYPE_COLOR     (0)
#define SIXEL_FORMATTYPE_GRAYSCALE (1 << 6)
#define SIXEL_FORMATTYPE_PALETTE   (1 << 7)

/* pixelformat type of input image
   NOTE: for compatibility, the value of PIXELFORAMT_COLOR_RGB888 must be 3 */
#define SIXEL_PIXELFORMAT_RGB555   (SIXEL_FORMATTYPE_COLOR     | 0x01) /* 15bpp */
#define SIXEL_PIXELFORMAT_RGB565   (SIXEL_FORMATTYPE_COLOR     | 0x02) /* 16bpp */
#define SIXEL_PIXELFORMAT_RGB888   (SIXEL_FORMATTYPE_COLOR     | 0x03) /* 24bpp */
#define SIXEL_PIXELFORMAT_BGR555   (SIXEL_FORMATTYPE_COLOR     | 0x04) /* 15bpp */
#define SIXEL_PIXELFORMAT_BGR565   (SIXEL_FORMATTYPE_COLOR     | 0x05) /* 16bpp */
#define SIXEL_PIXELFORMAT_BGR888   (SIXEL_FORMATTYPE_COLOR     | 0x06) /* 24bpp */
#define SIXEL_PIXELFORMAT_ARGB8888 (SIXEL_FORMATTYPE_COLOR     | 0x10) /* 32bpp */
#define SIXEL_PIXELFORMAT_RGBA8888 (SIXEL_FORMATTYPE_COLOR     | 0x11) /* 32bpp */
#define SIXEL_PIXELFORMAT_ABGR8888 (SIXEL_FORMATTYPE_COLOR     | 0x12) /* 32bpp */
#define SIXEL_PIXELFORMAT_BGRA8888 (SIXEL_FORMATTYPE_COLOR     | 0x13) /* 32bpp */
#define SIXEL_PIXELFORMAT_G1       (SIXEL_FORMATTYPE_GRAYSCALE | 0x00) /* 1bpp grayscale */
#define SIXEL_PIXELFORMAT_G2       (SIXEL_FORMATTYPE_GRAYSCALE | 0x01) /* 2bpp grayscale */
#define SIXEL_PIXELFORMAT_G4       (SIXEL_FORMATTYPE_GRAYSCALE | 0x02) /* 4bpp grayscale */
#define SIXEL_PIXELFORMAT_G8       (SIXEL_FORMATTYPE_GRAYSCALE | 0x03) /* 8bpp grayscale */
#define SIXEL_PIXELFORMAT_AG88     (SIXEL_FORMATTYPE_GRAYSCALE | 0x13) /* 16bpp gray+alpha */
#define SIXEL_PIXELFORMAT_GA88     (SIXEL_FORMATTYPE_GRAYSCALE | 0x23) /* 16bpp gray+alpha */
#define SIXEL_PIXELFORMAT_PAL1     (SIXEL_FORMATTYPE_PALETTE   | 0x00) /* 1bpp palette */
#define SIXEL_PIXELFORMAT_PAL2     (SIXEL_FORMATTYPE_PALETTE   | 0x01) /* 2bpp palette */
#define SIXEL_PIXELFORMAT_PAL4     (SIXEL_FORMATTYPE_PALETTE   | 0x02) /* 4bpp palette */
#define SIXEL_PIXELFORMAT_PAL8     (SIXEL_FORMATTYPE_PALETTE   | 0x03) /* 8bpp palette */

/* palette type */
#define SIXEL_PALETTETYPE_AUTO     0   /* choose palette type automatically */
#define SIXEL_PALETTETYPE_HLS      1   /* HLS colorspace */
#define SIXEL_PALETTETYPE_RGB      2   /* RGB colorspace */

/* policies of SIXEL encoding */
#define SIXEL_ENCODEPOLICY_AUTO    0   /* choose encoding policy automatically */
#define SIXEL_ENCODEPOLICY_FAST    1   /* encode as fast as possible */
#define SIXEL_ENCODEPOLICY_SIZE    2   /* encode to as small sixel sequence as possible */

/* method for re-sampling */
#define SIXEL_RES_NEAREST          0   /* Use nearest neighbor method */
#define SIXEL_RES_GAUSSIAN         1   /* Use guaussian filter */
#define SIXEL_RES_HANNING          2   /* Use hanning filter */
#define SIXEL_RES_HAMMING          3   /* Use hamming filter */
#define SIXEL_RES_BILINEAR         4   /* Use bilinear filter */
#define SIXEL_RES_WELSH            5   /* Use welsh filter */
#define SIXEL_RES_BICUBIC          6   /* Use bicubic filter */
#define SIXEL_RES_LANCZOS2         7   /* Use lanczos-2 filter */
#define SIXEL_RES_LANCZOS3         8   /* Use lanczos-3 filter */
#define SIXEL_RES_LANCZOS4         9   /* Use lanczos-4 filter */

/* image format */
#define SIXEL_FORMAT_GIF           0x0 /* read only */
#define SIXEL_FORMAT_PNG           0x1 /* read/write */
#define SIXEL_FORMAT_BMP           0x2 /* read only */
#define SIXEL_FORMAT_JPG           0x3 /* read only */
#define SIXEL_FORMAT_TGA           0x4 /* read only */
#define SIXEL_FORMAT_WBMP          0x5 /* read only with --with-gd configure option */
#define SIXEL_FORMAT_TIFF          0x6 /* read only */
#define SIXEL_FORMAT_SIXEL         0x7 /* read only */
#define SIXEL_FORMAT_PNM           0x8 /* read only */
#define SIXEL_FORMAT_GD2           0x9 /* read only with --with-gd configure option */
#define SIXEL_FORMAT_PSD           0xa /* read only */
#define SIXEL_FORMAT_HDR           0xb /* read only */

/* loop mode */
#define SIXEL_LOOP_AUTO            0   /* honer the setting of GIF header */
#define SIXEL_LOOP_FORCE           1   /* always enable loop */
#define SIXEL_LOOP_DISABLE         2   /* always disable loop */

/* setopt flags */
#define SIXEL_OPTFLAG_INPUT             ('i')  /* -i, --input: specify input file name. */
#define SIXEL_OPTFLAG_OUTPUT            ('o')  /* -o, --output: specify output file name. */
#define SIXEL_OPTFLAG_OUTFILE           ('o')  /* -o, --outfile: specify output file name. */
#define SIXEL_OPTFLAG_7BIT_MODE         ('7')  /* -7, --7bit-mode: for 7bit terminals or printers (default) */
#define SIXEL_OPTFLAG_8BIT_MODE         ('8')  /* -8, --8bit-mode: for 8bit terminals or printers */
#define SIXEL_OPTFLAG_HAS_GRI_ARG_LIMIT ('R')  /* -R, --gri-limit: limit arguments of DECGRI('!') to 255 */
#define SIXEL_OPTFLAG_COLORS            ('p')  /* -p COLORS, --colors=COLORS: specify number of colors */
#define SIXEL_OPTFLAG_MAPFILE           ('m')  /* -m FILE, --mapfile=FILE: specify set of colors */
#define SIXEL_OPTFLAG_MONOCHROME        ('e')  /* -e, --monochrome: output monochrome sixel image */
#define SIXEL_OPTFLAG_INSECURE          ('k')  /* -k, --insecure: allow to connect to SSL sites without certs */
#define SIXEL_OPTFLAG_INVERT            ('i')  /* -i, --invert: assume the terminal background color */
#define SIXEL_OPTFLAG_HIGH_COLOR        ('I')  /* -I, --high-color: output 15bpp sixel image */
#define SIXEL_OPTFLAG_USE_MACRO         ('u')  /* -u, --use-macro: use DECDMAC and DEVINVM sequences */
#define SIXEL_OPTFLAG_MACRO_NUMBER      ('n')  /* -n MACRONO, --macro-number=MACRONO:
                                                  specify macro register number */
#define SIXEL_OPTFLAG_COMPLEXION_SCORE  ('C')  /* -C COMPLEXIONSCORE, --complexion-score=COMPLEXIONSCORE:
                                                  specify an number argument for the score of
                                                  complexion correction. */
#define SIXEL_OPTFLAG_IGNORE_DELAY      ('g')  /* -g, --ignore-delay: render GIF animation without delay */
#define SIXEL_OPTFLAG_STATIC            ('S')  /* -S, --static: render animated GIF as a static image */
#define SIXEL_OPTFLAG_DIFFUSION         ('d')  /* -d DIFFUSIONTYPE, --diffusion=DIFFUSIONTYPE:
                                                  choose diffusion method which used with -p option.
                                                  DIFFUSIONTYPE is one of them:
                                                    auto     -> choose diffusion type
                                                                automatically (default)
                                                    none     -> do not diffuse
                                                    fs       -> Floyd-Steinberg method
                                                    atkinson -> Bill Atkinson's method
                                                    jajuni   -> Jarvis, Judice & Ninke
                                                    stucki   -> Stucki's method
                                                    burkes   -> Burkes' method
                                                    a_dither -> positionally stable
                                                                arithmetic dither
                                                    a_dither -> positionally stable
                                                                arithmetic xor based dither
                                                */
#define SIXEL_OPTFLAG_FIND_LARGEST      ('f')  /* -f FINDTYPE, --find-largest=FINDTYPE:
                                                  choose method for finding the largest
                                                  dimension of median cut boxes for
                                                  splitting, make sense only when -p
                                                  option (color reduction) is
                                                  specified
                                                  FINDTYPE is one of them:
                                                    auto -> choose finding method
                                                            automatically (default)
                                                    norm -> simply comparing the
                                                            range in RGB space
                                                    lum  -> transforming into
                                                            luminosities before the
                                                            comparison
                                                */
#define SIXEL_OPTFLAG_SELECT_COLOR      ('s')  /* -s SELECTTYPE, --select-color=SELECTTYPE
                                                  choose the method for selecting
                                                  representative color from each
                                                  median-cut box, make sense only
                                                  when -p option (color reduction) is
                                                  specified
                                                  SELECTTYPE is one of them:
                                                    auto      -> choose selecting
                                                                 method automatically
                                                                 (default)
                                                    center    -> choose the center of
                                                                 the box
                                                    average    -> calculate the color
                                                                 average into the box
                                                    histogram -> similar with average
                                                                 but considers color
                                                                 histogram
                                                */
#define SIXEL_OPTFLAG_CROP              ('c')  /* -c REGION, --crop=REGION:
                                                  crop source image to fit the
                                                  specified geometry. REGION should
                                                  be formatted as '%dx%d+%d+%d'
                                                */
#define SIXEL_OPTFLAG_WIDTH             ('w')  /* -w WIDTH, --width=WIDTH:
                                                  resize image to specified width
                                                  WIDTH is represented by the
                                                  following syntax
                                                    auto       -> preserving aspect
                                                                  ratio (default)
                                                    <number>%  -> scale width with
                                                                  given percentage
                                                    <number>   -> scale width with
                                                                  pixel counts
                                                    <number>px -> scale width with
                                                                  pixel counts
                                                */
#define SIXEL_OPTFLAG_HEIGHT            ('h')  /* -h HEIGHT, --height=HEIGHT:
                                                   resize image to specified height
                                                   HEIGHT is represented by the
                                                   following syntax
                                                     auto       -> preserving aspect
                                                                   ratio (default)
                                                     <number>%  -> scale height with
                                                                   given percentage
                                                     <number>   -> scale height with
                                                                   pixel counts
                                                     <number>px -> scale height with
                                                                   pixel counts
                                                */
#define SIXEL_OPTFLAG_RESAMPLING        ('r')  /* -r RESAMPLINGTYPE, --resampling=RESAMPLINGTYPE:
                                                  choose resampling filter used
                                                  with -w or -h option (scaling)
                                                  RESAMPLINGTYPE is one of them:
                                                    nearest  -> Nearest-Neighbor
                                                                method
                                                    gaussian -> Gaussian filter
                                                    hanning  -> Hanning filter
                                                    hamming  -> Hamming filter
                                                    bilinear -> Bilinear filter
                                                                (default)
                                                    welsh    -> Welsh filter
                                                    bicubic  -> Bicubic filter
                                                    lanczos2 -> Lanczos-2 filter
                                                    lanczos3 -> Lanczos-3 filter
                                                    lanczos4 -> Lanczos-4 filter
                                                */
#define SIXEL_OPTFLAG_QUALITY           ('q')  /* -q QUALITYMODE, --quality=QUALITYMODE:
                                                  select quality of color
                                                  quanlization.
                                                    auto -> decide quality mode
                                                            automatically (default)
                                                    low  -> low quality and high
                                                            speed mode
                                                    high -> high quality and low
                                                            speed mode
                                                    full -> full quality and careful
                                                            speed mode
                                                */
#define SIXEL_OPTFLAG_LOOPMODE          ('l')  /* -l LOOPMODE, --loop-control=LOOPMODE:
                                                  select loop control mode for GIF
                                                  animation.
                                                    auto    -> honor the setting of
                                                               GIF header (default)
                                                    force   -> always enable loop
                                                    disable -> always disable loop
                                                */
#define SIXEL_OPTFLAG_PALETTE_TYPE      ('t')  /* -t PALETTETYPE, --palette-type=PALETTETYPE:
                                                  select palette color space type
                                                    auto -> choose palette type
                                                            automatically (default)
                                                    hls  -> use HLS color space
                                                    rgb  -> use RGB color space
                                                */
#define SIXEL_OPTFLAG_BUILTIN_PALETTE   ('b')  /* -b BUILTINPALETTE, --builtin-palette=BUILTINPALETTE:
                                                  select built-in palette type
                                                    xterm16    -> X default 16 color map
                                                    xterm256   -> X default 256 color map
                                                    vt340mono  -> VT340 monochrome map
                                                    vt340color -> VT340 color map
                                                    gray1      -> 1bit grayscale map
                                                    gray2      -> 2bit grayscale map
                                                    gray4      -> 4bit grayscale map
                                                    gray8      -> 8bit grayscale map
                                                */
#define SIXEL_OPTFLAG_ENCODE_POLICY     ('E')  /* -E ENCODEPOLICY, --encode-policy=ENCODEPOLICY:
                                                  select encoding policy
                                                    auto -> choose encoding policy
                                                            automatically (default)
                                                    fast -> encode as fast as possible
                                                    size -> encode to as small sixel
                                                            sequence as possible
                                                */
#define SIXEL_OPTFLAG_BGCOLOR           ('B')  /* -B BGCOLOR, --bgcolor=BGCOLOR:
                                                  specify background color
                                                  BGCOLOR is represented by the
                                                  following syntax
                                                    #rgb
                                                    #rrggbb
                                                    #rrrgggbbb
                                                    #rrrrggggbbbb
                                                    rgb:r/g/b
                                                    rgb:rr/gg/bb
                                                    rgb:rrr/ggg/bbb
                                                    rgb:rrrr/gggg/bbbb
                                                */
#define SIXEL_OPTFLAG_PENETRATE         ('P')  /* -P, --penetrate:
                                                  penetrate GNU Screen using DCS
                                                  pass-through sequence */
#define SIXEL_OPTFLAG_PIPE_MODE         ('D')  /* -D, --pipe-mode: (deprecated)
                                                  read source images from stdin continuously */
#define SIXEL_OPTFLAG_VERBOSE           ('v')  /* -v, --verbose: show debugging info */
#define SIXEL_OPTFLAG_VERSION           ('V')  /* -V, --version: show version and license info */
#define SIXEL_OPTFLAG_HELP              ('H')  /* -H, --help: show this help */

#if SIXEL_USE_DEPRECATED_SYMBOLS
/* output character size */
enum characterSize {
    CSIZE_7BIT = 0,  /* 7bit character */
    CSIZE_8BIT = 1   /* 8bit character */
};

/* method for finding the largest dimension for splitting,
 * and sorting by that component */
enum methodForLargest {
    LARGE_AUTO = 0,  /* choose automatically the method for finding the largest
                        dimension */
    LARGE_NORM = 1,  /* simply comparing the range in RGB space */
    LARGE_LUM  = 2   /* transforming into luminosities before the comparison */
};

/* method for choosing a color from the box */
enum methodForRep {
    REP_AUTO           = 0, /* choose automatically the method for selecting
                               representative color from each box */
    REP_CENTER_BOX     = 1, /* choose the center of the box */
    REP_AVERAGE_COLORS = 2, /* choose the average all the color
                               in the box (specified in Heckbert's paper) */
    REP_AVERAGE_PIXELS = 3  /* choose the average all the pixels in the box */
};

/* method for diffusing */
enum methodForDiffuse {
    DIFFUSE_AUTO     = 0, /* choose diffusion type automatically */
    DIFFUSE_NONE     = 1, /* don't diffuse */
    DIFFUSE_ATKINSON = 2, /* diffuse with Bill Atkinson's method */
    DIFFUSE_FS       = 3, /* diffuse with Floyd-Steinberg method */
    DIFFUSE_JAJUNI   = 4, /* diffuse with Jarvis, Judice & Ninke method */
    DIFFUSE_STUCKI   = 5, /* diffuse with Stucki's method */
    DIFFUSE_BURKES   = 6, /* diffuse with Burkes' method */
    DIFFUSE_A_DITHER = 7, /* positionally stable arithmetic dither */
    DIFFUSE_X_DITHER = 8  /* positionally stable arithmetic xor based dither */
};

/* quality modes */
enum qualityMode {
    QUALITY_AUTO      = 0, /* choose quality mode automatically */
    QUALITY_HIGH      = 1, /* high quality palette construction */
    QUALITY_LOW       = 2, /* low quality palette construction */
    QUALITY_FULL      = 3, /* full quality palette construction */
    QUALITY_HIGHCOLOR = 4  /* high color */
};

/* built-in dither */
enum builtinDither {
    BUILTIN_MONO_DARK   = 0, /* monochrome terminal with dark background */
    BUILTIN_MONO_LIGHT  = 1, /* monochrome terminal with dark background */
    BUILTIN_XTERM16     = 2, /* xterm 16color */
    BUILTIN_XTERM256    = 3, /* xterm 256color */
    BUILTIN_VT340_MONO  = 4, /* vt340 monochrome */
    BUILTIN_VT340_COLOR = 5  /* vt340 color */
};

/* offset value of enum pixelFormat */
enum formatType {
    FORMATTYPE_COLOR     = 0,
    FORMATTYPE_GRAYSCALE = 1 << 6,
    FORMATTYPE_PALETTE   = 1 << 7
};

/* pixelformat type of input image
   NOTE: for compatibility, the value of PIXELFORAMT_COLOR_RGB888 must be 3 */
enum pixelFormat {
    PIXELFORMAT_RGB555   = FORMATTYPE_COLOR     | 0x01, /* 15bpp */
    PIXELFORMAT_RGB565   = FORMATTYPE_COLOR     | 0x02, /* 16bpp */
    PIXELFORMAT_RGB888   = FORMATTYPE_COLOR     | 0x03, /* 24bpp */
    PIXELFORMAT_BGR555   = FORMATTYPE_COLOR     | 0x04, /* 15bpp */
    PIXELFORMAT_BGR565   = FORMATTYPE_COLOR     | 0x05, /* 16bpp */
    PIXELFORMAT_BGR888   = FORMATTYPE_COLOR     | 0x06, /* 24bpp */
    PIXELFORMAT_ARGB8888 = FORMATTYPE_COLOR     | 0x10, /* 32bpp */
    PIXELFORMAT_RGBA8888 = FORMATTYPE_COLOR     | 0x11, /* 32bpp */
    PIXELFORMAT_G1       = FORMATTYPE_GRAYSCALE | 0x00, /* 1bpp grayscale */
    PIXELFORMAT_G2       = FORMATTYPE_GRAYSCALE | 0x01, /* 2bpp grayscale */
    PIXELFORMAT_G4       = FORMATTYPE_GRAYSCALE | 0x02, /* 4bpp grayscale */
    PIXELFORMAT_G8       = FORMATTYPE_GRAYSCALE | 0x03, /* 8bpp grayscale */
    PIXELFORMAT_AG88     = FORMATTYPE_GRAYSCALE | 0x13, /* 16bpp gray+alpha */
    PIXELFORMAT_GA88     = FORMATTYPE_GRAYSCALE | 0x23, /* 16bpp gray+alpha */
    PIXELFORMAT_PAL1     = FORMATTYPE_PALETTE   | 0x00, /* 1bpp palette */
    PIXELFORMAT_PAL2     = FORMATTYPE_PALETTE   | 0x01, /* 2bpp palette */
    PIXELFORMAT_PAL4     = FORMATTYPE_PALETTE   | 0x02, /* 4bpp palette */
    PIXELFORMAT_PAL8     = FORMATTYPE_PALETTE   | 0x03  /* 8bpp palette */
};

/* palette type */
enum paletteType {
    PALETTETYPE_AUTO = 0,     /* choose palette type automatically */
    PALETTETYPE_HLS  = 1,     /* HLS colorspace */
    PALETTETYPE_RGB  = 2      /* RGB colorspace */
};

/* policies of SIXEL encoding */
enum encodePolicy {
    ENCODEPOLICY_AUTO = 0,    /* choose encoding policy automatically */
    ENCODEPOLICY_FAST = 1,    /* encode as fast as possible */
    ENCODEPOLICY_SIZE = 2     /* encode to as small sixel sequence as possible */
};

/* method for re-sampling */
enum methodForResampling {
    RES_NEAREST  = 0,  /* Use nearest neighbor method */
    RES_GAUSSIAN = 1,  /* Use guaussian filter */
    RES_HANNING  = 2,  /* Use hanning filter */
    RES_HAMMING  = 3,  /* Use hamming filter */
    RES_BILINEAR = 4,  /* Use bilinear filter */
    RES_WELSH    = 5,  /* Use welsh filter */
    RES_BICUBIC  = 6,  /* Use bicubic filter */
    RES_LANCZOS2 = 7,  /* Use lanczos-2 filter */
    RES_LANCZOS3 = 8,  /* Use lanczos-3 filter */
    RES_LANCZOS4 = 9   /* Use lanczos-4 filter */
};
#endif

typedef void *(* sixel_malloc_t)(size_t);
typedef void *(* sixel_calloc_t)(size_t, size_t);
typedef void *(* sixel_realloc_t)(void *, size_t);
typedef void (* sixel_free_t)(void *);

struct sixel_allocator;
typedef struct sixel_allocator sixel_allocator_t;

#ifdef __cplusplus
extern "C" {
#endif

/* create allocator object */
SIXELSTATUS
sixel_allocator_new(
    sixel_allocator_t   /* out */ **ppallocator,  /* allocator object to be created */
    sixel_malloc_t      /* in */  fn_malloc,      /* custom malloc() function */
    sixel_calloc_t      /* in */  fn_calloc,      /* custom calloc() function */
    sixel_realloc_t     /* in */  fn_realloc,     /* custom realloc() function */
    sixel_free_t        /* in */  fn_free);       /* custom free() function */

/* increase reference count of allocator object (thread-unsafe) */
SIXELAPI void
sixel_allocator_ref(
    sixel_allocator_t /* in */ *allocator);  /* allocator object to be
                                                increment reference counter */

/* decrease reference count of output context object (thread-unsafe) */
SIXELAPI void
sixel_allocator_unref(sixel_allocator_t *allocator);

/* call custom malloc() */
SIXELAPI void *
sixel_allocator_malloc(
    sixel_allocator_t   /* in */ *allocator,  /* allocator object */
    size_t              /* in */ n);          /* allocation size */

/* call custom calloc() */
SIXELAPI void *
sixel_allocator_calloc(
    sixel_allocator_t   /* in */ *allocator,  /* allocator object */
    size_t              /* in */ nelm,        /* allocation size */
    size_t              /* in */ elsize);     /* allocation size */

/* call custom realloc() */
SIXELAPI void *
sixel_allocator_realloc(
    sixel_allocator_t   /* in */ *allocator,  /* allocator object */
    void                /* in */ *p,          /* existing buffer to be re-allocated */
    size_t              /* in */ n);          /* re-allocation size */

/* call custom free() */
SIXELAPI void
sixel_allocator_free(
    sixel_allocator_t   /* in */ *allocator,  /* allocator object */
    void                /* in */ *p);         /* existing buffer to be freed */

#ifdef HAVE_TESTS
extern volatile int sixel_debug_malloc_counter;

void *
sixel_bad_malloc(size_t size);

void *
sixel_bad_calloc(size_t count, size_t size);

void *
sixel_bad_realloc(void *ptr, size_t size);
#endif  /* HAVE_TESTS */

#ifdef __cplusplus
}
#endif

/* output context manipulation API */

struct sixel_output;
typedef struct sixel_output sixel_output_t;
typedef int (* sixel_write_function)(char *data, int size, void *priv);

#ifdef __cplusplus
extern "C" {
#endif

/* create new output context object */
SIXELAPI SIXELSTATUS
sixel_output_new(
    sixel_output_t          /* out */ **output,     /* output object to be created */
    sixel_write_function    /* in */  fn_write,     /* callback for output sixel */
    void                    /* in */ *priv,         /* private data given as
                                                       3rd argument of fn_write */
    sixel_allocator_t       /* in */  *allocator);  /* allocator, null if you use
                                                       default allocator */

/* deprecated: create an output object */
SIXELAPI __attribute__((deprecated)) sixel_output_t *
sixel_output_create(
    sixel_write_function /* in */ fn_write, /* callback for output sixel */
    void                 /* in */ *priv);   /* private data given as
                                               3rd argument of fn_write */
/* destroy output context object */
SIXELAPI void
sixel_output_destroy(sixel_output_t /* in */ *output); /* output context */

/* increase reference count of output context object (thread-unsafe) */
SIXELAPI void
sixel_output_ref(sixel_output_t /* in */ *output);     /* output context */

/* decrease reference count of output context object (thread-unsafe) */
SIXELAPI void
sixel_output_unref(sixel_output_t /* in */ *output);   /* output context */

/* get 8bit output mode which indicates whether it uses C1 control characters */
SIXELAPI int
sixel_output_get_8bit_availability(
    sixel_output_t /* in */ *output);   /* output context */

/* set 8bit output mode state */
SIXELAPI void
sixel_output_set_8bit_availability(
    sixel_output_t /* in */ *output,       /* output context */
    int            /* in */ availability); /* 0: do not use 8bit characters
                                              1: use 8bit characters */

/* set whether limit arguments of DECGRI('!') to 255 */
SIXELAPI void
sixel_output_set_gri_arg_limit(
    sixel_output_t /* in */ *output, /* output context */
    int            /* in */ value);  /* 0: don't limit arguments of DECGRI
                                        1: limit arguments of DECGRI to 255 */

/* set GNU Screen penetration feature enable or disable */
SIXELAPI void
sixel_output_set_penetrate_multiplexer(
    sixel_output_t /* in */ *output,    /* output context */
    int            /* in */ penetrate); /* 0: penetrate GNU Screen
                                           1: do not penetrate GNU Screen */

/* set whether we skip DCS envelope */
SIXELAPI void
sixel_output_set_skip_dcs_envelope(
    sixel_output_t /* in */ *output,   /* output context */
    int            /* in */ skip);     /* 0: output DCS envelope
                                          1: do not output DCS envelope */

/* set palette type: RGB or HLS */
SIXELAPI void
sixel_output_set_palette_type(
    sixel_output_t /* in */ *output,      /* output context */
    int            /* in */ palettetype); /* PALETTETYPE_RGB: RGB palette
                                             PALETTETYPE_HLS: HLS palette */

/* set encodeing policy: auto, fast or size */
SIXELAPI void
sixel_output_set_encode_policy(
    sixel_output_t /* in */ *output,    /* output context */
    int            /* in */ encode_policy);


#ifdef __cplusplus
}
#endif


/* color quantization API */

/* handle type of dither context object */
struct sixel_dither;
typedef struct sixel_dither sixel_dither_t;

#ifdef __cplusplus
extern "C" {
#endif

/* create dither context object */
SIXELAPI SIXELSTATUS
sixel_dither_new(
    sixel_dither_t      /* out */   **ppdither,  /* dither object to be created */
    int                 /* in */    ncolors,     /* required colors */
    sixel_allocator_t   /* in */    *allocator); /* allocator, null if you use
                                                    default allocator */

/* create dither context object */
SIXELAPI __attribute__((deprecated)) sixel_dither_t *
sixel_dither_create(int /* in */ ncolors); /* number of colors */

/* get built-in dither context object */
SIXELAPI sixel_dither_t *
sixel_dither_get(int builtin_dither); /* ID of built-in dither object */

/* destroy dither context object */
SIXELAPI void
sixel_dither_destroy(sixel_dither_t *dither); /* dither context object */

/* increase reference count of dither context object (thread-unsafe) */
SIXELAPI void
sixel_dither_ref(sixel_dither_t *dither); /* dither context object */

/* decrease reference count of dither context object (thread-unsafe) */
SIXELAPI void
sixel_dither_unref(sixel_dither_t *dither); /* dither context object */

/* initialize internal palette from specified pixel buffer */
SIXELAPI SIXELSTATUS
sixel_dither_initialize(
    sixel_dither_t *dither,                    /* dither context object */
    unsigned char /* in */ *data,              /* sample image */
    int           /* in */ width,              /* image width */
    int           /* in */ height,             /* image height */
    int           /* in */ pixelformat,        /* one of enum pixelFormat */
    int           /* in */ method_for_largest, /* method for finding the largest dimension */
    int           /* in */ method_for_rep,     /* method for choosing a color from the box */
    int           /* in */ quality_mode);      /* quality of histogram processing */

/* set diffusion type, choose from enum methodForDiffuse */
SIXELAPI void
sixel_dither_set_diffusion_type(
    sixel_dither_t /* in */ *dither,   /* dither context object */
    int /* in */ method_for_diffuse);  /* one of enum methodForDiffuse */

/* get number of palette colors */
SIXELAPI int
sixel_dither_get_num_of_palette_colors(
    sixel_dither_t /* in */ *dither);  /* dither context object */

/* get number of histogram colors */
SIXELAPI int
sixel_dither_get_num_of_histogram_colors(
    sixel_dither_t /* in */ *dither);  /* dither context object */

SIXELAPI __attribute__((deprecated)) int /* typoed! remains for compatibility. */
sixel_dither_get_num_of_histgram_colors(
    sixel_dither_t /* in */ *dither);  /* dither context object */

/* get palette */
SIXELAPI unsigned char *
sixel_dither_get_palette(
    sixel_dither_t /* in */ *dither);  /* dither context object */

/* set palette */
SIXELAPI void
sixel_dither_set_palette(
    sixel_dither_t /* in */ *dither,   /* dither context object */
    unsigned char  /* in */ *palette);

/* set the factor of complexion color correcting */
SIXELAPI void
sixel_dither_set_complexion_score(
    sixel_dither_t /* in */ *dither,   /* dither context object */
    int            /* in */ score);    /* complexion score (>= 1) */

/* set whether omitting palette difinition */
SIXELAPI void
sixel_dither_set_body_only(
    sixel_dither_t /* in */ *dither,   /* dither context object */
    int            /* in */ bodyonly); /* 0: output palette section(default)
                                          1: do not output palette section */
/* set whether optimize palette size */
SIXELAPI void
sixel_dither_set_optimize_palette(
    sixel_dither_t /* in */ *dither,   /* dither context object */
    int            /* in */ do_opt);   /* 0: optimize palette size
                                          1: don't optimize palette size */
/* set pixelformat */
SIXELAPI void
sixel_dither_set_pixelformat(
    sixel_dither_t /* in */ *dither,      /* dither context object */
    int            /* in */ pixelformat); /* one of enum pixelFormat */

/* set transparent */
SIXELAPI void
sixel_dither_set_transparent(
    sixel_dither_t /* in */ *dither,      /* dither context object */
    int            /* in */ transparent); /* transparent color index */

#ifdef __cplusplus
}
#endif

/* converter API */

typedef void * (* sixel_allocator_function)(size_t size);

#ifdef __cplusplus
extern "C" {
#endif

/* convert pixels into sixel format and write it to output context */
SIXELAPI SIXELSTATUS
sixel_encode(
    unsigned char  /* in */ *pixels,     /* pixel bytes */
    int            /* in */  width,      /* image width */
    int            /* in */  height,     /* image height */
    int            /* in */  depth,      /* color depth: now unused */
    sixel_dither_t /* in */ *dither,     /* dither context */
    sixel_output_t /* in */ *context);   /* output context */

/* convert sixel data into indexed pixel bytes and palette data */
SIXELAPI SIXELSTATUS
sixel_decode_raw(
    unsigned char       /* in */  *p,           /* sixel bytes */
    int                 /* in */  len,          /* size of sixel bytes */
    unsigned char       /* out */ **pixels,     /* decoded pixels */
    int                 /* out */ *pwidth,      /* image width */
    int                 /* out */ *pheight,     /* image height */
    unsigned char       /* out */ **palette,    /* ARGB palette */
    int                 /* out */ *ncolors,     /* palette size (<= 256) */
    sixel_allocator_t   /* in */  *allocator);  /* allocator object or null */

SIXELAPI __attribute__((deprecated)) SIXELSTATUS
sixel_decode(
    unsigned char            /* in */  *sixels,    /* sixel bytes */
    int                      /* in */  size,       /* size of sixel bytes */
    unsigned char            /* out */ **pixels,   /* decoded pixels */
    int                      /* out */ *pwidth,    /* image width */
    int                      /* out */ *pheight,   /* image height */
    unsigned char            /* out */ **palette,  /* RGBA palette */
    int                      /* out */ *ncolors,   /* palette size (<= 256) */
    sixel_allocator_function /* in */  fn_malloc); /* malloc function */

#ifdef __cplusplus
}
#endif

/* helper API */

#ifdef __cplusplus
extern "C" {
#endif

SIXELAPI void
sixel_helper_set_additional_message(
    const char      /* in */  *message         /* error message */
);

SIXELAPI char const *
sixel_helper_get_additional_message(void);

/* convert error status code int formatted string */
SIXELAPI char const *
sixel_helper_format_error(
    SIXELSTATUS     /* in */  status           /* status code */
);

/* compute pixel depth from pixelformat */
SIXELAPI int
sixel_helper_compute_depth(
    int /* in */ pixelformat /* one of enum pixelFormat */
);

/* convert pixelFormat into PIXELFORMAT_RGB888 */
SIXELAPI SIXELSTATUS
sixel_helper_normalize_pixelformat(
    unsigned char       /* out */ *dst,             /* destination buffer */
    int                 /* out */ *dst_pixelformat, /* converted pixelformat */
    unsigned char const /* in */  *src,             /* source pixels */
    int                 /* in */  src_pixelformat,  /* format of source image */
    int                 /* in */  width,            /* width of source image */
    int                 /* in */  height            /* height of source image */
);

/* scale image to specified size */
SIXELAPI SIXELSTATUS
sixel_helper_scale_image(
    unsigned char       /* out */ *dst,                  /* destination buffer */
    unsigned char const /* in */  *src,                  /* source image data */
    int                 /* in */  srcw,                  /* source image width */
    int                 /* in */  srch,                  /* source image height */
    int                 /* in */  pixelformat,           /* one of enum pixelFormat */
    int                 /* in */  dstw,                  /* destination image width */
    int                 /* in */  dsth,                  /* destination image height */
    int                 /* in */  method_for_resampling, /* one of methodForResampling */
    sixel_allocator_t   /* in */  *allocator             /* allocator object */
);

#ifdef __cplusplus
}
#endif


/* image loader/writer API */

#if SIXEL_USE_DEPRECATED_SYMBOLS
enum imageFormat {
    FORMAT_GIF   =  0, /* read only */
    FORMAT_PNG   =  1, /* read/write */
    FORMAT_BMP   =  2, /* read only */
    FORMAT_JPG   =  3, /* read only */
    FORMAT_TGA   =  4, /* read only */
    FORMAT_WBMP  =  5, /* read only with --with-gd configure option */
    FORMAT_TIFF  =  6, /* read only */
    FORMAT_SIXEL =  7, /* read only */
    FORMAT_PNM   =  8, /* read only */
    FORMAT_GD2   =  9, /* read only with --with-gd configure option */
    FORMAT_PSD   = 10, /* read only */
    FORMAT_HDR   = 11  /* read only */
};

/* loop mode */
enum loopControl {
    LOOP_AUTO    = 0,  /* honer the setting of GIF header */
    LOOP_FORCE   = 1,  /* always enable loop */
    LOOP_DISABLE = 2   /* always disable loop */
};
#endif

/* handle type of dither context object */
struct sixel_frame;
typedef struct sixel_frame sixel_frame_t;

#ifdef __cplusplus
extern "C" {
#endif

/* constructor of frame object */
SIXELAPI SIXELSTATUS
sixel_frame_new(
    sixel_frame_t       /* out */ **ppframe,    /* frame object to be created */
    sixel_allocator_t   /* in */  *allocator);  /* allocator, null if you use
                                                   default allocator */
/* deprecated version of sixel_frame_new() */
SIXELAPI __attribute__((deprecated)) sixel_frame_t *
sixel_frame_create(void);

/* increase reference count of frame object (thread-unsafe) */
SIXELAPI void
sixel_frame_ref(sixel_frame_t /* in */ *frame);

/* decrease reference count of frame object (thread-unsafe) */
SIXELAPI void
sixel_frame_unref(sixel_frame_t /* in */ *frame);

/* initialize frame object with a pixel buffer */
SIXELAPI SIXELSTATUS
sixel_frame_init(
    sixel_frame_t   /* in */ *frame,        /* frame object to be initialize */
    unsigned char   /* in */ *pixels,       /* pixel buffer */
    int             /* in */ width,         /* pixel width of buffer */
    int             /* in */ height,        /* pixel height of buffer */
    int             /* in */ pixelformat,   /* pixelformat of buffer */
    unsigned char   /* in */ *palette,      /* palette for buffer or NULL */
    int             /* in */ ncolors        /* number of palette colors or (-1) */
);

/* get pixels */
SIXELAPI unsigned char *
sixel_frame_get_pixels(sixel_frame_t /* in */ *frame);  /* frame object */

/* get palette */
SIXELAPI unsigned char *
sixel_frame_get_palette(sixel_frame_t /* in */ *frame);  /* frame object */

/* get width */
SIXELAPI int
sixel_frame_get_width(sixel_frame_t /* in */ *frame);  /* frame object */

/* get height */
SIXELAPI int
sixel_frame_get_height(sixel_frame_t /* in */ *frame);  /* frame object */

/* get ncolors */
SIXELAPI int
sixel_frame_get_ncolors(sixel_frame_t /* in */ *frame);  /* frame object */

/* get pixelformat */
SIXELAPI int
sixel_frame_get_pixelformat(sixel_frame_t /* in */ *frame);  /* frame object */

/* get transparent */
SIXELAPI int
sixel_frame_get_transparent(sixel_frame_t /* in */ *frame);  /* frame object */

/* get transparent */
SIXELAPI int
sixel_frame_get_multiframe(sixel_frame_t /* in */ *frame);  /* frame object */

/* get delay */
SIXELAPI int
sixel_frame_get_delay(sixel_frame_t /* in */ *frame);  /* frame object */

/* get frame no */
SIXELAPI int
sixel_frame_get_frame_no(sixel_frame_t /* in */ *frame);  /* frame object */

/* get loop no */
SIXELAPI int
sixel_frame_get_loop_no(sixel_frame_t /* in */ *frame);  /* frame object */

/* strip alpha from RGBA/ARGB formatted pixbuf */
SIXELAPI int
sixel_frame_strip_alpha(
    sixel_frame_t  /* in */ *frame,
    unsigned char  /* in */ *bgcolor);

/* resize a frame to given size with specified resampling filter */
SIXELAPI SIXELSTATUS
sixel_frame_resize(
    sixel_frame_t  /* in */ *frame,
    int            /* in */ width,
    int            /* in */ height,
    int            /* in */ method_for_resampling);

/* clip frame */
SIXELAPI SIXELSTATUS
sixel_frame_clip(
    sixel_frame_t  /* in */ *frame,
    int            /* in */ x,
    int            /* in */ y,
    int            /* in */ width,
    int            /* in */ height);

typedef SIXELSTATUS (* sixel_load_image_function)(
    sixel_frame_t /* in */     *frame,
    void          /* in/out */ *context);

SIXELAPI SIXELSTATUS
sixel_helper_load_image_file(
    char const                /* in */     *filename,     /* source file name */
    int                       /* in */     fstatic,       /* whether to extract static image */
    int                       /* in */     fuse_palette,  /* whether to use paletted image */
    int                       /* in */     reqcolors,     /* requested number of colors */
    unsigned char             /* in */     *bgcolor,      /* background color */
    int                       /* in */     loop_control,  /* one of enum loopControl */
    sixel_load_image_function /* in */     fn_load,       /* callback */
    int                       /* in */     finsecure,     /* true if do not verify SSL */
    int const                 /* in */     *cancel_flag,  /* cancel flag */
    void                      /* in/out */ *context,      /* private data for callback */
    sixel_allocator_t         /* in */     *allocator);   /* allocator object */

/* write image to file */
SIXELAPI SIXELSTATUS
sixel_helper_write_image_file(
    unsigned char       /* in */ *data,        /* source pixel data */
    int                 /* in */ width,        /* source data width */
    int                 /* in */ height,       /* source data height */
    unsigned char       /* in */ *palette,     /* palette of source data */
    int                 /* in */ pixelformat,  /* source pixelFormat */
    char const          /* in */ *filename,    /* destination filename */
    int                 /* in */ imageformat,  /* one of enum imageformat */
    sixel_allocator_t   /* in */ *allocator);  /* allocator object */

#ifdef __cplusplus
}
#endif


/* easy encoder API */

/* handle type of dither context object */
struct sixel_encoder;
typedef struct sixel_encoder sixel_encoder_t;

#ifdef __cplusplus
extern "C" {
#endif

/* create encoder object */
SIXELAPI SIXELSTATUS
sixel_encoder_new(
    sixel_encoder_t     /* out */ **ppencoder, /* encoder object to be created */
    sixel_allocator_t   /* in */  *allocator); /* allocator, null if you use
                                                  default allocator */

/* deprecated version of sixel_decoder_new() */
SIXELAPI __attribute__((deprecated)) sixel_encoder_t *
sixel_encoder_create(void);

/* increase reference count of encoder object (thread-unsafe) */
SIXELAPI void
sixel_encoder_ref(sixel_encoder_t /* in */ *encoder);

/* decrease reference count of encoder object (thread-unsafe) */
SIXELAPI void
sixel_encoder_unref(sixel_encoder_t /* in */ *encoder);

/* set cancel state flag to encoder object */
SIXELAPI SIXELSTATUS
sixel_encoder_set_cancel_flag(
    sixel_encoder_t /* in */ *encoder,
    int             /* in */ *cancel_flag);

/* set an option flag to encoder object */
SIXELAPI SIXELSTATUS
sixel_encoder_setopt(
    sixel_encoder_t /* in */ *encoder,
    int             /* in */ arg,
    char const      /* in */ *optarg);

/* load source data from specified file and encode it to SIXEL format */
SIXELAPI SIXELSTATUS
sixel_encoder_encode(
    sixel_encoder_t /* in */ *encoder,
    char const      /* in */ *filename);

/* encode specified pixel data to SIXEL format
 * output to encoder->outfd */
SIXELAPI SIXELSTATUS
sixel_encoder_encode_bytes(
    sixel_encoder_t     /* in */    *encoder,
    unsigned char       /* in */    *bytes,
    int                 /* in */    width,
    int                 /* in */    height,
    int                 /* in */    pixelformat,
    unsigned char       /* in */    *palette,
    int                 /* in */    ncolors);

#ifdef __cplusplus
}
#endif


/* easy encoder API */

/* handle type of dither context object */
struct sixel_decoder;
typedef struct sixel_decoder sixel_decoder_t;

#ifdef __cplusplus
extern "C" {
#endif

/* create decoder object */
SIXELAPI SIXELSTATUS
sixel_decoder_new(
    sixel_decoder_t    /* out */ **ppdecoder,  /* decoder object to be created */
    sixel_allocator_t  /* in */  *allocator);  /* allocator, null if you use
                                                  default allocator */

/* deprecated version of sixel_decoder_new() */
SIXELAPI __attribute__((deprecated)) sixel_decoder_t *
sixel_decoder_create(void);

/* increase reference count of decoder object (thread-unsafe) */
SIXELAPI void
sixel_decoder_ref(sixel_decoder_t *decoder);

/* decrease reference count of decoder object (thread-unsafe) */
SIXELAPI void
sixel_decoder_unref(sixel_decoder_t *decoder);

/* set an option flag to decoder object */
SIXELAPI SIXELSTATUS
sixel_decoder_setopt(
    sixel_decoder_t /* in */ *decoder,  /* decoder object */
    int             /* in */ arg,       /* one of SIXEL_OPTFLAG_*** */
    char const      /* in */ *optarg);  /* null or an argument of optflag */

/* load source data from stdin or the file specified with
   SIXEL_OPTFLAG_INPUT flag, and decode it */
SIXELAPI SIXELSTATUS
sixel_decoder_decode(
    sixel_decoder_t /* in */ *decoder);

#ifdef __cplusplus
}
#endif

#endif  /* LIBSIXEL_SIXEL_H */

/* emacs Local Variables:      */
/* emacs mode: c               */
/* emacs tab-width: 4          */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4     */
/* emacs End:                  */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
