📄 jpgdecoder.~cpp
字号:
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)
{
resetDcDifferences () ;
processRestartMarker (inputstream) ;
restartcount = 0 ;
}
scan_components [0]->decodeAcRefine (inputstream,
row, col,
sss, sse,
ssa) ;
}
}
return ;
}
//
// 描述:
//
// 读顺序扫描的扫描数据. 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 (JpegInputStream &inputstream)
{
expected_restart = 0 ;
if (scanIsInterleaved ())
{
readSequentialInterleavedScan (inputstream) ;
}
else
{
readSequentialNonInterleavedScan (inputstream) ;
}
return ;
}
//
// 描述:
//
// 读交叉扫描数据.
//
void JpegDecoder::readSequentialInterleavedScan (JpegInputStream &inputstream)
{
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 (inputstream) ;
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 (
inputstream,
durow,
ducol) ;
}
}
}
}
}
return ;
}
//
// 描述:
//
// 读非交叉扫描数据
//
void JpegDecoder::readSequentialNonInterleavedScan (JpegInputStream &inputstream)
{
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 (inputstream) ;
restartcount = 0 ;
}
scan_components [0]->decodeSequential (inputstream, row, col) ;
}
}
return ;
}
//
// 描述:
//
// 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 ;
}
//
// 描述:
//
// 读一个重启动标志.
// 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 (JpegInputStream &inputstream)
{
inputstream.exitBitMode () ;
UBYTE1 data = inputstream.getByte () ;
if (data != 0xFF)
throw JpegBadStream ("Missing Restart Marker") ;
// According to E.1.2 0xFF can be used as a fill character
// before the marker.
while (data == 0xFF)
data = inputstream.getByte () ;
if (data < RST0 || data > RST7)
throw JpegBadStream ("Missing Restart Marker") ;
// Restart markers RST0..RST7 should come in sequence.
if ((0x0F & data) != expected_restart)
throw JpegBadStream ("Incorrect Restart Marker") ;
// Move the counter to the next restart marker
++ expected_restart ;
expected_restart %= 8 ;
// Reset the DC coefficent differences to zero.
resetDcDifferences () ;
inputstream.enterBitMode (CHAR_BIT) ;
return ;
}
//
// 描述:
//
// 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 (JpegInputStream &inputstream,
BitmapImage &image)
{
unsigned char data ;
current_scan = 0 ;
scan_count = 0 ;
current_image = &image ;
if (progress_function != 0)
getScanCount (inputstream) ;
restart_interval = 0 ; // Clear the restart interval ;
try
{
processing_image = true ;
current_image->clearImage () ;
eoi_found = false ;
sof_found = false ;
// Read the required SOI and APP0 markers at the start of the image.
readStreamHeader (inputstream) ;
data = inputstream.getByte () ;
while (inputstream.moreData () && ! eoi_found)
{
if (data == SOB)
{
readMarker (inputstream) ;
if (eoi_found)
break ;
}
data = inputstream.getByte () ;
if (! inputstream.moreData ())
throw JpegBadStream ("Premature end of file") ;
}
}
catch (GraphicsAbort)
{
freeAllocatedResources () ;
current_image = 0 ;
}
catch (...)
{
updateImage () ;
freeAllocatedResources () ;
current_image = 0 ;
processing_image = false ;
throw ;
}
updateImage () ;
processing_image = false ;
// Some people say we should not have this check here. If it bothers you
// remove it.
if (! eoi_found)
{
throw JpegBadStream("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.
inputstream.read ((char *) &data, sizeof (data)) ;
while ((data == '\r' || data == '\n') && inputstream.moreData ())
inputstream.read ((char *) &data, sizeof (data)) ;
if (inputstream.moreData ())
{
throw JpegBadStream ("Extra Data After End of Image Marker") ;
}
freeAllocatedResources () ;
current_image = 0 ;
return ;
}
//
// 描述:
// 扫描,统计扫描数目
// This function scans a stream and counts the number of scans. This
// allows an exact count for a progress function.
//
void JpegDecoder::getScanCount (JpegInputStream &inputstream)
{
// Save the stream position so we can go back
// when we are finished.
InputByteStream::POSITIONTYPE startpos = inputstream.tellg () ;
// Count the number of SOS markers.
scan_count = 0 ;
while (inputstream.moreData ())
{
UBYTE1 data = inputstream.getByte () ;
if (data == SOB)
{
while (data == SOB)
{
data = inputstream.getByte () ;
}
if (data == SOS)
++ scan_count ;
else if (data == EOI)
break ;
}
}
// Go back to where we were in the stream.
inputstream.seekg (startpos) ;
return ;
}
//
// 描述:
//
// 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 == 0)
throw JpegError ("Not reading an image") ;
if (current_scan > 0)
{
if (progressive_frame)
{
for (unsigned int ii = 0 ; ii < component_count ; ++ ii)
{
components [component_indices [ii]].progressiveInverseDct () ;
components [component_indices [ii]].upsampleImage (use_filters) ;
}
}
else
{
for (int ii = 0 ; ii < component_count ; ++ ii)
{
components [component_indices [ii]].upsampleImage (use_filters) ;
}
}
switch (component_count)
{
case 3:
JpegDecoderComponent::convertRgb (components [component_indices [0]],
components [component_indices [1]],
components [component_indices [2]],
*current_image) ;
break ;
case 1:
JpegDecoderComponent::convertGrayscale (
components [component_indices [0]],
*current_image) ;
break ;
}
}
return ;
}
//
// 描述:
//
// This function frees all the memory dynamically allocated
// during the image decoding process.
//
void JpegDecoder::freeAllocatedResources ()
{
if (current_scan > 0)
{
for (unsigned int ii = 0 ; ii < component_count ; ++ ii)
{
components [component_indices [ii]].freeComponentBuffers () ;
}
}
return ;
}
//
// Description:
//
// This function is only used in progressive images. It refines
// a non-zero AC coefficient. It is called at various times while
// processing a progressive scan that refines AC coefficients.
//
// Parameters:
// value: (in/out) The value to refine
// ssa: The succesive approximation for the scan.
// decoder: The JPEG decoder
//
void JpegDecoder::refineAcCoefficient (JpegInputStream &inputstream,
BYTE2 &value,
unsigned int ssa)
{
// Section G.1.2.3
if (value > 0)
{
if (inputstream.nextBit () != 0)
{
value += (1 << ssa) ;
}
}
else if (value < 0)
{
if (inputstream.nextBit () != 0)
{
value += (-1 << ssa) ;
}
}
return ;
}
void JpegDecoder::readImageFile (const std::string &filename, BitmapImage &image)
{
#if ! defined (USEMAP)
JpegInputFileStream inputstream ;
#else
JpegInputMapStream inputstream ;
#endif
const char *name = filename.c_str () ;
inputstream.open (name) ;
if (! inputstream)
throw JpegError ("Can't open input file") ;
try
{
readImage (inputstream, image) ;
}
catch (InputByteStream::StreamError &error)
{
// Convert input stream errors to JPEG errors.
throw JpegError (error.what ()) ;
}
return ;
}
bool JpegDecoder::isProgressive () const
{
return progressive_frame ;
}
unsigned int JpegDecoder::mcuRows () const
{
return mcu_rows ;
}
unsigned int JpegDecoder::mcuCols () const
{
return mcu_cols ;
}
unsigned int JpegDecoder::restartInterval () const
{
return restart_interval ;
}
unsigned int JpegDecoder::frameHeight () const
{
return frame_height ;
}
unsigned int JpegDecoder::frameWidth () const
{
return frame_width ;
}
unsigned int JpegDecoder::maxVFrequency () const
{
return max_vertical_frequency ;
}
unsigned int JpegDecoder::maxHFrequency () const
{
return max_horizontal_frequency ;
}
bool JpegDecoder::scanIsInterleaved () const
{
if (scan_component_count != 1)
return true ;
else
return false ;
}
bool JpegDecoder::getVerbose () const
{
return verbose_flag ;
}
void JpegDecoder::setVerbose (bool value)
{
verbose_flag = value ;
return ;
}
bool JpegDecoder::getUseFilters () const
{
return use_filters ;
}
void JpegDecoder::setUseFilters (bool value)
{
use_filters = value ;
return ;
}
} // End Namespace Colosseum
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -