//------------------------------------------------------------------------------
// jpegdecoder.h
// Small JPEG Decoder Library
// Last updated: Nov. 16, 2000 v0.93
// Copyright (C) 1994-2000 Rich Geldreich
// richgel@voicenet.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------
#ifndef JPEG_DECODER_H
#define JPEG_DECODER_H
//------------------------------------------------------------------------------
#include "../types.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//------------------------------------------------------------------------------
// May need to be adjusted if support for other colorspaces/sampling factors is added
#define JPGD_MAXBLOCKSPERMCU 10
//------------------------------------------------------------------------------
#define JPGD_MAXHUFFTABLES   8
#define JPGD_MAXQUANTTABLES  4
#define JPGD_MAXCOMPONENTS   4
#define JPGD_MAXCOMPSINSCAN  4
//------------------------------------------------------------------------------
// Increase this if you increase the max width!
#define JPGD_MAXBLOCKSPERROW 6144
//------------------------------------------------------------------------------
// Max. allocated blocks
#define JPGD_MAXBLOCKS    100
//------------------------------------------------------------------------------
#define JPGD_MAX_HEIGHT 8192
#define JPGD_MAX_WIDTH  8192
//------------------------------------------------------------------------------
/* JPEG specific errors */
#define JPGD_BAD_DHT_COUNTS              -200
#define JPGD_BAD_DHT_INDEX               -201
#define JPGD_BAD_DHT_MARKER              -202
#define JPGD_BAD_DQT_MARKER              -203
#define JPGD_BAD_DQT_TABLE               -204
#define JPGD_BAD_PRECISION               -205
#define JPGD_BAD_HEIGHT                  -206
#define JPGD_BAD_WIDTH                   -207
#define JPGD_TOO_MANY_COMPONENTS         -208
#define JPGD_BAD_SOF_LENGTH              -209
#define JPGD_BAD_VARIABLE_MARKER         -210
#define JPGD_BAD_DRI_LENGTH              -211
#define JPGD_BAD_SOS_LENGTH              -212
#define JPGD_BAD_SOS_COMP_ID             -213
#define JPGD_W_EXTRA_BYTES_BEFORE_MARKER -214
#define JPGD_NO_ARITHMITIC_SUPPORT       -215
#define JPGD_UNEXPECTED_MARKER           -216
#define JPGD_NOT_JPEG                    -217
#define JPGD_UNSUPPORTED_MARKER          -218
#define JPGD_BAD_DQT_LENGTH              -219
#define JPGD_TOO_MANY_BLOCKS             -221
#define JPGD_UNDEFINED_QUANT_TABLE       -222
#define JPGD_UNDEFINED_HUFF_TABLE        -223
#define JPGD_NOT_SINGLE_SCAN             -224
#define JPGD_UNSUPPORTED_COLORSPACE      -225
#define JPGD_UNSUPPORTED_SAMP_FACTORS    -226
#define JPGD_DECODE_ERROR                -227
#define JPGD_BAD_RESTART_MARKER          -228
#define JPGD_ASSERTION_ERROR             -229
#define JPGD_BAD_SOS_SPECTRAL            -230
#define JPGD_BAD_SOS_SUCCESSIVE          -231
#define JPGD_STREAM_READ                 -232
#define JPGD_NOTENOUGHMEM                -233
//------------------------------------------------------------------------------
#define JPGD_GRAYSCALE 0
#define JPGD_YH1V1     1
#define JPGD_YH2V1     2
#define JPGD_YH1V2     3
#define JPGD_YH2V2     4
//------------------------------------------------------------------------------
const int JPGD_FAILED = -1;
const int JPGD_DONE = 1;
const int JPGD_OKAY = 0;
//------------------------------------------------------------------------------
typedef enum
{
  M_SOF0  = 0xC0,
  M_SOF1  = 0xC1,
  M_SOF2  = 0xC2,
  M_SOF3  = 0xC3,

  M_SOF5  = 0xC5,
  M_SOF6  = 0xC6,
  M_SOF7  = 0xC7,

  M_JPG   = 0xC8,
  M_SOF9  = 0xC9,
  M_SOF10 = 0xCA,
  M_SOF11 = 0xCB,

  M_SOF13 = 0xCD,
  M_SOF14 = 0xCE,
  M_SOF15 = 0xCF,

  M_DHT   = 0xC4,

  M_DAC   = 0xCC,

  M_RST0  = 0xD0,
  M_RST1  = 0xD1,
  M_RST2  = 0xD2,
  M_RST3  = 0xD3,
  M_RST4  = 0xD4,
  M_RST5  = 0xD5,
  M_RST6  = 0xD6,
  M_RST7  = 0xD7,

  M_SOI   = 0xD8,
  M_EOI   = 0xD9,
  M_SOS   = 0xDA,
  M_DQT   = 0xDB,
  M_DNL   = 0xDC,
  M_DRI   = 0xDD,
  M_DHP   = 0xDE,
  M_EXP   = 0xDF,

  M_APP0  = 0xE0,
  M_APP15 = 0xEF,

  M_JPG0  = 0xF0,
  M_JPG13 = 0xFD,
  M_COM   = 0xFE,

  M_TEM   = 0x01,

  M_ERROR = 0x100
} JPEG_MARKER;
//------------------------------------------------------------------------------
#define RST0 0xD0
//------------------------------------------------------------------------------
typedef struct huff_tables_tag
{
  uint32  look_up[256];
  uint8 code_size[256];
  // FIXME: Is 512 tree entries really enough to handle _all_ possible
  // code sets? I think so but not 100% positive.
  uint32  tree[512];
} huff_tables_t, *Phuff_tables_t;
//------------------------------------------------------------------------------
typedef struct coeff_buf_tag
{
  uint8 *Pdata;

  int block_num_x, block_num_y;
  int block_len_x, block_len_y;

  int block_size;

} coeff_buf_t, *Pcoeff_buf_t;
//------------------------------------------------------------------------------
class jpeg_decoder;
typedef void (*Pdecode_block_func)(jpeg_decoder *, int, int, int);
//------------------------------------------------------------------------------

#define QUANT_TYPE int16
#define BLOCK_TYPE int16

class jpeg_decoder
{
private:

  void free_all_blocks(void);

  void terminate(int status);

  void *alloc(int n);

  void word_clear(void *p, uint16 c, uint32 n);

  void init(void);

  void create_look_ups(void);

  void fix_in_buffer(void);

  void transform_row(void);

  Pcoeff_buf_t coeff_buf_open(
    int block_num_x, int block_num_y,
    int block_len_x, int block_len_y);

  void coeff_buf_read(
    Pcoeff_buf_t cb,
    int block_x, int block_y,
    BLOCK_TYPE *buffer);

  void coeff_buf_write(
    Pcoeff_buf_t cb,
    int block_x, int block_y,
    BLOCK_TYPE *buffer);

  BLOCK_TYPE *coeff_buf_getp(
    Pcoeff_buf_t cb,
    int block_x, int block_y);

  void load_next_row(void);

  void decode_next_row(void);

  void make_huff_table(
    int index,
    Phuff_tables_t hs);

  void check_quant_tables(void);

  void check_huff_tables(void);

  void calc_mcu_block_order(void);

  int init_scan(void);

  void init_frame(void);

  void process_restart(void);

  void decode_scan(
    Pdecode_block_func decode_block_func);

  void init_sequential(void);

  void decode_init(void);

  void decode_start(void);

  void H2V2Convert(void);
  void H2V1Convert(void);
  void H1V2Convert(void);
  void H1V1Convert(void);
  void GrayConvert(void);

  void find_eoi(void);
//------------------
  inline uint32 rol(uint32 i, uint8 j);
  inline uint32 get_char(void);
  inline uint32 get_char(bool *Ppadding_flag);
  inline void stuff_char(uint8 q);
  inline uint8 get_octet(void);
  inline uint32 get_bits_1(int num_bits);
  inline uint32 get_bits_2(int numbits);
  inline int huff_decode(Phuff_tables_t Ph);
  inline uint8 clamp(int i);

//------------------
  int   image_x_size;
  int   image_y_size;

  uint8 *huff_num[JPGD_MAXHUFFTABLES];  /* pointer to number of Huffman codes per bit size */
  uint8 *huff_val[JPGD_MAXHUFFTABLES];  /* pointer to Huffman codes per bit size */

  QUANT_TYPE *quant[JPGD_MAXQUANTTABLES];    /* pointer to quantization tables */

  int   scan_type;                      /* Grey, Yh1v1, Yh1v2, Yh2v1, Yh2v2,
                                           CMYK111, CMYK4114 */

  int   comps_in_frame;                 /* # of components in frame */
  int   comp_h_samp[JPGD_MAXCOMPONENTS];     /* component's horizontal sampling factor */
  int   comp_v_samp[JPGD_MAXCOMPONENTS];     /* component's vertical sampling factor */
  int   comp_quant[JPGD_MAXCOMPONENTS];      /* component's quantization table selector */
  int   comp_ident[JPGD_MAXCOMPONENTS];      /* component's ID */

  int   comp_h_blocks[JPGD_MAXCOMPONENTS];
  int   comp_v_blocks[JPGD_MAXCOMPONENTS];

  int   comps_in_scan;                  /* # of components in scan */
  int   comp_list[JPGD_MAXCOMPSINSCAN];      /* components in this scan */
  int   comp_dc_tab[JPGD_MAXCOMPONENTS];     /* component's DC Huffman coding table selector */
  int   comp_ac_tab[JPGD_MAXCOMPONENTS];     /* component's AC Huffman coding table selector */

  int   spectral_start;                 /* spectral selection start */
  int   spectral_end;                   /* spectral selection end   */
  int   successive_low;                 /* successive approximation low */
  int   successive_high;                /* successive approximation high */

  int   max_mcu_x_size;                 /* MCU's max. X size in pixels */
  int   max_mcu_y_size;                 /* MCU's max. Y size in pixels */

  int   blocks_per_mcu;
  int   max_blocks_per_row;
  int   mcus_per_row, mcus_per_col;

  int   mcu_org[JPGD_MAXBLOCKSPERMCU];

  int   total_lines_left;               /* total # lines left in image */
  int   mcu_lines_left;                 /* total # lines left in this MCU */

  int   real_dest_bytes_per_scan_line;
  int   dest_bytes_per_scan_line;        /* rounded up */
  int   dest_bytes_per_pixel;            /* currently, 4 (RGB) or 1 (Y) */

  void  *blocks[JPGD_MAXBLOCKS];         /* list of all dynamically allocated blocks */

  Phuff_tables_t h[JPGD_MAXHUFFTABLES];

  Pcoeff_buf_t dc_coeffs[JPGD_MAXCOMPONENTS];
  Pcoeff_buf_t ac_coeffs[JPGD_MAXCOMPONENTS];

  int eob_run;

  int block_y_mcu[JPGD_MAXCOMPONENTS];

  uint8 *Pin_buf_ofs;
  int in_buf_left;
  int tem_flag;
  bool eof_flag;

  uint8 *in_buf;

  int   bits_left;
  union
  {
    uint32 bit_buf;
    uint32 bit_buf_64[2];
  };
  
  uint32  saved_mm1[2];

  int   restart_interval;
  int   restarts_left;
  int   next_restart_num;

  int   max_mcus_per_row;
  int   max_blocks_per_mcu;

  int   max_mcus_per_col;

  uint32 *component[JPGD_MAXBLOCKSPERMCU];   /* points into the lastdcvals table */
  uint32  last_dc_val[JPGD_MAXCOMPONENTS];

  Phuff_tables_t dc_huff_seg[JPGD_MAXBLOCKSPERMCU];
  Phuff_tables_t ac_huff_seg[JPGD_MAXBLOCKSPERMCU];

  BLOCK_TYPE *block_seg[JPGD_MAXBLOCKSPERROW];
  int   block_max_zag_set[JPGD_MAXBLOCKSPERROW];

  uint8 *Psample_buf;
  //int   block_num[JPGD_MAXBLOCKSPERROW];

  int   crr[256];
  int   cbb[256];
  int   padd;
  long  crg[256];
  long  cbg[256];

  uint8 *scan_line_0;
  uint8 *scan_line_1;

  BLOCK_TYPE temp_block[64];

  int error_code;
  bool ready_flag;

  int total_bytes_read;

public:

  jpeg_decoder(void);

  int begin(void);

  int decode(void * *Pscan_line_ofs, uint32 *Pscan_line_len);

  ~jpeg_decoder();

  int get_error_code(void)
  {
    return (error_code);
  }

  void set_in_buffer(uint8 *data, uint32 len);
  void set_huffman(int index, const uint8 *data);
  void set_quant(int n, uint8 *data);
  void set_sof(int width, int height, int Y_h_samp, int Y_v_samp, int Y_quant, int Cb_h_samp,
        int Cb_v_samp, int Cb_quant, int Cr_h_samp, int Cr_v_samp, int Cr_quant);
  void set_sos(int Y_dc_tab, int Y_ac_tab, int Cb_dc_tab, int Cb_ac_tab, int Cr_dc_tab, int Cr_ac_tab);

};
//------------------------------------------------------------------------------
#include "jpegdecoder.inl"

//------------------------------------------------------------------------------
typedef jpeg_decoder *Pjpeg_decoder;

//------------------------------------------------------------------------------
// idct.cpp
void idct(BLOCK_TYPE *data, uint8 *Pdst_ptr);

#endif

