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