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

📄 jpgdecodercomponent.~cpp

📁 Jpeg编解码器的源代码
💻 ~CPP
📖 第 1 页 / 共 4 页
字号:

//
//  Description:
//
//    This function copies the component values at the edge of a data
//    unit to the 8 surrounding data units so that each value at the edge
//    of the center is the same as the adjacent value in the ajoining
//    data unit. This is used to create dummy data units at the edge of an
//    image.
//
//  Parameters:
//    center: The data unit to copy
//    upperleft, uppercenter, upperight,
//    left, right,
//    lowerleft, lowercenter, lowerright: The dummy data units to copy to.
//
inline void FillEdges (
                const JpegDecoderDataUnit &center,
                JpegDecoderDataUnit &upperleft,
                JpegDecoderDataUnit &uppercenter,
                JpegDecoderDataUnit &upperright,
                JpegDecoderDataUnit &left,
                JpegDecoderDataUnit &right,
                JpegDecoderDataUnit &lowerleft,
                JpegDecoderDataUnit &lowercenter,
                JpegDecoderDataUnit &lowerright)
{
  const int LAST = JPEGSAMPLEWIDTH - 1 ;
  upperleft [LAST][LAST] = center [0][0] ;
  lowerleft [0][LAST] = center [LAST][0] ;
  upperright [LAST][0] = center [0][LAST] ;
  lowerright [0][0] = center [LAST][LAST] ;
  for (unsigned int ii = 0 ; ii < JPEGSAMPLEWIDTH ; ++ ii)
  {
    left [ii][LAST] = center [ii][0] ;
    uppercenter [LAST][ii] = center [0][ii] ;
    right [ii][0] = center [ii][LAST] ;
    lowercenter [0][ii] = center [LAST][ii] ;
  }
}

}

namespace ColosseumPrivate
{
//
//  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 (0),
  dc_table (0),
  quantization_table (0),
  eob_run (0),
  noninterleaved_rows (0),
  noninterleaved_cols (0),
  data_units (0),
  coefficient_blocks (0),
  upsample_data (0)
{
  return ;
}

//
//  Description:
//
//    Class Destructor
//
JpegDecoderComponent::~JpegDecoderComponent ()
{
  delete [] data_units ; data_units = 0 ;
  delete [] upsample_data ; upsample_data = 0 ;
  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 JpegDecoder::JpegError ("Sampling Frequency Outside the Range 1-4") ;

  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 JpegDecoder::JpegError ("Vertical Sampling Frequency Outside the Range 1-4") ;

  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 == 0)
  {
    image_height = decoder.frameHeight () ;
    image_width = decoder.frameWidth () ;

    // 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 = (image_height
                           + v_sampling * JPEGSAMPLEWIDTH - 1)
                          / (v_sampling * JPEGSAMPLEWIDTH) ;
    noninterleaved_cols = (image_width
                           + h_sampling * JPEGSAMPLEWIDTH - 1)
                          / (h_sampling * JPEGSAMPLEWIDTH) ;

    du_rows = decoder.mcuRows () * vertical_frequency ;
    du_cols = decoder.mcuCols () * horizontal_frequency ;
    pdu_rows=du_rows;
    pdu_cols=du_cols;
    data_units = new JpegDecoderDataUnit [du_rows * du_cols] ;
  }

  if (decoder.isProgressive () && coefficient_blocks == 0)
  {
    unsigned int count = du_rows * du_cols ;
    coefficient_blocks = new JpegCoefficientBlock [count] ;
    memset (coefficient_blocks,
            0,
            sizeof (JpegCoefficientBlock) * count) ;
  }
  return ;
}

//
//  Description:
//
//    This function frees the memory allocated by the component
//    during the decompression process.
//
void JpegDecoderComponent::freeComponentBuffers ()
{
  delete [] data_units ; data_units = 0 ;
  delete [] coefficient_blocks ; coefficient_blocks = 0 ;
  delete [] upsample_data ; upsample_data = 0 ;
  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.
  ASSERT (ac_table != 0) ;

  if (! ac_table->tableDefined ())
    throw JpegDecoder::JpegBadStream ("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 ()
{
  ASSERT (dc_table != 0)

  // This condition could be caused by a corrupt JPEG stream.
  if (! dc_table->tableDefined ())
    throw JpegDecoder::JpegError ("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 == 0)
    throw JpegDecoder::JpegError ("INTERNAL ERROR - Quantization Table Not Assigned") ;

  if (! quantization_table->tableDefined ())
    throw JpegDecoder::JpegBadStream ("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 (JpegInputStream &inputstream,
                                             unsigned int mcurow,
                                             unsigned int mcucol)
{
  JpegCoefficientBlock 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 (inputstream) ;
  int bits = inputstream.getBits (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] = 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 (inputstream) ;
    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 JpegDecoder::JpegBadStream ("Coefficient Index out of Range") ;

      // Receive and extend the additional bits.
      // Section F2.2.2 Figure F.14
      int bits = inputstream.getBits (ssss) ;
      int value = Extend (bits, ssss) ;
      data [JpegZigZagInputOrder (kk)] = value ;
    }
  }

  data_units [mcurow * du_cols + mcucol].inverseDCT (data,
                                                     *quantization_table) ;
  //ShowMessage(data_units [mcurow * du_cols + mcucol].values[0][0]);
  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.
//
//  Parameters:
//
//    usefilter: true => Upsample using triangle filter if appropriate.
//
void JpegDecoderComponent::upsampleImage (bool usefilter)
{
  const unsigned int rowwidth = du_cols * h_sampling * JPEGSAMPLEWIDTH ;
  const unsigned int imagesize = rowwidth * du_rows * v_sampling * JPEGSAMPLEWIDTH ;
  if (imagesize == 0)
    return ;  // No data for this component yet.

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

  // Simple case where component does not need to be upsampled.
  if (v_sampling == 1 && h_sampling == 1)
  {
    upSample1To1 () ;
  }
  else
  {
    // The triangle filter only workd for 2:1 and 4:1 sampling.
    if (usefilter
        && (v_sampling % 2 == 0 || v_sampling == 1)
        && (h_sampling % 2 == 0 || h_sampling == 1))
    {
      triangleFilter () ;
    }
    else
    {
      blockFilter () ;
    }
  }

  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::convertGrayscale (JpegDecoderComponent &cc,
                                             BitmapImage &image)
{
  unsigned int rowstart = 0 ;
  BitmapImage::Pixel *pixel = &image [0] ;
  for (unsigned int ii = 0 ; ii < image.getHeight () ; ++ ii)
  {
    unsigned int offset = rowstart ;
    for (unsigned int jj = 0 ; jj < image.getWidth () ; ++ jj, ++ pixel)
    {
      pixel->red   = cc.upsample_data [offset] ;
      ShowMessage(pixel->red);
      pixel->green = cc.upsample_data [offset] ;
      pixel->blue  = cc.upsample_data [offset] ;
      pixel->alpha = 0xFFU ;
      ++ offset ;
    }
    rowstart += cc.du_cols * cc.h_sampling * JPEGSAMPLEWIDTH ;
  }
  return ;
}

//
//  Description:
//
//    This static member function converts the upsample_data in three

⌨️ 快捷键说明

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