JPEG解码器

JPEG编码原理
在这里插入图片描述
JPEG文件格式
在这里插入图片描述
1)SOI:FFD8,图像开始标志
2)APP0:FFE0,应用程序保留标记
3)DQT:FFDB, 量化表
4) SOF0:FFC0, 帧图像开始
5)DHT Haffman表
6)SOS:FFDA, 扫描开始

三个重要结构体
huffman表结构体

struct huffman_table
{
   
  /* Fast look up table, using HUFFMAN_HASH_NBITS bits we can have directly the symbol,
   * if the symbol is <0, then we need to look into the tree table */
  short int lookup[HUFFMAN_HASH_SIZE];
  /* code size: give the number of bits of a symbol is encoded */
  unsigned char code_size[HUFFMAN_HASH_SIZE];
  /* some place to store value that is not encoded in the lookup table 
   * FIXME: Calculate if 256 value is enough to store all values
   */
  uint16_t slowtable[16-HUFFMAN_HASH_NBITS][256];
};

component结构体:每个8*8的块都对应一个component结构体,在程序中为使用完后将该结构体给下一个块继续使用)

struct component 
{
   
  unsigned int Hfactor;
  unsigned int Vfactor;
  float *Q_table;  /* Pointer to the quantisation table to use */
  struct huffman_table *AC_table;
  struct huffman_table *DC_table;
  short int previous_DC; /* Previous DC coefficient */
  short int DCT[64];  /* DCT coef */
#if SANITY_CHECK
  unsigned int cid;
#endif
};

jpec_private结构体:关于jpeg数据流的结构体,包含图片长宽、码表等信息

struct jdec_private
{
   
  /* Public variables */
  uint8_t *components[COMPONENTS];
  unsigned int width, height; /* Size of the image */
  unsigned int flags;
  /* Private variables */
  const unsigned char *stream_begin, *stream_end;
  unsigned int stream_length;
  const unsigned char *stream; /* Pointer to the current stream */
  unsigned int reservoir, nbits_in_reservoir;
  struct component component_infos[COMPONENTS];
  float Q_tables[COMPONENTS][64];  /* quantization tables */
  struct huffman_table HTDC[HUFFMAN_TABLES]; /* DC huffman tables   */
  struct huffman_table HTAC[HUFFMAN_TABLES]; /* AC huffman tables   */
  int default_huffman_table_initialized;
  int restart_interval;
  int restarts_to_go;    /* MCUs left in this restart interval */
  int last_rst_marker_seen;   /* Rst marker is incremented each time */
  /* Temp space used after the IDCT to store each components */
  uint8_t Y[64*4], Cr[64], Cb[64];
  jmp_buf jump_state;
  /* Internal Pointer use for colorspace conversion, do not modify it !!! */
  uint8_t *plane[COMPONENTS]
};

图片转换函数,包含从JPEG文件头中提取信息并选择性的转换为各种格式

int convert_one_image(const char *infilename, const char *outfilename, int output_format)
{
   
  FILE *fp;
  unsigned int length_of_file;
  unsigned int width, height;
  unsigned char *buf;
  struct jdec_private *jdec;
  unsigned char *components[3];
  /* Load the Jpeg into memory */
  fp = fopen(infilename, "rb");
  if (fp == NULL)
    exitmessage("Cannot open filename\n");
  length_of_file = filesize(fp);
  buf = (unsigned char *)malloc(length_of_file + 4);
  if (buf == NULL)
    exitmessage("Not enough memory for loading file\n");
  fread(buf, length_of_file, 1, fp);
  fclose(fp);
  /* Decompress it */
  jdec = tinyjpeg_init();
  if (jdec == NULL)
    exitmessage("Not enough memory to alloc the structure need for decompressing\n");
  if (tinyjpeg_parse_header(jdec, buf, length_of_file)<0)
    exitmessage(tinyjpeg_get_errorstring(jdec));
  /* Get the size of the image */
  tinyjpeg_get_size(jdec, &width, &height);
  snprintf(error_string, sizeof(error_string),"Decoding JPEG image...\n");
  if (tinyjpeg_decode(jdec, output_format) < 0)
    exitmessage(tinyjpeg_get_errorstring(jdec));
  /* 
   * Get address for each plane (not only max 3 planes is supported), and
   * depending of the output mode, only some components will be filled 
   * RGB: 1 plane, YUV420P: 3 planes, GREY: 1 plane
   */
  tinyjpeg_get_components(jdec, components);
  /* Save it */
  switch (output_format)
   {
   
    case TINYJPEG_FMT_RGB24:
    case TINYJPEG_FMT_BGR24:
      write_tga(outfilename, output_format, width, height, components);
      break;
    case TINYJPEG_FMT_YUV420P:
      write_yuv(outfilename, width, height, components);
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值