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

📄 jpgencoder.~cpp

📁 Jpeg编解码器的源代码
💻 ~CPP
📖 第 1 页 / 共 5 页
字号:
                                      max_vertical_frequency,
                                      image_components [YCOMPONENT], 
                                      image_components [CBCOMPONENT], 
                                      image_components [CRCOMPONENT]) ;
    ++ current_pass ;
    image_components [YCOMPONENT].sampleComponent (*this,
                                                    max_horizontal_frequency,
                                                    max_vertical_frequency) ;
    ++ current_pass ;
    image_components [CBCOMPONENT].sampleComponent (*this,
                                                    max_horizontal_frequency,
                                                    max_vertical_frequency) ;
    ++ current_pass ;
    image_components [CRCOMPONENT].sampleComponent (*this,
                                                    max_horizontal_frequency,
                                                    max_vertical_frequency) ;

    // Output JPEG SOS Marker
    // Section B.2.2
    outputMarker (outputstream, SOF2) ;
    outputstream.writeBigEndianWord (8 + 3 * 3) ;

    outputstream.writeByte (8) ; // Precision
    outputstream.writeBigEndianWord (image.getHeight ()) ;
    outputstream.writeBigEndianWord (image.getWidth ()) ;

    outputstream.writeByte (3) ;  // Component Count
    outputstream.writeByte(YCOMPONENT) ;
    outputstream.writeByte (
        (image_components [YCOMPONENT].getHorizontalFrequency () << 4)
        | image_components [YCOMPONENT].getVerticalFrequency ()) ;
    outputstream.writeByte (quantization_table_assignments [YCOMPONENT]) ;

    outputstream.writeByte(CBCOMPONENT) ;
    outputstream.writeByte (
        (image_components [CBCOMPONENT].getHorizontalFrequency () << 4)
         | image_components [CBCOMPONENT].getVerticalFrequency ()) ;
    outputstream.writeByte (quantization_table_assignments [CBCOMPONENT]) ;  // Quantization Table

    outputstream.writeByte(CRCOMPONENT) ;
    outputstream.writeByte (
        (image_components [CRCOMPONENT].getHorizontalFrequency () << 4)
         | image_components [CRCOMPONENT].getVerticalFrequency ()) ;
    outputstream.writeByte (quantization_table_assignments [CRCOMPONENT]) ;  // Quantization Table

    printQuantizationTables (outputstream) ;

    // Because of successive approximation we may have to go through the
    // scan list several times. This flag gets set each time a scan
    // is processed. The first time we search the scan list and do
    // nothing this flag will be false and we are all done.
    bool doingwork ;
    do
    {
      doingwork = false ;
      for (unsigned int ii = 0 ; ii < scan_count ; ++ ii)
      {
        findComponentsInScan (image_scans [ii]) ;

        if (scan_component_count != 0
            && image_scans [ii].successive_approximation_low >= 0)
        {
          ++ current_pass ;
          printProgressiveScan (outputstream, image_scans [ii]) ;
          doingwork = true ;
          image_scans [ii].successive_approximation_high
            = image_scans [ii].successive_approximation_low ;
          -- image_scans [ii].successive_approximation_low ;
        }
      }
    } while (doingwork) ;

  }
  return ;
}


//
//  Description:
//
//    This function enables or disables progressive output. When the mode is
//    changed the image_scans is initialized with a default set of values for
//    the new mode.
//
//  Parameters:
//    value: (true=>Progressive Mode, false=>Sequential Mode)
//
void JpegEncoder::setProgressive (bool value)
{
  if (value == progressive_mode)
    return ;

  progressive_mode = value ;
  memset (image_scans, 0, sizeof (image_scans)) ;
  if (progressive_mode)
  {
    // For Progressive Scans our default is four scans.  The first
    // contains the DC coefficients for all three components. The next
    // three scans contain the AC coefficients for each component.

    image_scans [0].component_mask = (1<<YCOMPONENT)
                                    |(1<<CBCOMPONENT)
                                    |(1<<CRCOMPONENT) ;
    image_scans [1].component_mask = (1<<YCOMPONENT) ;
    image_scans [1].spectral_selection_end = 63 ;
    image_scans [2].component_mask = (1<<CBCOMPONENT) ;
    image_scans [2].spectral_selection_end = 63 ;
    image_scans [3].component_mask = (1<<CRCOMPONENT) ;
    image_scans [3].spectral_selection_end = 63 ;
  }
  else
  {
    // For sequential mode the default is to create one scan with
    // all components.
    image_scans [0].component_mask = (1<<YCOMPONENT)
                                   |(1<<CBCOMPONENT)
                                   |(1<<CRCOMPONENT) ;
  }
  return ;
}

//
//  Description:
//
//    This function writes a sequential scan to the output stream.
//
//  Parameters:
//    scan:   The scan descriptor
//
void JpegEncoder::printSequentialScan (JpegOutputStream &outputstream,
                                       const Scan &scan)
{
  ASSERT (scan_component_count != 0) ; // No components defined for scan 

  // Output the restart interval and the Huffman tables. We must set the
  // restart interval *BEFORE* gathering statistics.
  if (scan_component_count != 1)
  {
    outputRestartInterval (outputstream, rows_per_restart * mcu_cols) ;
  }
  else
  {
    outputRestartInterval (outputstream,
                           rows_per_restart * scan_components [0]->dataUnitCols ()) ;
  }

  // Gather Huffman Statistics
  if ((scan.component_mask & (1<<YCOMPONENT)) != 0)
  {
    dc_tables [0].reset () ;
    ac_tables [0].reset () ;
  }
  if ((scan.component_mask & (1<<YCOMPONENT)) == 0
      || scan_component_count != 1)
  {
    ac_tables [1].reset () ;
    dc_tables [1].reset () ;
  }


  if (scan_component_count != 1)
  {
    interleavedPass (
          outputstream,
          false,
          &JpegEncoderComponent::encodeSequential,
          &JpegEncoderComponent::gatherDcData,
          &JpegEncoderComponent::gatherAcData,
          0, JPEGSAMPLESIZE - 1, 0) ;
  }
  else
  {
    noninterleavedPass (
          outputstream,
          false,
          &JpegEncoderComponent::encodeSequential,
          &JpegEncoderComponent::gatherDcData,
          &JpegEncoderComponent::gatherAcData,
          0, JPEGSAMPLESIZE - 1, 0) ;
  }

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

  // Output the Huffman tables
  printHuffmanTables (outputstream, scan, true, true) ; // Output DC and AC tables.

  // Create the scan marker.
  // 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 (0x01) ; // YCOMPONENT
    outputstream.writeByte (0x00) ; // Entropy Tables
  }
  if (! gray_scale)
  {
    if ((scan.component_mask & (1<<CBCOMPONENT)) != 0)
    {
      outputstream.writeByte (0x02) ; // CBCOMPONENT
      outputstream.writeByte (0x11) ; // Entropy Tables
    }
    if ((scan.component_mask & (1<<CRCOMPONENT)) != 0)
    {
      outputstream.writeByte (0x03) ; // CRCOMPONENT
      outputstream.writeByte (0x11) ; // Entropy Tables
    }
  }

  outputstream.writeByte (0) ; // Spectral Selection Start
  outputstream.writeByte (JPEGSAMPLESIZE - 1) ; // Spectral Selection End
  outputstream.writeByte (0) ; // Successive Approximation

  // Output the Scan data.
  outputstream.enterBitMode (CHAR_BIT) ;
  if (scan_component_count != 1)
  {
    interleavedPass (
          outputstream,
          true,
          &JpegEncoderComponent::encodeSequential,
          &JpegEncoderComponent::printDcData,
          &JpegEncoderComponent::printAcData,
          0, JPEGSAMPLESIZE - 1, 0) ;
  }
  else
  {
    noninterleavedPass (
          outputstream,
          true,
          &JpegEncoderComponent::encodeSequential,
          &JpegEncoderComponent::printDcData,
          &JpegEncoderComponent::printAcData,
          0, JPEGSAMPLESIZE - 1, 0) ;
  }
  outputstream.exitBitMode () ;
  return ;
}

//
//  Description:
//
//    This function makes a pass through the data units for a non-interleaved
//    Scan.
//
//    The reason for having a generic function that uses pointers to member
//    functions to do processing is that there are several places where the
//    control processing has to be identical in multiple passes where the
//    low level actions are different. For example, the processing here when
//    gathering Huffman statistics has to be identical to the processing when
//    writing values to the output file. Using separate functions turned out
//    to be error prone due to the difficulty of keeping multiple functions
//    exactly in synchronization.
//
//  Parameters:
//    writerestarts: false => This is a statistics gathering pass
//                   true => This pass is writing data to the output file.
//    passfunctions: Pointer to EncoderComponent member function used
//                   to process this pass.
//    dcfunction:    Pointer to the EncoderComponent member function used
//                   to process DC coefficient values.
//    acfunction:    Pointer to the EncoderComponent member function used
//                   to process AC coefficient values.
//    sss:           Spectral Selection Start (0-63)
//    sse:           Spectral Selection End (0-63)
//    ssa:           Successive Approximation (0-13)
//
void JpegEncoder::noninterleavedPass (
                    JpegOutputStream &outputstream,
                    bool writedata,
                    JpegEncoderComponent::COMPONENTPASSFUNCTION passfunction,
                    JpegEncoderComponent::DCOUTPUTFUNCTION dcfunction,
                    JpegEncoderComponent::ACOUTPUTFUNCTION acfunction,
                    unsigned int sss,
                    unsigned int sse,
                    unsigned int ssa)
{
  // We use a scale integer to keep trake of progress to lessen the
  // change that the progress increment will be zero.
  const int progressscale = 8 ;
  unsigned int progress ;
  unsigned int progressincrement ;
  if (writedata)
    progress = 50 << progressscale ;
  else
    progress = 0 ;
  progressincrement = (100 << progressscale)
                    / (2 * scan_components [0]->dataUnitRows ()) ;

  resetDcValues () ;

  unsigned int intervalcount = 0 ;
  unsigned int restartmarker = 0 ;
  for (unsigned int row = 0 ;
       row < scan_components [0]->noninterleavedDuRows () ;
       ++ row)
  {
    for (unsigned int col = 0 ;
         col < scan_components [0]->noninterleavedDuColumns () ;
         ++ col, ++ intervalcount)
    {
      if (restart_interval != 0)
      {
        if (intervalcount == restart_interval && restart_interval != 0)
        {
          // If there are any outstanding EOB runs we flush them before the
          // restart marker. This is not explicitly stated in the JPEG
          // standard. The definition of "Restart Interval" in section 4.1
          // states that restart markers separate independent sequences,
          // something we would not have if we did not output the EOB run
          // here.
          scan_components [0]->printEobRun (acfunction) ;
          // E.1.4
          if (writedata)
            outputRestartMarker (outputstream, restartmarker) ;
          resetDcValues () ;
          ++ restartmarker ;
          restartmarker %= 8 ;
          intervalcount = 0 ;
        }
      }
      (scan_components [0]->*passfunction) (
                                row,
                                col,
                                dcfunction,
                                acfunction,
                                sss, sse,
                                ssa) ;

    }
    progress += progressincrement ;
    callProgressFunction (progress >> progressscale) ;
  }
  if (writedata)
    callProgressFunction (100) ;
  else
    callProgressFunction (50) ;
  return ;
}

//
//  Description:
//
//    This function makes a pass through the data units for an interleaved
//    Scan.
//
//    The reason for having a generic function that uses pointers to member
//    functions to do processing is that there are several places where the
//    control processing has to be identical in multiple passes where the
//    low level actions are different. For example, the processing here when
//    gathering Huffman statistics has to be identical to the processing when
//    writing values to the output file. Using separate functions turned out
//    to be error prone due to the difficulty of keeping multiple functions
//    exactly in synchronization.
//
//  Parameters:
//     writerestarts: false => This is a statistics gathering pass
//                    true => This pass is writing data to the output file.
//     passfunctions: Pointer to EncoderComponent member function used
//                    to process this pass.
//     dcfunction:    Pointer to the EncoderComponent member function used
//                    to process DC coefficient values.
//     acfunction:    Pointer to the EncoderComponent member function used
//                    to process AC coefficient values.
//     sss:           Spectral Selection Start (0-63)
//     sse:           Spectral Selection End (0-63)
//     ssa:           Successive Approximation (0-13)
//
void JpegEncoder::interleavedPass (
                    JpegOutputStream &outputstream,
                    bool writedata,
                    JpegEncoderComponent::COMPONENTPASSFUNCTION passfunction,
                    JpegEncoderComponent::DCOUTPUTFUNCTION dcfunction,
                    JpegEncoderComponent::ACOUTPUTFUNCTION acfunction,
                    unsigned int sss,
                    unsigned int sse,
                    unsigned int ssa)
{
  const int progressscale = 8 ;
  unsigned int progress ;
  unsigned int progressincrement ;
  if (writedata)
    progress = 50 << progressscale ;
  else
    progress = 0 ;
  progressincrement = (100 << progressscale) / (2 * mcu_rows) ;

⌨️ 快捷键说明

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