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

📄 jpegdeco.cpp

📁 超强jpeg解码程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  unsigned int remaining = length - sizeof (length) ;
  while (remaining > 0)
  {
    UBYTE1 data = ReadByte () ; -- remaining ;

    // Tc in standard 0=>DC, 1=>AC
    unsigned int tableclass = data >> 4 ; 
    unsigned int id = data & 0x0F ; // Th in standard
    if (id > 3)
    {
      throw EJpegBadData (
        "Huffman Table Index outside range [0..3]") ;
    }
    if (verbose_flag)
    {
      cout << "   Table Index " << (int) id << endl ;
      if (tableclass == 0)
        cout << "   Table Class: DC" << endl ;
      else
        cout << "   Table Class: AC" << endl ;
    }
    if (id > 3)
    {
      cout << "Bad index " << id << endl ;
      return ;
    }

    JpegHuffmanDecoder *table ;
    if (tableclass != 0)
      table = &ac_tables [id] ;
    else
       table = &dc_tables [id] ;

    // Read the table data into the table object
    remaining -= table->ReadTable (*this) ;

    if (verbose_flag)
    {
      table->Dump (cout) ;
    }
  }

  if (verbose_flag)
    cout << "}" << endl ;
  return ;
}

//
//  Description:
//
//    This function reads a DQT marker from the input stream.
//
void JpegDecoder::ReadQuantization ()
{
  // Defined in Section B.2.4.1

  UBYTE2 length = ReadWord () ;
  UBYTE1 data ;

  // Maintain a counter for the number of bytes remaining to be read in
  // the quantization table.
  int remaining = length - sizeof (length) ;

  if (verbose_flag)
  {
    cout << "{ Define Quantization Table" << endl ;
    cout << "  Length: " << length << endl ;
  }
  while (remaining > 0)
  {
    data = ReadByte () ; -- remaining ;
    unsigned int precision = data >> 4 ;    // Pq in standard
    unsigned int index = data & 0x0F ;      // Tq in standard

    if (index >= MaxQuantizationTables)
      throw EJpegBadData ("Quantization Table Index Too Large") ;

    if (verbose_flag)
    {
      cout << "  Table Index: " << dec << index << endl ;
      cout << "  Table Precision: " << dec << precision << endl ;
    }

    switch (precision)
    {
    case 1:
      remaining -= sizeof(UBYTE2) * JpegSampleSize ;
      break ;
    case 0:
      remaining -= sizeof (UBYTE1) * JpegSampleSize ;
      break ;
    }

    // Read the table data into the table object
    quantization_tables [index].ReadTable (*this, precision) ;

    if (verbose_flag)
    {
      cout << "  Table Values: " ;
      quantization_tables [index].Print (cout) ;
      cout << endl << "}" << endl ;
    }
  }
  return ;
}

//
//  Description:
//
//    This function reads a define restart interval marker
//    from the input stream.
//
void JpegDecoder::ReadRestartInterval ()
{
  // Section B.2.4.4

  UBYTE2 length = ReadWord () ;
  restart_interval = ReadWord () ;
  if (verbose_flag)
  {
    cout << "{ Define Restart Interval" << endl ;
    cout << "  Length:  " << dec << length << endl ; // Should be 4
    cout << "  Interval: " << dec << restart_interval << endl ;
    cout << "}" << endl ;
   }
   return ;
}

//
//  Description:
//
//    The function reads a start of frame marker from the input stream.
//
//  Parameters:
//    type:  The marker type for the frame
//
void JpegDecoder::ReadStartOfFrame (UBYTE1 type)
{
  // Section B.2.2
  // Read in the image dimensions
  unsigned int length = ReadWord () ;
  unsigned int dataprecision = ReadByte () ;  // P in standard
  if (dataprecision != 8)
    throw EJpegBadData ("Only 8-bit data supported") ;

  frame_height = ReadWord () ;            // Y in standard
  frame_width = ReadWord () ;             // X in standard
  component_count = ReadByte () ;   // Nf in standard

  // JFIF only allows 1 or 3 components.
  if (component_count != 1 && component_count != 3)
    throw EJpegBadData ("JFIF only supports 1 and 3 component streams") ;

  frame_type = type ;

  if (verbose_flag)
  {
    cout << "{ Start Of Frame " << endl ;
    cout << "  Length: " << dec << length << endl ;
    cout << "  Precision: " << dec << dataprecision << endl ;
    cout << "  Height: " << dec << frame_height << endl ;
    cout << "  Width: " << dec << frame_width << endl ;
    cout << "  Component Count: " << component_count << endl ;
  }

  if (length != (component_count * 3 + 8))
    throw EJpegBadData ("Invalid Frame Size") ;

  // Rread the component descriptions
  max_horizontal_frequency = 0 ;
  max_vertical_frequency = 0 ;
  for (unsigned int ii = 0 ; ii < component_count ; ++ ii)
  {
    unsigned int ID = ReadByte () ;  // Ci in standard
    unsigned int qtable ;

    // While JPEG does not put these restrictions on component IDs
    // the JFIF standard does.
    if (strict_jfif)
    {
    if (component_count == 1 && ID != 1)
      throw EJpegBadData ("Component ID not 1") ;
    else if (ID != ii + 1)
      throw EJpegBadData ("Invalid Component ID or ID out of order") ;
    }
    
    component_indices [ii] = ID ;

    UBYTE1 data = ReadByte () ;
    components [ID].HorizontalFrequency (data >> 4) ; // Hi in standard
    components [ID].VerticalFrequency (data & 0xF) ;  // Vi in standard
    qtable= ReadByte () ;  // Tqi in standard
    if (qtable >= MaxQuantizationTables)
      throw EJpegBadData ("Bad Quantization Table Index") ;
    components [ID].SetQuantizationTable (quantization_tables [qtable]) ;

    // Keep track of the largest values for horizontal and vertical
    // frequency.
    if (components [ID].HorizontalFrequency ()
        > max_horizontal_frequency)
    {
      max_horizontal_frequency =
        components [ID].HorizontalFrequency () ;
    }

    if (components [ID].VerticalFrequency ()
          > max_vertical_frequency)
    {
      max_vertical_frequency =
        components [ID].VerticalFrequency () ;
    }

    if (verbose_flag)
    {
      cout << "   Component " << ID << endl ;
      cout << "   Horizontal Frequency: "
           << components [ID].HorizontalFrequency () << endl ;
      cout << "   Vertical Frequency: "
           << components [ID].VerticalFrequency () << endl ;
      cout << "   Quantization Table: "
           << qtable << endl ;
    }
  }

  CalculateMcuDimensions () ;

  // Allocate storage for the image.
  if (component_count == 1)
  {
    current_image->SetSize (1 << 8, 8, frame_width, frame_height) ;
    // For a grey scale image we need to create the color map. Each color
    // has equal amounts of red, green, and blue.
    for (unsigned int ii = 0 ; ii < (1 << 8) ; ++ ii)
    {
      current_image->ColorMap (ii).red = (UBYTE1) ii ;
      current_image->ColorMap (ii).green = (UBYTE1) ii ;
      current_image->ColorMap (ii).blue = (UBYTE1) ii ;
    }
  }
  else
  {
    current_image->SetSize (0,     // Color Table Entries
                            8 * component_count,  // Bits
                            frame_width,
                            frame_height) ;

  }

  if (verbose_flag)
    cout << "}" << endl ;

  sof_found = true ;
  return ;
}

//
//  Description:
//
//    This function reads a start of scan marker and the scan data
//    following the marker.
//
void JpegDecoder::ReadStartOfScan ()
{
  unsigned int ii ;

  if (! sof_found)
    throw EJpegBadData ("Scan found before frame defined") ;

  // Section B.2.3

  UBYTE2 length = ReadWord () ;
  if (verbose_flag)
  {
    cout << "{ Start Of Scan " << endl ;
    cout << "  Length:  " << dec << length << endl ;
  }

  scan_component_count = ReadByte () ;  // Ns in standard
  // Right now we can only handle up to three components.
  if (scan_component_count > 3 || scan_component_count < 1)
    throw EJpegBadData ("Invalid component count in scan") ;

  for (ii = 0 ; ii < scan_component_count ; ++ ii)
  {
    UBYTE1 componentID = ReadByte () ;  // Csi in standard

    scan_components [ii] = &components [componentID] ;
    // If the horizontal frequency is zero then the component was not
    // defined in the SOFx marker.
    if (scan_components [ii]->HorizontalFrequency () == 0)
      throw EJpegBadData ("Component Not Defined") ;

    UBYTE1 rb = ReadByte () ;
    unsigned int actable = rb & 0x0F ;
    unsigned int dctable = rb >> 4 ;

    scan_components [ii]->SetHuffmanTables (
                              dc_tables [dctable],
                              ac_tables [actable]) ;
    if (verbose_flag)
    {
      cout << "  Component ID: "
           << dec << (unsigned int) componentID << endl ;
      cout << "  DC Entropy Table: "
           << dec << dctable << endl  ;
      cout << "  AC Entropy Table: "
           << dec << actable << endl  ;
    }
  }

  unsigned int spectralselectionstart = ReadByte () ; // Ss in standard
  unsigned int spectralselectionend = ReadByte ()  ;  // Se in standard

  UBYTE1 ssa = ReadByte () ;
  unsigned int successiveapproximationhigh = ssa >> 4 ;  // Ah in standard
  unsigned int successiveapproximationlow = ssa & 0x0F ; // Al in standard

  if (verbose_flag)
  {
    cout << " Spectral Selection Start: "
         << dec << (unsigned int) spectralselectionstart << endl ;
    cout << " Spectral Selection End: "
         << dec << (unsigned int) spectralselectionend << endl ;
    cout << " Successive Approximation High: "
         << dec << successiveapproximationhigh << endl ;
    cout << " Successive Approximation Low: "
         << dec << successiveapproximationlow << endl  ;
    cout << "}" << endl ;
  }

  for (ii = 0 ; ii < scan_component_count ; ++ ii)
  {
    scan_components [ii]->CheckQuantizationTable () ;
    scan_components [ii]->CheckDcTable () ;
    scan_components [ii]->CheckAcTable () ;
    scan_components [ii]->AllocateComponentBuffers (*this) ;

  }

  ++ current_scan ;
  ReadSequentialScanData () ;

  CallProgressFunction (100) ;
  return ;
}

//
//  Description:
//
//    This function determines for non-interlaced scans:
//
//     o The dimensions in pixels for an MCU
//     o The number of MCU rows and columns needed to encode the scan.
//
void JpegDecoder::CalculateMcuDimensions ()
{
  mcu_height = max_vertical_frequency * JpegSampleWidth ;
  mcu_width = max_horizontal_frequency * JpegSampleWidth ;
  mcu_rows = (frame_height + mcu_height - 1) / mcu_height ;
  mcu_cols = (frame_width + mcu_width - 1) / mcu_width ;
  return ;
}

//
//  Dimensions:
//
//    This function calls the progress function if it has
//    been supplied by the user.
//
//  Parameters:
//    progress: The progress percentage.
//
void JpegDecoder::CallProgressFunction (unsigned int progress)
{
  if (progress_function == NULL)
    return ;

  bool abort = false ;
  unsigned int percent = progress ;
  if (percent > 100)
    percent = 100 ;
  if (progress_function != NULL)
  {
    progress_function (*this,
                       progress_data,
                       current_scan,
                       scan_count,
                       percent,
                       abort) ;
  }

  if (abort)

⌨️ 快捷键说明

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