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

📄 jpegdeco.cpp

📁 超强jpeg解码程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) 1997,1998 Colosseum Builders, Inc.
// All rights reserved.
//
// Colosseum Builders, Inc. makes no warranty, expressed or implied
// with regards to this software. It is provided as is.
//
// See the README.TXT file that came with this software for restrictions
// on the use and redistribution of this file or send E-mail to
// info@colosseumbuilders.com
//

//
// JPEG Decoder Class Implementation
//
// Author:  John M. Miano miano@colosseumbuilders.com
//
#include <iostream>
#include "jpegdeco.h"
#include "jfif.h"
#include "jpdehuff.h"
#include "bitimage.h"
#include "jpdequan.h"
#include "jpdecomp.h"
#include <limits.h>

using namespace std ;
//
//  Description:
//
//    Class Default Constructor
//
JpegDecoder::JpegDecoder ()
{
  Initialize () ;
  return ;
}
//
//  Description:
//
//    Class copy constructor
//
JpegDecoder::JpegDecoder (const JpegDecoder &source)
{
  Initialize () ;
  DoCopy (source) ;
  return ;
}

//
//  Description:
//
//    Class Destructor
//
JpegDecoder::~JpegDecoder ()
{
  delete [] ac_tables ; ac_tables = NULL ;
  delete [] dc_tables ; dc_tables = NULL ;

  delete [] quantization_tables ; quantization_tables = NULL ;
  delete [] components ; components = NULL ;
  delete [] component_indices ; component_indices = NULL ;
  delete [] scan_components ; scan_components = NULL ;
  return ;
}
//
//  Description:
//
JpegDecoder &JpegDecoder::operator=(const JpegDecoder &source)
{
  DoCopy (source) ;
  return *this ;
}

//
//  Description:
//
//    Class initialization procudure for use by constructors.
//
void JpegDecoder::Initialize ()
{
  verbose_flag = false ;
  strict_jfif = false ;

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

  quantization_tables = new JpegDecoderQuantizationTable [MaxQuantizationTables] ;
  components = new JpegDecoderComponent [JpegMaxComponentsPerFrame] ;
  component_indices = new unsigned int [JpegMaxComponentsPerFrame] ;

  scan_components = new JpegDecoderComponent * [JpegMaxComponentsPerScan] ;
  return ;
}
//
//  Description:
//
//    Copy function. This function is called by the assignment operator
//    and copy constructor to copy the state of one object to another.
//    we only copy user configurable parameters. We do not support
//    copying while a decode operation is in progress.
//
void JpegDecoder::DoCopy (const JpegDecoder &source)
{
  verbose_flag = source.verbose_flag ;
  strict_jfif = source.strict_jfif ;
  BitmapImageCoder::operator=(source) ;
  return ;
}
//
//  Description:
//
//    This function returns the next byte from the input stream.
//
UBYTE1 JpegDecoder::ReadByte ()
{
  UBYTE1 value ;
  input_stream->read ((char *) &value, sizeof (value)) ;
  bit_position = 0 ;

  if (input_stream->eof ())
    throw EJpegBadData ("Premature end of file") ;
  return value ;
}

//
//  Description:
//
//    This function reads the next 2-byte integer from the input stream
//    and returns the value in the correct format for the system.
//

UBYTE2 JpegDecoder::ReadWord ()
{
  bit_position = 0 ;
  UBYTE2 value ;
  input_stream->read ((char *) &value, sizeof (value)) ;
  return BigEndianToSystem (value) ;
}

//
//  Description:
//
//    Section F.2.2.4
//
//    Extracts the next "count" bits from the input stream.
//
int JpegDecoder::Receive (unsigned int count)
{
  int result = 0 ;
  for (unsigned int ii = 0 ; ii < count ; ++ii)
  {
    result <<= 1 ;
    result |= NextBit () ;
  }
  return result ;
}

//
//  Description:
//
//    This function reads the Start of Image Marker and the JFIF APP0
//    marker that begin a JPEG file.
//
//    The JFIF standard states "The JPEG FIF APP0 marker is mandatory
//     right after the SOI marker."
//
//    I have come across some JPEG files that have a COM marker between
//    the SOI marker and APP0. This code will reject these non-conforming
//    files.
//

void JpegDecoder::ReadStreamHeader ()
{
  if (ReadByte () != SOB)
    throw EJpegBadData ("Missing SOI Marker") ;
  if (ReadByte () != SOI)
    throw EJpegBadData ("Missing SOI Marker") ;
  if (ReadByte () != SOB)
    throw EJpegBadData ("Missing JFIF APP0 Marker") ;
  if (ReadByte () != APP0)
    throw EJpegBadData ("Missing JFIF APP0 Marker") ;

  JfifHeader header ;
  input_stream->read ((char *) &header, sizeof (header)) ;
  if (memcmp ("JFIF", (char *) header.identifier, 4) != 0)
    throw EJpegBadData ("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)
    (void) ReadByte () ;

  return ;
}

//
//  Description:
//
//    This function reads the next marker in the input
//    stream. If the marker is followed by a data block
//    this function dispatches a routine to read the
//    data.
//
void JpegDecoder::ReadMarker ()
{
  while (! input_stream->eof ())
  {
    UBYTE1 type = ReadByte () ;
    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 () ;
      return ;
    case DHP:
      throw EJpegBadData ("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:
      ReadStartOfFrame (type) ;
      return ;
    case SOF2:
      throw EJpegBadData ("Progressive JPEG Not Supported") ;
    case SOF3:
      throw EJpegBadData ("Lossless Huffman Coding Not Supported") ;
    case SOF5:
      throw EJpegBadData (
        "Differential Sequential Huffman Coding Not Supported") ;
    case SOF6:
      throw EJpegBadData (
        "Differential Progressive Huffman Coding Not Supported") ;
    case SOF7:
      throw EJpegBadData (
        "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 EJpegBadData (
        "Cannot read image - Arithmetic Coding covered by patents") ;
    case DHT:
      ReadHuffmanTable () ;
      return ;
    case SOS:
      ReadStartOfScan () ;
      return ;
    case DRI:
      ReadRestartInterval () ;
      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) ;
      return ;
    default:
      // We call ReadByte to make sure the problem
      // is not a premature EOF.
      (void) ReadByte () ; 
      throw EJpegBadData (
      "Unknown, unsupported, or reserved marker encountered") ;
    }
  }
  throw EJpegBadData ("Premature end of file") ;
}

//
//  Description:
//
//    This method reads an application or comment marker
//    from the input stream.
//
//  Parameters:
//    type:  The marker type
//
void JpegDecoder::ReadApplication (UBYTE1 type)
{
  unsigned int length = ReadWord () ;
  char id [512] ;
  int ii = 0 ;

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

  for ( ; ii < length - sizeof (UBYTE2) ; ++ ii)
    (void) ReadByte () ;

  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 ;
}

//
//  Description:
//
//    The function reads a Define Huffman Table marker from the input
//    stream.
//
void JpegDecoder::ReadHuffmanTable ()
{
  // Section B.2.4.2

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

  UBYTE2 length = ReadWord () ;

⌨️ 快捷键说明

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