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

📄 jpgencoder.~cpp

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

  resetDcValues () ;

  unsigned int intervalcount = 0 ;
  unsigned int restartmarker = 0 ;
  for (unsigned int mcurow = 0 ;
       mcurow < mcu_rows ;
       ++ mcurow)
  {
    for (unsigned int mcucol = 0 ;
         mcucol < mcu_cols ;
          ++ mcucol, ++ intervalcount)
    {
      // Handle Restart Markers
      if (restart_interval != 0)
      {
        if (intervalcount == restart_interval && restart_interval != 0)
        {
          if (writedata)
            outputRestartMarker (outputstream, restartmarker) ;
          resetDcValues () ;
          ++ restartmarker ;
          restartmarker %= 8 ;
          intervalcount = 0 ;
        }
      }

      for (unsigned int cc = 0 ; cc < scan_component_count ; ++ cc)
      {
        for (unsigned int cy = 0 ;
             cy < scan_components [cc]->getVerticalFrequency () ;
             ++ cy)
        {
          unsigned int durow = scan_components [cc]->getVerticalFrequency ()
                             * mcurow + cy ;
          for (unsigned int cx = 0 ;
               cx < scan_components [cc]->getHorizontalFrequency () ;
               ++ cx)
          {
            unsigned int ducol
              = scan_components [cc]->getHorizontalFrequency ()
              * mcucol + cx ;
            (scan_components [cc]->*passfunction) (durow, ducol,
                                              dcfunction, acfunction,
                                              sss, sse, ssa) ;
          }
        }
      }
    }
    progress += progressincrement ;
    callProgressFunction (progress >> progressscale) ;
  }
  if (writedata)
    callProgressFunction (100) ;
  else
    callProgressFunction (50) ;
  return ;
}

//
//  Description:
//
//    This function writes the Huffman tables used by a scan to the output
//    stream.
//
//    We only use two DC and two AC tables to be compatible with baseline
//    JPEG.  In progressive JPEG there is really no reason for more than
//    two tables for RGB images. If we ever go to four colors then things
//    may need to change.
//
//    The Y component always uses table ID 0. The Cb and Cr components always
//    use table ID 1.
//
//  Parameters:
//    scan:     Here the scan structure is used to determine which components
//              are part of the scan (Y and/or Cb/Cr)
//    usedc:    Set to true if the scan includes DC components. (Sequential
//              Scan or Progressive Scan with the spectral selection 0)
//    useac:    Set to true if the scan includes AC components. (Sequential
//              Scan or Progressive Scan with the spectral selection start
//              not zero)
//
void JpegEncoder::printHuffmanTables (JpegOutputStream &outputstream,
                                      const Scan &scan,
                                      bool usedc,
                                      bool useac)
{
  // Section B.2.4.2

  if ((scan.component_mask & (1 << YCOMPONENT)) != 0)
  {
    // See if this is a color image.
    if (scan_component_count != 1)
    {
      // We have at least two components and the first is the Y component.
      // This means we need the both of the huffman tables.
      // B.2.4.2
      outputMarker (outputstream, DHT) ;
      unsigned int size = sizeof (UBYTE2) ;
      if (usedc)
      {
        size += dc_tables [0].outputSize ()
                + dc_tables [1].outputSize () ;
      }
      if (useac)
      {
        size += ac_tables [0].outputSize ()
                + ac_tables [1].outputSize () ;
      }
      outputstream.writeBigEndianWord (size) ;
      if (usedc)
      {
        outputstream.writeByte (0x00) ;
        dc_tables [0].printTable (outputstream) ;
      }
      if (useac)
      {
        outputstream.writeByte (0x10) ;
        ac_tables [0].printTable (outputstream) ;
      }
      if (usedc)
      {
        outputstream.writeByte (0x01) ;
        dc_tables [1].printTable (outputstream) ;
      }
      if (useac)
      {
        outputstream.writeByte (0x11) ;
        ac_tables [1].printTable (outputstream) ;
      }
    }
    else
    {
      // The only component is Y
      unsigned int size = sizeof (UBYTE2) ;
      if (usedc)
      {
        size += dc_tables [0].outputSize () ;
      }
      if (useac)
      {
        size += ac_tables [0].outputSize () ;
      }

      outputMarker (outputstream, DHT) ;
      outputstream.writeBigEndianWord (size) ;
      if (usedc)
      {
        outputstream.writeByte (0x00) ;
        dc_tables [0].printTable (outputstream) ;
      }
      if (useac)
      {
        outputstream.writeByte (0x10) ;
        ac_tables [0].printTable (outputstream) ;
      }
    }
  }
  else
  {
    // The Y component is not present. Output is the same for
    // Cb, Cr, or Cb & Cr.
    unsigned int size = sizeof (UBYTE2) ;
    if (usedc)
    {
      size += dc_tables [1].outputSize () ;
    }
    if (useac)
    {
      size += ac_tables [1].outputSize () ;
    }

    outputMarker (outputstream, DHT) ;
    outputstream.writeBigEndianWord (size) ;
    if (usedc)
    {
      outputstream.writeByte (0x01) ;
      dc_tables [1].printTable (outputstream) ;
    }
    if (useac)
    {
      outputstream.writeByte (0x11) ;
      ac_tables [1].printTable (outputstream) ;
    }
  }
  return ;
}

//
//  Description:
//
//   This function resets the DC difference values for all
//   all the components in the scan.  We do this at the start of
//   each scan and whenever we output a restart marker.
//
void JpegEncoder::resetDcValues ()
{
  for (unsigned int ii = 0 ; ii < scan_component_count ; ++ ii)
    scan_components [ii]->resetDcDifference () ;
  return ;
}

//
//  Description:
//
//    This function determines the dimensions of an MCU using the maximum
//    sampling frequencies of the components.
//
void JpegEncoder::calculateMcuDimensions ()
{
  max_horizontal_frequency = 1 ;
  max_vertical_frequency = 1 ;

  if (! gray_scale)
  {
    for (unsigned int ii = YCOMPONENT ; ii <= CRCOMPONENT ; ++ ii)
    {
      if (image_components [ii].getHorizontalFrequency ()
          > max_horizontal_frequency)
      {
        max_horizontal_frequency
          = image_components [ii].getHorizontalFrequency () ;
      }

      if (image_components [ii].getVerticalFrequency ()
          > max_vertical_frequency)
      {
        max_vertical_frequency
          = image_components [ii].getVerticalFrequency () ;
      }
    }
  }
  else
  {
    max_horizontal_frequency
      = image_components [YCOMPONENT].getHorizontalFrequency () ;
    max_vertical_frequency
      = image_components [YCOMPONENT].getVerticalFrequency () ;
  }

  unsigned int mcuheight = max_vertical_frequency * JPEGSAMPLEWIDTH ;
  unsigned int mcuwidth = max_horizontal_frequency * JPEGSAMPLEWIDTH ;
  mcu_rows = (frame_height + mcuheight - 1) / mcuheight ;
  mcu_cols = (frame_width + mcuwidth - 1) / mcuwidth ;
  return ;
}

//
//  Description:
//
//    This function writes a progressive scan to the output stream.
//
//  Parameters:
//    scan:  The structure that contains the scan parameters.
//
void JpegEncoder::printProgressiveScan (JpegOutputStream &outputstream,
                                        const Scan &scan)
{
  ASSERT (scan_component_count != 0) ; // No components in progressive scan

  if (scan.spectral_selection_start == 0)
  {
    if (scan.successive_approximation_high == 0)
    {
      printDcFirst (outputstream, scan) ;
    }
    else
    {
      printDcRefine (outputstream, scan) ;
    }
  }
  else
  {
    ASSERT (scan_component_count == 1) ; // AC Scan does not have 1 component

    if (scan.successive_approximation_high == 0)
    {
      printAcFirst (outputstream, scan) ;
    }
    else
    {
      printAcRefine (outputstream, scan) ;
    }
  }
  return ;
}

//
//  Description:
//
//    This function handles scans containing the first pass for DC
//    coefficients.  If successive approximation is not used then
//    this would be the only DC coefficient pass. DC progressive
//    scans may be interleaved, unlike AC scans.
//
//  Parameters:
//    scan:  The structure that contains the scan parameters.
//
void JpegEncoder::printDcFirst (JpegOutputStream &outputstream, const Scan &scan)
{
  // Reset the Huffman statistics counters.
  if ((scan.component_mask & (1 << YCOMPONENT)) != 0)
  {
    dc_tables [0].reset () ;
  }
  if ((scan.component_mask & (1 << YCOMPONENT)) == 0
       || scan_component_count > 1)
  {
    dc_tables [1].reset () ;
  }

  outputRestartInterval (outputstream, restart_interval) ;

  // Gather the Huffman statistics
  if (scan_component_count != 1)
  {
    interleavedPass (
          outputstream,
          false,
          &JpegEncoderComponent::progressiveDcFirst,
          &JpegEncoderComponent::gatherDcData, 0,
          0, 0,
          scan.successive_approximation_low) ;
  }
  else
  {
    noninterleavedPass (
          outputstream,
          false,
          &JpegEncoderComponent::progressiveDcFirst,
          &JpegEncoderComponent::gatherDcData, 0,
          0, 0,
          scan.successive_approximation_low) ;
  }

  // Create the Huffman tables from the statistics
  if ((scan.component_mask & (1 << YCOMPONENT)) != 0)
  {
    dc_tables [0].buildTable () ;
  }
  if ((scan.component_mask & (1 << YCOMPONENT)) == 0
      || scan_component_count > 1)
  {
    dc_tables [1].buildTable () ;
  }

  printHuffmanTables (outputstream, scan, true, false) ;

  // Output the scan header.
  // Section B.2.3
  outputMarker (outputstream, SOS) ;
  outputstream.writeBigEndianWord (6 + 2 * scan_component_count) ;  // Length
  outputstream.writeByte (scan_component_count) ;  // Component Count


  if ((scan.component_mask & (1 << YCOMPONENT)) != 0)
  {
    outputstream.writeByte (YCOMPONENT) ;
    outputstream.writeByte (0x00) ; // Entropy Tables
  }
  if (! gray_scale)
  {
    if ((scan.component_mask & (1 << CBCOMPONENT)) != 0)
    {
      outputstream.writeByte (CBCOMPONENT) ;
      outputstream.writeByte (0x11) ; // Entropy Tables
    }
    if ((scan.component_mask & (1 << CRCOMPONENT)) != 0)
    {
      outputstream.writeByte (CRCOMPONENT) ;
      outputstream.writeByte (0x11) ; // Entropy Tables
    }
  }

  outputstream.writeByte (0) ; // Spectral Selection Start
  outputstream.writeByte (0) ; // Spectral Selection End
  int value = (scan.successive_approximation_high << 4)
            | scan.successive_approximation_low ;
  outputstream.writeByte (value) ; // Successive Approximation

  // Output the scan data.
  outputstream.enterBitMode (CHAR_BIT) ;
  if (scan_component_count != 1)
  {
    interleavedPass (
          outputstream,
          true,
          &JpegEncoderComponent::progressiveDcFirst,
          &JpegEncoderComponent::printDcData, 0,
          0, 0,
          scan.successive_approximation_low) ;
  }
  else
  {
    noninterleavedPass (
          outputstream,
          true,
          &JpegEncoderComponent::progressiveDcFirst,
          &JpegEncoderComponent::printDcData, 0,

⌨️ 快捷键说明

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