📄 jpegdeco.cpp
字号:
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 + -