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

📄 jpdecomp.cpp

📁 超强jpeg解码程序
💻 CPP
字号:
//
// 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 Component Class Implementation
//
// Author:  John M. Miano  miano@colosseumbuilders.com
//


#include "jpdecomp.h"
#include "jpgexcep.h"
#include "jpdequan.h"
#include "jpegdeco.h"
#include "jpdecobk.h"
#include "jpeg.h"
#include "bitimage.h"


//
//  Description:
//
//    SequentialOnly
//
//    This function extends the sign bit of a decoded value.
//
//  Parameters:
//    vv: The bit value
//    tt: The length of the bit value
//

static inline int Extend (int vv, int tt)
{
  // Extend function defined in Section F.2.2.1 Figure F.12
   // The tt'th bit of vv is the sign bit. One is for
   // positive values and zero is for negative values.
   int vt = 1 << (tt - 1) ;
   if (vv < vt)
   {
      vt = (-1 << tt) + 1 ;
      return vv + vt ;
   }
   else
   {
      return vv ;
   }
}

//
//  Description:
//
//    Class default constructor
//
JpegDecoderComponent::JpegDecoderComponent ()
{
  component_id = 0 ;
  horizontal_frequency = 0 ;
  vertical_frequency = 0 ;
  v_sampling = 0 ;
  h_sampling = 0 ;
  last_dc_value = 0 ;
  ac_table = NULL ;
  dc_table = NULL ;
  quantization_table = NULL ;
  noninterleaved_rows = 0 ;
  noninterleaved_cols = 0 ;
  data_units = NULL ;
  upsample_data = NULL ;
  return ;
}

//
//  Description:
//
//    Class Destructor
//
JpegDecoderComponent::~JpegDecoderComponent ()
{
  delete [] data_units ; data_units = NULL ;
  delete [] upsample_data ; upsample_data = NULL ;
  return ;
}

//
//  Description:
//
//    This function sets the horizontal sampling frequency
//    for the component.
//
//  Parameters:
//    value: The sampling factor (1..4)
//
void JpegDecoderComponent::HorizontalFrequency (unsigned int value)
{
  if (value < JpegMinSamplingFrequency || value > JpegMaxSamplingFrequency)
    throw EJpegValueOutOfRange () ;

  horizontal_frequency = value ;
  return ;
}

//
//  Description:
//
//    This function sets the vertical sampling frequency
//    for the component.
//
//  Parameters:
//    value: The sampling factor (1..4)
//
void JpegDecoderComponent::VerticalFrequency (unsigned int value)
{
  if (value < JpegMinSamplingFrequency || value > JpegMaxSamplingFrequency)
    throw EJpegValueOutOfRange () ;

  vertical_frequency = value ;

  return ;
}

//
//  Description:
//
//    This function associates a quantization table with the component.
//
//  Parameters:
//    table:  The quantization table
//
void JpegDecoderComponent::SetQuantizationTable (
                                     JpegDecoderQuantizationTable &table)
{
  quantization_table = &table ;
  return ;
}

//
//  Description:
//
//    This function determines the dimensions for the component and allocates
//    the storage to hold the component's data.
//
//  Parameters:
//    decoder:  The jpeg decoder this component belongs to.
//
void JpegDecoderComponent::AllocateComponentBuffers (
                               const JpegDecoder &decoder)
{
  if (data_units == NULL)
  {
    // Determine sampling for the component. This is the amount of
    // stretching needed for the component.
    v_sampling = decoder.MaxVFrequency () / vertical_frequency ;
    h_sampling = decoder.MaxHFrequency () / horizontal_frequency ;

    // Determine the component's dimensions in a non-interleaved scan.
    noninterleaved_rows = (decoder.FrameHeight ()
                           + v_sampling * JpegSampleWidth - 1)
                          / (v_sampling * JpegSampleWidth) ;
    noninterleaved_cols = (decoder.FrameWidth ()
                           + h_sampling * JpegSampleWidth - 1)
                          / (h_sampling * JpegSampleWidth) ;

    du_rows = decoder.McuRows () * vertical_frequency ;
    du_cols = decoder.McuCols () * horizontal_frequency ;

    data_units = new JpegDecoderDataUnit [du_rows * du_cols] ;
  }

  return ;
}

//
//  Description:
//
//    This function frees the memory allocated by the component
//    during the decompression process.
//
void JpegDecoderComponent::FreeComponentBuffers ()
{
  delete [] data_units ; data_units = NULL ;
  delete [] upsample_data ; upsample_data = NULL ;
  return ;
}

//
//  Description:
//
//    This function asigned Huffman tables to the component.
//
//  Parameters:
//    dc:  The DC Huffman table
//    ac:  The AC Huffman table
//
void JpegDecoderComponent::SetHuffmanTables (JpegHuffmanDecoder &dc,
                                             JpegHuffmanDecoder &ac)
{
  dc_table = &dc ;
  ac_table = &ac ;
  return ;
}

//
//  Description:
//
//    This function ensures that this component has a defined
//    AC table assigned to it. If not, it throws an exception.
//
void JpegDecoderComponent::CheckAcTable ()
{
  // If this occurs then we have a programming error.
  if (ac_table == NULL)
    throw EJpegFatal ("INTERNAL ERROR - AC Table Not Assigned") ;

  if (! ac_table->Defined ())
    throw EJpegError ("AC Table Not Defined") ;

  return ;
}

//
//  Sequential and Progressive
//
//  This function is called before processing a scan. It ensures that the
//  DC Huffman table used by the component has actually been defined.
//
void JpegDecoderComponent::CheckDcTable ()
{
  if (dc_table == NULL)
    throw EJpegFatal ("INTERNAL ERROR - DC Table Not Assigned") ;

  // This condition could be caused by a corrupt JPEG stream.
  if (! dc_table->Defined ())
    throw EJpegFatal ("INTERNAL ERROR - DC Table Not Defined") ;

  return ;
}

//
//  Description:
//
//    Sequential and Progressive
//
//    This function is called before processing a scan. It ensures that the
//    Quantization table used by the component has actually been defined.
//
void JpegDecoderComponent::CheckQuantizationTable ()
{
  if (quantization_table == NULL)
    throw EJpegFatal ("INTERNAL ERROR - Quantization Table Not Assigned") ;

  if (! quantization_table->Defined ())
    throw EJpegError ("Quantization Table Not Defined") ;

  return ;
}

//
//  Description:
//
//    This function decodes a data unit in a sequential scan.
//
//  Parameters:
//    decoder: The decoder that owns this component
//    mcurow, mcucol:  The row and column for this data unit.
//
void JpegDecoderComponent::DecodeSequential (JpegDecoder &decoder,
                                             unsigned int mcurow,
                                             unsigned int mcucol)
{
  JpegDecoderCoefficientBlock data ;
  memset (&data, 0, sizeof (data)) ;

  // Decode the DC differce value.
  // Section F.2.2.1
  unsigned int count ; // called T in F.2.2.1
  count = dc_table->Decode (decoder) ;
  int bits = decoder.Receive (count) ;
  int diff = Extend (bits, count) ;

  // Create the DC value from the difference and the previous DC value.
  int dc = diff + last_dc_value ;
  last_dc_value = dc ;
  data [0][0] = dc ;

  // Decode the AC coefficients.
  // Section F.2.2.2 Figure F.13
  for (unsigned int kk = 1 ; kk < JpegSampleSize ; ++ kk)
  {
    UBYTE2 rs = ac_table->Decode (decoder) ;
    UBYTE2 ssss = (UBYTE2) (rs & 0xF) ;
    UBYTE2 rrrr = (UBYTE2) (rs >> 0x4) ;

    if (ssss == 0)
    {
      // ssss is zero then rrrr should either be 15 or zero according to
      // Figure F.1. 0 means that the rest of the coefficients are zero
      // while 15 means the next 16 coefficients are zero. We are not checking
      // for other values because Figure F.13 shows values other than 15
      // as being treated as zero.
      if (rrrr  != 15)
        break ;
      kk += 15 ; // Actually 16 since one more gets added by the loop.
    }
    else
    {
      // If ssss is non-zero then rrrr gives the number of zero coefficients
      // to skip.

      kk += rrrr ;
      if (kk >= JpegSampleSize)
        throw EJpegFatal ("Value out of range") ;

      // Receive and extend the additional bits.
      // Section F2.2.2 Figure F.14
      int bits = decoder.Receive (ssss) ;
      int value = Extend (bits, ssss) ;
      (&data [0][0])[JpegZigZagInputOrder (kk)] = value ;
    }
  }
  data_units [mcurow * du_cols + mcucol].InverseDCT (data,
                                                     *quantization_table) ;
  return ;
}

//
//  Description:
//
//    This function upsamples the data for the component. Here we take
//    the values from the data_units array and copy it to the
//    upsample_data. If the horizontal or vertical sampling frequencies
//    are less than the maximum for the image then we need to
//    stretch the data during the copy.
//
void JpegDecoderComponent::Upsample ()
{
  unsigned int imagesize = du_rows * v_sampling * du_cols
                              * h_sampling * JpegSampleSize ;
  if (imagesize == 0)
    return ;  // No data for this component yet.

  if (upsample_data == NULL)
    upsample_data = new JPEGSAMPLE [imagesize] ;

  // Simple case where component does not need to be upsampled.
  if (v_sampling == 1 && h_sampling == 1)
  {
    unsigned output = 0 ;
    unsigned int startdu = 0 ;
    for (unsigned int durow = 0 ; durow < du_rows ; ++ durow)
    {
      for (unsigned int ii = 0 ; ii < JpegSampleWidth ; ++ ii)
      {
         unsigned int du = startdu ;
	      for (unsigned int ducol = 0 ; ducol < du_cols ; ++ ducol)
        {
      	  upsample_data [output] = data_units [du][ii][0] ; ++ output ;
      	  upsample_data [output] = data_units [du][ii][1] ; ++ output ;
      	  upsample_data [output] = data_units [du][ii][2] ; ++ output ;
      	  upsample_data [output] = data_units [du][ii][3] ; ++ output ;
      	  upsample_data [output] = data_units [du][ii][4] ; ++ output ;
      	  upsample_data [output] = data_units [du][ii][5] ; ++ output ;
      	  upsample_data [output] = data_units [du][ii][6] ; ++ output ;
      	  upsample_data [output] = data_units [du][ii][7] ; ++ output ;
          ++ du ;
      	}
      }
      startdu += du_cols ;
    }
  }
  else
  {
    unsigned output = 0 ;
    unsigned int startdu = 0 ;
    for (unsigned int durow = 0 ; durow < du_rows ; ++ durow)
    {
      for (unsigned int ii = 0 ; ii < JpegSampleWidth ; ++ ii)
      {
         for (unsigned int vv = 0 ; vv < v_sampling ; ++ vv)
         {
           unsigned int du = startdu ;
    	      for (unsigned int ducol = 0 ; ducol < du_cols ; ++ ducol)
           {
             unsigned int jj ;
             for (jj = 0 ; jj < h_sampling ; ++ jj)
             {
               upsample_data [output] = data_units [du][ii][0] ; ++ output ;
             }
             for (jj = 0 ; jj < h_sampling ; ++ jj)
             {
               upsample_data [output] = data_units [du][ii][1] ; ++ output ;
             }
             for (jj = 0 ; jj < h_sampling ; ++ jj)
             {
               upsample_data [output] = data_units [du][ii][2] ; ++ output ;
             }
             for (jj = 0 ; jj < h_sampling ; ++ jj)
             {
               upsample_data [output] = data_units [du][ii][3] ; ++ output ;
             }
             for (jj = 0 ; jj < h_sampling ; ++ jj)
             {
               upsample_data [output] = data_units [du][ii][4] ; ++ output ;
             }
             for (jj = 0 ; jj < h_sampling ; ++ jj)
             {
               upsample_data [output] = data_units [du][ii][5] ; ++ output ;
             }
             for (jj = 0 ; jj < h_sampling ; ++ jj)
             {
               upsample_data [output] = data_units [du][ii][6] ; ++ output ;
             }
             for (jj = 0 ; jj < h_sampling ; ++ jj)
             {
               upsample_data [output] = data_units [du][ii][7] ; ++ output ;
             }
             ++ du ;
           }
      	}
      }
      startdu += du_cols ;
    }
  }
  return ;
}

//
//  Description:
//
//    This static member function grayscale converts component
//    image data in the upsample_data array and writes it to the
//    the output image.  Actually for a grayscale conversion all
//    we do is copy.
//
//  Parameters:
//    cc:  The component
//    image:  The output image
//
void JpegDecoderComponent::GrayscaleConvert (JpegDecoderComponent &cc,
                                             BitmapImage &image)
{
  unsigned int rowstart = 0 ;
  for (unsigned int ii = 0 ; ii < image.Height () ; ++ ii)
  {
    unsigned int offset = rowstart ;
    UBYTE1 *outrow = image [ii] ;
    for (unsigned int jj = 0 ; jj < image.Width () ; ++ jj)
    {
      outrow [jj] = cc.upsample_data [offset] ;
      ++ offset ;
    }
    rowstart += cc.du_cols * cc.h_sampling * JpegSampleWidth ;
  }
  return ;
}

//
//  Description:
//
//    This static member function converts the upsample_data in three
//    components from YCbCr to RGB and writes it to an image.
//
//  Parameters:
//    c1: The component containing the Y data
//    c2: Ditto for Cb
//    c3: Ditto for Cr
//    image: The output image
//
void JpegDecoderComponent::RGBConvert (JpegDecoderComponent &c1,
                                       JpegDecoderComponent &c2,
                                       JpegDecoderComponent &c3,
                                       BitmapImage &image)
{
  if (c1.upsample_data == NULL
      || c2.upsample_data == NULL
      || c3.upsample_data == NULL)
  {
    // If we get here then do do not yet have data for all components.
    return ;
  }

  unsigned int rowstart = 0 ;
  for (unsigned int ii = 0 ; ii < image.Height () ; ++ ii)
  {
    unsigned int offset = rowstart ;
    UBYTE1 *outrow = image [ii] ;
    for (unsigned int jj = 0 ; jj < 3 * image.Width () ; jj += 3)
    {
      JPEGSAMPLE red = YCbCrToR (c1.upsample_data [offset],
                                 c2.upsample_data [offset],
                                 c3.upsample_data [offset]) ;
      JPEGSAMPLE green = YCbCrToG (c1.upsample_data [offset],
                                  c2.upsample_data [offset],
                                  c3.upsample_data [offset]) ;
      JPEGSAMPLE blue = YCbCrToB (c1.upsample_data [offset],
                                  c2.upsample_data [offset],
                                  c3.upsample_data [offset]) ;
      outrow [jj + BitmapImage::RedOffset] = red ;
      outrow [jj + BitmapImage::GreenOffset] = green ;
      outrow [jj + BitmapImage::BlueOffset] = blue ;
      ++ offset ;
    }
    rowstart += c1.du_cols * c1.h_sampling * JpegSampleWidth ;
  }
  return ;
}

⌨️ 快捷键说明

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