⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpgdecoder.~cpp

📁 Jpeg编解码器的源代码
💻 ~CPP
📖 第 1 页 / 共 3 页
字号:
//
//  标题:  JPEG解码器类实现
//
#include <iostream>
#include <climits>

#include "jpgdecoder.h"
#include "jfif.h"
#include "jpghuffmandecoder.h"
#include "bitmapimage.h"
#include "jpgdecoderquantization.h"
#include "jpgdecodercomponent.h"
#include "jpginputfilestream.h"
#include "jpginputmapstream.h"
#include "vcl.h"
#include "jpgcoefficient.h"

using namespace std ;
using namespace ColosseumPrivate ;


namespace Colosseum
{

//
//  描述:
//
//    类缺省构造函数
//
JpegDecoder::JpegDecoder ()
{
  initialize () ;
  return ;
}
//
//  描述:
//
//    类复制构造函数
//
JpegDecoder::JpegDecoder (const JpegDecoder &source)
{
  initialize () ;
  doCopy (source) ;
  return ;
}

//
//  描述:
//
//    类析构函数
//
JpegDecoder::~JpegDecoder ()
{
  delete [] ac_tables ; ac_tables = 0 ;
  delete [] dc_tables ; dc_tables = 0 ;

  delete [] quantization_tables ; quantization_tables = 0 ;
  delete [] components ; components = 0 ;
  delete [] component_indices ; component_indices = 0 ;
  delete [] scan_components ; scan_components = 0 ;
  return ;
}
//
//  描述:
//       赋值
//
JpegDecoder &JpegDecoder::operator=(const JpegDecoder &source)
{
  doCopy (source) ;
  return *this ;
}

//
//  描述:
//
//    类初始化
//
void JpegDecoder::initialize ()
{
  verbose_flag = false ;
  strict_jfif = false ;
  processing_image = false ;

  ac_tables = new JpegHuffmanDecoder [JPEGMAXHUFFMANTABLES] ;
  dc_tables = new JpegHuffmanDecoder [JPEGMAXHUFFMANTABLES] ;

  quantization_tables = new JpegDecoderQuantizationTable [JPEGMAXQUANTIZATIONTABLES] ;
  components = new JpegDecoderComponent [JPEGMAXCOMPONENTSPERFRAME] ;
  component_indices = new unsigned int [JPEGMAXCOMPONENTSPERFRAME] ;

  scan_components = new JpegDecoderComponent * [JPEGMAXCOMPONENTSPERFRAME] ;

  use_filters = false ;
  return ;
}
//
//  描述:
//
//    复制函数
//
void JpegDecoder::doCopy (const JpegDecoder &source)
{
  verbose_flag = source.verbose_flag ;
  strict_jfif = source.strict_jfif ;
  BitmapImageCoder::operator=(source) ;
  return ;
}

//
//  描述:
//
//    读JPEG文件开头的SOI标记和JFIF APP0标记
//
//    APP0在SIO标记之后,可能中间插入COM标记
//

void JpegDecoder::readStreamHeader (JpegInputStream &inputstream)
{
  if (inputstream.getByte () != SOB)
    throw JpegBadStream ("Missing SOI Marker") ;
  if (inputstream.getByte () != SOI)
    throw JpegBadStream ("Missing SOI Marker") ;
  if (inputstream.getByte () != SOB)
    throw JpegBadStream ("Missing JFIF APP0 Marker") ;
  if (inputstream.getByte () != APP0)
    throw JpegBadStream ("Missing JFIF APP0 Marker") ;

  JfifHeader header ;
  inputstream.read (reinterpret_cast<char*>(&header), sizeof (header)) ;
  if (memcmp ("JFIF", reinterpret_cast<char *>(header.identifier), 4) != 0)
    throw JpegBadStream ("Not a JFIF file") ;

  if (verbose_flag)
  {
    cout << "{ Start Of Image }" << endl ;
    cout << "{ JFIF APP0 Marker" << endl ;
    cout << "  Length: " << dec << BigEndianToSystem (header.length) << endl ;
    cout << "  Version: " << dec << (unsigned int) header.version [0]
         << "." << (unsigned int) header.version [0] << endl ;
    // density unit = 0 => Only the aspect ratio is specified.
    // density unit = 1 => Density in pixels per inch.
    // density unit = 2 => Density in pixels per centimeter.
    cout << "  Density Unit: " ;
    switch (header.units)
    {
    case 0:   cout << " (aspect ratio)" << endl ;     break ;
    case 1:   cout << " (pixels per inch)" << endl ;  break ;
    case 2:   cout << " (pixels/cm)" << endl ;        break ;
    default:  cout << " (????)" << endl ;             break ;
    }
    cout << "  X Density: " << dec << BigEndianToSystem (header.xdensity) << endl ;
    cout << "  Y Density: " << dec << BigEndianToSystem (header.xdensity) << endl ;
    cout << "  Thumbnail Width: " << dec << (unsigned int) header.xthumbnail << endl ;
    cout << "  Thumbnail Height: " << dec << (unsigned int) header.xthumbnail << endl ;
    cout << "}" << endl ;
  }

  // Skip over any thumbnail data.
  for (int ii = sizeof (header) ; ii < BigEndianToSystem (header.length) ; ++ ii)
    inputstream.getByte () ;

  return ;
}

//
//  描述:
//
//    读下一个标记
//
void JpegDecoder::readMarker (JpegInputStream &inputstream)
{
  while (inputstream.moreData ())
  {
    UBYTE1 type = inputstream.getByte () ;
    switch (type)
    {
    case SOB:
      // According to E.1.2, 0xFF is allowed as fill when a
      // marker is expected.
      break ;
    case SOI:
      if (verbose_flag)
        cout << "{ Start Of Image }" << endl ;
      return ; // SOI has no data.
    case DQT:
      readQuantization (inputstream) ;
      return ;
    case DHP:
      throw JpegBadStream ("DHP marker not supported") ;

    // The only difference between a Sequential DCT Frame
    // (SOF0) and an extended Sequential DCT Frame (SOF1)
    // is that a baseline frame may only have 2 DC and 2 AC
    // Huffman tables per scan (F.1.2) and and extended
    // Sequential Frame may have up to 4 DC and 4 AC Huffman
    // tables per scan (F.1.3). Both are decoded identically
    // for 8-bit precision. Extended Sequential frames may
    // use 12-bit precision (F, Table B.2) which we do not
    // support.
    case SOF0:
    case SOF1:
    case SOF2:
      readStartOfFrame (inputstream, type) ;
      return ;
    case SOF3:
      throw JpegBadStream ("Lossless Huffman Coding Not Supported") ;
    case SOF5:
      throw JpegBadStream (
        "Differential Sequential Huffman Coding Not Supported") ;
    case SOF6:
      throw JpegBadStream (
        "Differential Progressive Huffman Coding Not Supported") ;
    case SOF7:
      throw JpegBadStream (
        "Differential Lossless Huffman Coding Not Supported") ;

    // These are markers for frames using arithmetic coding.
    // Arithmetic coding is covered by patents so we ignore
    // this type.
    case SOF9:
    case SOFA:
    case SOFB:
    case SOFD:
    case SOFE:
    case SOFF:
      throw JpegBadStream (
        "Cannot read image - Arithmetic Coding covered by patents") ;
    case DHT:
      readHuffmanTable (inputstream) ;
      return ;
    case SOS:
      readStartOfScan (inputstream) ;
      return ;
    case DRI:
      readRestartInterval (inputstream) ;
      return ;
    case EOI:
      eoi_found = true ;
      if (verbose_flag)
        cout << "{ End Of Image }" << endl ;
      return ; // End of Image marker has no data
    case APP0:
    case APP1:
    case APP2:
    case APP3:
    case APP4:
    case APP5:
    case APP6:
    case APP7:
    case APP8:
    case APP9:
    case APPA:
    case APPB:
    case APPC:
    case APPD:
    case APPE:
    case APPF:
    case COM:
      readApplication (type, inputstream) ;
      return ;
    default:
      // We call ReadByte to make sure the problem
      // is not a premature EOF.
      inputstream.getByte () ;
      throw JpegBadStream (
      "Unknown, unsupported, or reserved marker encountered") ;
    }
  }
  throw JpegBadStream ("Premature end of file") ;
}

//
//  描述:
//
//    读应用和注释标记
//
//
//  参数:
//    type:  标记类型
//
void JpegDecoder::readApplication (UBYTE1 type, JpegInputStream &inputstream)
{
  unsigned int length = inputstream.getBigEndianWord () ;
  char id [512] ;
  int ii = 0 ;

  id [ii] = inputstream.getByte () ;
  for (ii = 1 ; id [ii - 1] != '\000'
                && ii < sizeof (id)
                && ii < length - sizeof (UBYTE2) ; ++ ii)
  {
    id [ii] = inputstream.getByte () ;
  }

  for ( ; ii < length - sizeof (UBYTE2) ; ++ ii)
    (void) inputstream.getByte () ;

  if (verbose_flag)
  {
    if (type == COM)
      cout << "( Comment Marker" << endl ;
    else
    cout << "{ APP" << hex << (UBYTE2) (type & 0x0F) << " Marker" << endl ;
    cout << "Length: " << dec << length << endl ;
    cout << "ID: " << id << endl ;
    cout << "}" << endl ;
  }
  return ;
}

//
//  描述:
//
//    读 a Define Huffman Table标记
//
void JpegDecoder::readHuffmanTable (JpegInputStream &inputstream)
{
  // Section B.2.4.2

  if (verbose_flag)
    cout << "{ Define Huffman Table" << endl ;

  UBYTE2 length = inputstream.getBigEndianWord () ;
  unsigned int remaining = length - sizeof (length) ;
  while (remaining > 0)
  {
    UBYTE1 data = inputstream.getByte () ; -- remaining ;

    // Tc in standard 0=>DC, 1=>AC
    unsigned int tableclass = data >> 4 ;
    unsigned int id = data & 0x0F ; // Th in standard
    if (id > 3)
    {
      throw JpegBadStream (
        "Huffman Table Index outside range [0..3]") ;
    }
    if (verbose_flag)
    {
      cout << "   Table Index " << (int) id << endl ;
      if (tableclass == 0)
        cout << "   Table Class: DC" << endl ;
      else
        cout << "   Table Class: AC" << endl ;
    }
    if (id > 3)
    {
      cout << "Bad index " << id << endl ;
      return ;
    }

    JpegHuffmanDecoder *table ;
    if (tableclass != 0)
      table = &ac_tables [id] ;
    else
      table = &dc_tables [id] ;

    // Read the table data into the table object
    remaining -= table->readTable (inputstream) ;

    if (verbose_flag)
    {
      table->printOn (cout) ;
    }
  }

  if (verbose_flag)
    cout << "}" << endl ;
  return ;
}

//
//  描述:
//
//    读DQT标记
//
void JpegDecoder::readQuantization (JpegInputStream &inputstream)
{
  // Defined in Section B.2.4.1

  UBYTE2 length = inputstream.getBigEndianWord () ;
  UBYTE1 data ;

  // Maintain a counter for the number of bytes remaining to be read in
  // the quantization table.
  int remaining = length - sizeof (length) ;

  if (verbose_flag)
  {
    cout << "{ Define Quantization Table" << endl ;
    cout << "  Length: " << length << endl ;
  }
  while (remaining > 0)
  {
    data = inputstream.getByte () ; -- remaining ;
    unsigned int precision = data >> 4 ;    // Pq in standard
    unsigned int index = data & 0x0F ;      // Tq in standard

    if (index >= JPEGMAXQUANTIZATIONTABLES)
      throw JpegBadStream ("Quantization Table Index Too Large") ;

    if (verbose_flag)
    {
      cout << "  Table Index: " << dec << index << endl ;
      cout << "  Table Precision: " << dec << precision << endl ;
    }

    switch (precision)
    {
    case 1:
      remaining -= sizeof(UBYTE2) * JPEGSAMPLESIZE ;
      break ;
    case 0:
      remaining -= sizeof (UBYTE1) * JPEGSAMPLESIZE ;
      break ;
    }

    // Read the table data into the table object
    quantization_tables [index].readTable (inputstream, precision) ;
    int c[64];
    quantization_tables [index].printOnArray(c);

    if (verbose_flag)
    {
      cout << "  Table Values: " ;
      quantization_tables [index].printOn (cout) ;
      cout << endl << "}" << endl ;
    }
  }
  return ;
}

//
//  描述:
//
//    读重启间隔标记
//
void JpegDecoder::readRestartInterval (JpegInputStream &inputstream)
{
  // Section B.2.4.4

  UBYTE2 length = inputstream.getBigEndianWord () ;
  restart_interval = inputstream.getBigEndianWord () ;
  if (verbose_flag)
  {
    cout << "{ Define Restart Interval" << endl ;
    cout << "  Length:  " << dec << length << endl ; // Should be 4
    cout << "  Interval: " << dec << restart_interval << endl ;
    cout << "}" << endl ;
   }
   return ;
}

//
//  描述:
//
//    读SOF标记
//
//  参数:
//    type:  帧的标记类型
//
void JpegDecoder::readStartOfFrame (JpegInputStream &inputstream, UBYTE1 type)
{
  if (type == SOF2)
    progressive_frame = true ;
  else
    progressive_frame = false ;

  // Section B.2.2
  // Read in the image dimensions
  unsigned int length = inputstream.getBigEndianWord () ;
  unsigned int dataprecision = inputstream.getByte () ;  // P in standard
  if (dataprecision != 8)
    throw JpegBadStream ("Only 8-bit data supported") ;

  frame_height = inputstream.getBigEndianWord () ;            // Y in standard
  frame_width = inputstream.getBigEndianWord () ;             // X in standard
  component_count = inputstream.getByte () ;   // Nf in standard

  // JFIF only allows 1 or 3 components.
  if (component_count != 1 && component_count != 3)
    throw JpegBadStream ("JFIF only supports 1 and 3 component streams") ;

  frame_type = type ;

  if (verbose_flag)
  {
    cout << "{ Start Of Frame " << endl ;
    cout << "  Length: " << dec << length << endl ;
    cout << "  Precision: " << dec << dataprecision << endl ;
    cout << "  Height: " << dec << frame_height << endl ;
    cout << "  Width: " << dec << frame_width << endl ;
    cout << "  Component Count: " << component_count << endl ;
  }

  if (length != (component_count * 3 + 8))
    throw JpegBadStream ("Invalid Frame Size") ;

  // Rread the component descriptions
  max_horizontal_frequency = 0 ;
  max_vertical_frequency = 0 ;
  for (unsigned int ii = 0 ; ii < component_count ; ++ ii)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -