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

📄 jpegdeco.cpp

📁 超强jpeg解码程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    throw EJpegAbort () ;
  return ;
}


//
//  Parameters:
//
//    The function reads the scan data for a sequential scan. All
//    we do here is determine whether or not we have an interleaved
//    or non-interleaved scan then call a function that handles
//    the scan type.

void JpegDecoder::ReadSequentialScanData ()
{
  expected_restart = 0 ;
  if (ScanIsInterleaved ())
  {
    ReadSequentialInterleavedScan () ;
  }
  else
  {
    ReadSequentialNonInterleavedScan () ;
  }
  return ;
}

//
//  Description:
//
//    This function reads the scan data for an interleaved scan.
//

void JpegDecoder::ReadSequentialInterleavedScan ()
{
  ResetDcDifferences () ;

  unsigned int restartcount = 0 ;
  for (unsigned int mcurow = 0 ; mcurow < mcu_rows ; ++ mcurow)
  {
    CallProgressFunction (mcurow * 100 / mcu_rows) ;
    for (unsigned int mcucol = 0 ; mcucol < mcu_cols ;
         ++ mcucol, ++restartcount)
    {
      if (restart_interval != 0 && restart_interval == restartcount)
      {
        ProcessRestartMarker () ;
        restartcount = 0 ;
      }
      for (unsigned int cc = 0 ; cc < scan_component_count ; ++ cc)
      {
        for (unsigned int cy = 0 ;
             cy < scan_components [cc]->VerticalFrequency () ;
             ++ cy)
        {
          unsigned int durow = scan_components [cc]->VerticalFrequency ()
                               * mcurow + cy ;
          for (unsigned int cx = 0 ;
               cx < scan_components [cc]->HorizontalFrequency () ;
               ++ cx)
          {
            unsigned int ducol =
                   scan_components [cc]->HorizontalFrequency ()
                   * mcucol + cx ;

            scan_components [cc]->DecodeSequential (
                                      *this,
                                      durow,
                                      ducol) ;
          }
        }
      }
    }
  }
  return ;
}

//
//  Description:
//
//    This function reads the scan data for a non-interleaved scan.
//

void JpegDecoder::ReadSequentialNonInterleavedScan ()
{
  ResetDcDifferences () ;

  unsigned int restartcount = 0 ;
  for (unsigned int row = 0 ;
       row < scan_components [0]->NoninterleavedRows () ;
       ++ row)
  {
    CallProgressFunction (row * 100 / scan_components [0]->NoninterleavedRows ()) ;
    for (unsigned int col = 0 ;
         col < scan_components [0]->NoninterleavedCols () ;
         ++ col, ++ restartcount)
    {
      if (restart_interval != 0
          && restart_interval == restartcount)
      {
        ProcessRestartMarker () ;
        restartcount = 0 ;
      }
      scan_components [0]->DecodeSequential (*this, row, col) ;
    }
  }
  return ;
}

//
//  Description:
//
//    This function resets the DC difference values for all components
//    for the current scan.
//
//    This function gets called before each scan is processed and
//    whenever a restart marker is read.
//

void JpegDecoder::ResetDcDifferences ()
{
  for (unsigned int ii = 0 ; ii < scan_component_count ; ++ ii)
    scan_components [ii]->ResetDcDifference () ;
  return ;
}

//
//  Description:
//
//    This function reads a restart marker from the input stream.
//    It gets called byte functions that read scan data whenever
//    a restart marker is expected. An exception is raise if the
//    correct restart marker is not next in the input stream.
//
void JpegDecoder::ProcessRestartMarker ()
{
  UBYTE1 data = ReadByte () ;
  if (data != 0xFF)
    throw EJpegBadData ("Missing Restart Marker") ;
  // According to E.1.2 0xFF can be used as a fill character
  // before the marker.
  while (data == 0xFF)
    data = ReadByte () ;
  if (data < RST0 || data > RST7)
    throw EJpegBadData ("Missing Restart Marker") ;

  // Restart markers RST0..RST7 should come in sequence.
  if ((0x0F & data) != expected_restart)
    throw EJpegBadData ("Incorrect Restart Marker") ;

  // Move the counter to the next restart marker
  ++ expected_restart ;
  expected_restart %= 8 ;

  // Reset the DC coefficent differences to zero.
  ResetDcDifferences () ;
  return ;
}

//
//  Description:
//
//    This function reads an image from a JPEG stream. The
//    stream needs to have been opened in binary mode.
//
//  Parameters:
//    istrm: Input stream
//    image: The output image
//

void JpegDecoder::ReadImage (std::istream &istrm,
                             BitmapImage &image)
{
  unsigned char data ;

  current_scan = 0 ;
  scan_count = 0 ;
  input_stream = &istrm ;
  current_image = &image ;

  if (progress_function != NULL)
    GetScanCount () ;

  restart_interval = 0 ;  // Clear the restart interval ;
  try
  {
    current_image->Clear () ;
    eoi_found = false ;
    sof_found = false ;

    // Read the required SOI and APP0 markers at the start of the image.
    ReadStreamHeader () ;

    data = ReadByte () ;
    while (! input_stream->eof () && ! eoi_found)
    {
      if (data == SOB)
      {
        ReadMarker () ;
        if (eoi_found)
          break ;
      }
      data = ReadByte () ;
      if (input_stream->eof ())
        throw EJpegBadData ("Premature end of file") ;
    }
  }
  catch (EJpegAbort)
  {
    FreeAllocatedResources () ;
    current_image = NULL ;
  }
  catch (...)
  {
    UpdateImage () ;
    FreeAllocatedResources () ;
    current_image = NULL ;
    throw ;
  }
  UpdateImage () ;

  if (! eoi_found)
  {
    throw EJpegBadData("End of Image Marker Not Found") ;
  }
  // We do no want an exception so do not call ReadByte ()
  // Sometimes there can be trailing end of record markers.
  input_stream->read ((char *) &data, sizeof (data)) ;
  while ((data == '\r' || data == '\n') && ! input_stream->eof ())
    input_stream->read ((char *) &data, sizeof (data)) ;
  if (! input_stream->eof ())
  {
    throw EJpegBadData ("Extra Data After End of Image Marker") ;
  }

  FreeAllocatedResources () ;
  current_image = NULL ;
  return ;
}

//
//  Description:
//
//    This function scans a stream and counts the number of scans.  This
//    allows an exact count for a progress function.
//
void JpegDecoder::GetScanCount ()
{
  // Save the stream position so we can go back
  // when we are finished.
  long startpos = input_stream->tellg () ;

  // Count the number of SOS markers.
  scan_count = 0 ;
  while (! input_stream->eof ())
  {
    UBYTE1 data ;
    input_stream->read ((char *) &data, 1) ;
    if (data == SOB)
    {
      while (data == SOB)
      {
        input_stream->read ((char *) &data, 1) ;
      }
      if (data == SOS)
        ++ scan_count ;
      else if (data == EOI)
        break ;
    }
  }
  // Go back to where we were in the stream.
  input_stream->seekg (startpos) ;
  input_stream->clear () ;  // Clear the EOF flag.
  return ;
}

//
//  Description:
//
//    This function writes the image data that has been read so
//    far to the image. This function gets called after reading
//    the entire image stream.  The user can also call this function
//    from a progress function to display progressive images,
//    multi-scan sequential images, or just to display the image
//    as it is being read (slow).
//

void JpegDecoder::UpdateImage ()
{
  if (current_image == NULL)
    throw EJpegError ("Not reading an image") ;

  for (int ii = 0 ; ii < component_count ; ++ ii)
  {
    components [component_indices [ii]].Upsample () ;
  }

  switch (component_count)
  {
  case 3:
    JpegDecoderComponent::RGBConvert (components [component_indices [0]],
                                      components [component_indices [1]],
                                      components [component_indices [2]],
                                      *current_image) ;
    break ;
  case 1:
    JpegDecoderComponent::GrayscaleConvert (
                             components [component_indices [0]],
                             *current_image) ;
    break ;
  }
  return ;
}

//
//  Description:
//
//    This function frees all the memory dynamically allocated
//    during the image decoding process.  
//
void JpegDecoder::FreeAllocatedResources ()
{
  for (unsigned int ii = 0 ; ii < component_count ; ++ ii)
  {
    components [component_indices [ii]].FreeComponentBuffers () ;
  }
  return ;
}


//
//  Description:
//
//    This function returns the next raw bit in the input stream.
//
//    Bits are read from high order to low.
//
//  Return Value:
//
//    The next bit (0, 1)
//

// This function returns the next bit in the input stream.
int JpegDecoder::NextBit ()
{
  // Section F.2.2.5 Figure F.18.
  // CNT is called bitposition
  // B is called bitdata
  if (bit_position == 0)
  {
    // We are out of data so read the next byte from the input stream.
    input_stream->read ((char *) &bit_data, sizeof (bit_data)) ;
    if (input_stream->eof ())
      throw EJpegBadData ("Premature end of file") ;
    // Reset the bit read position starting with the highest order bit. We
    // read high to low.
    bit_position = CHAR_BIT * sizeof (bit_data) ;

    if (bit_data == 0xFF)
    {
      // 0xFF could start a marker. The sequence 0xFF, 0x00 is used to
      // to represent the value 0xFF. The only other marker that is legal
      // at this point is a DNL marker.
      UBYTE1 b2 ;
      input_stream->read ((char *) &b2, 1) ;
      if (input_stream->eof ())
        throw EJpegBadData ("Premature end of file") ;
      if (b2 != 0)
      {
        if (b2 == DNL)
        {
          // DNL markers should not occur within the supported frame types.
          throw EJpegBadData ("Unexpected Marker DNL") ;
        }
        else
        {
          throw EJpegBadData ("Unexpected Marker") ;
        }
      }
    }
  }

  // Consume one bit of the input.
  -- bit_position ;
  // Shift the value to the low order bit position.
  UBYTE1 result = (UBYTE1) ((bit_data >> bit_position) & 1) ;
  return result ;
}

⌨️ 快捷键说明

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