///////////////////////////////////////////////////////////////////////////////
//
//       JPEG デコーダ 構造体

#ifndef JDECODER_H
#define JDECODER_H

#include "istrm_c.h"

#ifdef __cplusplus
extern "C" {
#endif

//-----------------------------------------------------------------------------
typedef struct _hufmanTable {
  unsigned int code;
  unsigned int bits;
} HuffmanTable;

typedef struct _huffmanTree {
  struct _huffmanTree *next_tree[2];
  unsigned int value[2];
} HuffmanTree;


// JPEG デコーダの構造体 -----------------------------------------------------
typedef struct _JPEGDecoder {

  // APP0
  char app0_identifier[5];  // "JFIF\0" 固定のはず

  // app0_identifier == "JFIF\0" の場合
    int  major_revision;
    int  minor_revision;
    int  density_unit;
    int  horiz_density;
    int  verti_density;
    int  thumb_width;
    int  thumb_height;
    // サムネイル画像は略

  // SOF0
  int depth;
  int height;
  int width;
  int component_count;   // 1 or 3
  int component_id[3];
  int sampling_factor[3];
  int horizontal_sampling_factor[3];
  int vertical_sampling_factor[3];
  int qt_selector[3];

  int inverse_horizontal_sampling_factor[3];  // Y/Cb/Cr は，実際の何分の一になっているか
  int inverse_vertical_sampling_factor[3];
  int horizontal_block_count_a_MCU[3]; // YCbCr それぞれの MCU 内の横方向のブロックの数
  int vertical_block_count_a_MCU[3];   // YCbCr それぞれの MCU 内の縦方向のブロックの数
  int block_count_a_MCU[3];            // YCbCr それぞれの MCU 内のブロックの数
  int total_block_count_a_MCU;         // YCrCb の合計 = MCU の中に 8x8 ブロックはいくつあるか
  int MCU_width;  // MCU の実質の幅
  int MCU_height; // MCU の実質の高さ
  int actual_horizontal_block_count_a_MCU[3];
  int actual_vertical_block_count_a_MCU[3];
  int actual_block_count_a_MCU[3];
  int actual_total_block_count_a_MCU;
  int actual_MCU_width;
  int actual_MCU_height;

  // DQT
  int quant_tables[2][64];

  // DHT
  HuffmanTable huffman_tables[2][2][256];
  HuffmanTree huffman_trees[2][2];

  // SOS
  int huffman_table_for_dc[3]; // Y, Cr, Cb 別
  int huffman_table_for_ac[3];

  short MCU[3][256];
  int dc_pred[3];
  int mcu_skip_next;

  void (*output_callback)(struct _JPEGDecoder *, void *,
                     unsigned char, unsigned char, unsigned char);
  void *extra_data;

} JPEGDecoder;


typedef void (*JDECOutputCallback)(JPEGDecoder *, void *,
                     unsigned char, unsigned char, unsigned char);


#define JDEC_NOERROR 0
#define JDEC_IOEXCEPTION 1
#define JDEC_NOTSUPPORTED 2

#define JM_JUST_A_0xFF               0xFF00
#define JM_START_OF_FRAME_MIN        0xFFC0
#define JM_START_OF_FRAME_0          0xFFC0
#define JM_START_OF_FRAME_MAX        0xFFCF
#define JM_DEFINE_HUFFMAN_TABLE      0xFFC4
#define JM_START_OF_IMAGE            0xFFD8
#define JM_END_OF_IMAGE              0xFFD9
#define JM_START_OF_SCAN             0xFFDA
#define JM_DEFINE_QUANTIZATION_TABLE 0xFFDB
#define JM_DEFINE_RESTART_INTERVAL   0xFFDD
#define JM_APPLICATION_MIN           0xFFE0
#define JM_APPLICATION_0             0xFFE0
#define JM_APPLICATION_MAX           0xFFEF
#define JM_COMMENT                   0xFFFE

void JD_initialize( JPEGDecoder *jd, JDECOutputCallback joc, void *extra_data );
unsigned int JD_decode( JPEGDecoder *jd, InputStream *is );
void JD_finalize( JPEGDecoder *jd );


#ifdef __cplusplus
}
#endif


#endif // JDECODER_H


