蘇泊爾耗的JPEG解碼器[二]

哈夫曼解碼和位流操作部分。

JPEG的哈夫曼編碼是優化過的,對於每一個N位長的編碼只要它小於MAX[N]就是一個結束編碼。MAX[N]可根據DHT語法中給出的碼錶算出。

取位的方法很普通。如果用匯編優化的話,可以考慮用以前跟蹤到的某H-GAME中圖片解碼程序的實現方法。在這裏就不多講了。

要注意的是RSTn可能會穿插在這裏面。

jpeghuff.h

********************************************** 低調滴分隔線(1) ***************************************

/**************************************************************************************************

  superarhow's JPEG decoder

  by superarhow([email protected]).  All rights reserved.

 **************************************************************************************************/

#pragma once

#include "JpegDec2.h"

/* 從流中讀下一個哈夫曼編碼並解碼出其對應的字節 */
BYTE jpeg_dec_next_huff_code(p_jpeg_dec_rec p_rec, p_jpeg_huff_table p_table);

/* 從流中讀取n_bits位 */
WORD jpeg_get_next_bits(p_jpeg_dec_rec p_rec, BYTE n_bits); 

********************************************** 低調滴分隔線(2) ***************************************

jpeghuff.c

********************************************** 低調滴分隔線(3) ***************************************

/**************************************************************************************************

  superarhow's JPEG decoder

  by superarhow([email protected]).  All rights reserved.

 **************************************************************************************************/

#include "jpegdec2.h"

/*
 *  從流中讀下一個哈夫曼編碼並解碼出其對應的字節
 *  返回解碼出的字節
 */
BYTE jpeg_dec_next_huff_code(p_jpeg_dec_rec p_rec, p_jpeg_huff_table p_table)
{
 WORD *p_min_code, *p_max_code;
 BYTE *p_codedata, *p_startindexes;
 BYTE *p_data;
 BYTE left_bits, n_left_bit_count, mask;
 WORD code;

 p_min_code  = p_table->huff_min_codes;
 p_max_code  = p_table->huff_max_codes;
 p_codedata  = p_table->start_code_indexes;
 p_startindexes = p_table->start_code_indexes;

 p_data = p_rec->p_data;
 left_bits = p_rec->left_bits;
 n_left_bit_count = p_rec->n_left_bit_count;
 mask = 1 << (n_left_bit_count - 1);
 code = 0;
 for ( ;; ) {
  if ( n_left_bit_count == 0 ) {
   /* fetch the next bits from the stream */
   n_left_bit_count = 8;
   mask = 0x80;
   left_bits = *p_data++;
   while ( left_bits == 0xFF ) {
    if ( *p_data == 0 ) {
     p_data++;
     break;
    } else if ( *p_data >= 0xD0 && *p_data <= 0xD7 ) {
     /* RSTn */
     n_left_bit_count = 0;
     jpeg_reset(p_rec);
     ++p_data;
     break;
    } else {
     left_bits = *p_data++;
     break;
    }
   }
   if ( n_left_bit_count == 0 ) continue; /* still not get the next byte :( */
  }
  code = code << 1;
  if ( left_bits & mask ) code++;
  n_left_bit_count--;
  left_bits &= (~mask);
  if ( code <= *p_max_code && (*p_max_code >= 0x8000 || 0x8000 >= *p_min_code) ) {
   /* Done! */
   break;
  }
  p_max_code++;
  p_min_code++;
  p_codedata++;
  p_startindexes++;
  mask >>= 1;
 }
 p_rec->n_left_bit_count = n_left_bit_count;
 p_rec->left_bits = left_bits;
 p_rec->p_data = p_data;
 code -= *p_min_code;
 if (code + *p_startindexes >= p_table->n_code_count) _asm int 3;
 return p_table->codes[code + *p_startindexes];
}

/*
 *  從流中讀取n_bits位
 *  返回讀取的位碼
 */
WORD jpeg_get_next_bits(p_jpeg_dec_rec p_rec, BYTE n_bits)
{
 WORD result;
 BYTE *p_data;
 BYTE left_bits, n_left_bit_count;

 result = 0;
 p_data = p_rec->p_data;
 left_bits = p_rec->left_bits;
 n_left_bit_count = p_rec->n_left_bit_count;

 while ( n_bits > 0 ) {

  if ( n_left_bit_count == 0 ) {
   /* fetch the next bits from the stream */
   n_left_bit_count = 8;
   left_bits = *p_data++;
   while ( left_bits == 0xFF ) {
    if ( *p_data == 0 ) {
     ++p_data;
     break;
    } else if ( *p_data >= 0xD0 && *p_data <= 0xD7 ) {
     /* RSTn */
     n_left_bit_count = 0;
     jpeg_reset(p_rec);
     ++p_data;
     break;
    } else {
     left_bits = *p_data++;
     break;
    }
   }
   if ( n_left_bit_count == 0 ) continue; /* still not get the next byte :( */
  }

  if ( n_left_bit_count >= n_bits ) {
   /* fetch n_bits bits */
   n_left_bit_count -= n_bits;
   result <<= n_bits;
   result |= ( ((1 << n_bits) - 1) & (left_bits >> n_left_bit_count) );
   break;
  } else {
   /* fetch n_left_bit_count bits */
   result <<= n_left_bit_count;
   result |= ( ((1 << n_left_bit_count) - 1) & left_bits );
   n_bits -= n_left_bit_count;
   n_left_bit_count = 0;
  }
 }
 /* set the changed pointer and bit values */
 p_rec->left_bits = left_bits;
 p_rec->n_left_bit_count = n_left_bit_count;
 p_rec->p_data = p_data;
 return result;
}

********************************************** 低調滴分隔線(4) ***************************************

發佈了41 篇原創文章 · 獲贊 2 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章