📄 jpgencoder.~cpp
字号:
0, 0,
scan.successive_approximation_low) ;
}
outputstream.exitBitMode () ;
return ;
}
//
// Description:
//
// This function outputs the data for a refining DC scan. This type of
// scan is unique in that it does use Huffman encoding.
//
//
// Parameters:
// scan: The structure that contains the scan parameters.
//
void JpegEncoder::printDcRefine (JpegOutputStream &outputstream, const Scan &scan)
{
// Output the scan header.
// Section B.2.3
outputMarker (outputstream, SOS) ;
outputstream.writeBigEndianWord (6 + 2 * scan_component_count) ; // Length
outputstream.writeByte (scan_component_count) ;
if ((scan.component_mask & (1 << YCOMPONENT)) != 0)
{
outputstream.writeByte (YCOMPONENT) ;
outputstream.writeByte (0) ; // No Huffman table is used.
}
if (! gray_scale)
{
if ((scan.component_mask & (1 << CBCOMPONENT)) != 0)
{
outputstream.writeByte (CBCOMPONENT) ;
outputstream.writeByte (0) ; // No Huffman table is used.
}
if ((scan.component_mask & (1 << CRCOMPONENT)) != 0)
{
outputstream.writeByte (CRCOMPONENT) ;
outputstream.writeByte (0) ; // No Huffman table is used.
}
}
outputstream.writeByte (0) ; // Spectral Selection Start
outputstream.writeByte (0) ; // Spectral Selection End
int value = (scan.successive_approximation_high << 4)
| scan.successive_approximation_low ;
outputstream.writeByte (value) ;
// Output the scan data.
outputstream.enterBitMode (CHAR_BIT) ;
if (scan_component_count != 1)
{
interleavedPass (
outputstream,
true,
&JpegEncoderComponent::progressiveDcRefine,
0, 0,
0, 0,
scan.successive_approximation_low) ;
}
else
{
noninterleavedPass (
outputstream,
true,
&JpegEncoderComponent::progressiveDcRefine,
0, 0,
0, 0,
scan.successive_approximation_low) ;
}
outputstream.exitBitMode () ;
return ;
}
//
// Description:
//
// This function outputs a scan that is the first pass for a set of AC
// coefficients.
//
// Even though AC progressive scans cannot be interleaved, we follow the
// convention of using Huffman Table #0 for the Y component and #1 for
// the Cb and Cr components.
//
//
// Parameters:
// scan: The structure that contains the scan parameters.
//
void JpegEncoder::printAcFirst (JpegOutputStream &outputstream, const Scan &scan)
{
// Reset the Huffman statistics counters.
if ((scan.component_mask & (1<<YCOMPONENT)) != 0)
{
ac_tables [0].reset () ;
}
else
{
ac_tables [1].reset () ;
}
outputRestartInterval (outputstream, restart_interval) ;
// Gather the Huffman statistics
firstAcData (outputstream, scan, false, &JpegEncoderComponent::gatherAcData) ;
// Generate the Huffman statistics
if ((scan.component_mask & (1<<YCOMPONENT)) != 0)
{
ac_tables [0].buildTable () ;
}
else
{
ac_tables [1].buildTable () ;
}
printHuffmanTables (outputstream, scan, false, true) ;
// Section B.2.3
outputMarker (outputstream, SOS) ;
outputstream.writeBigEndianWord (6 + 2 * scan_component_count) ; // Length
outputstream.writeByte (scan_component_count) ; // Component Count
if ((scan.component_mask & (1<<YCOMPONENT)) != 0)
{
outputstream.writeByte (YCOMPONENT) ;
outputstream.writeByte (0x00) ; // Entropy Table
}
else if ((scan.component_mask & (1<<CBCOMPONENT)) != 0)
{
outputstream.writeByte (CBCOMPONENT) ;
outputstream.writeByte (0x11) ; // Entropy Tables
}
else if ((scan.component_mask & (1<<CRCOMPONENT)) != 0)
{
outputstream.writeByte (CRCOMPONENT) ;
outputstream.writeByte (0x11) ; // Entropy Tables
}
outputstream.writeByte (scan.spectral_selection_start) ; // Spectral Selection Start
outputstream.writeByte (scan.spectral_selection_end) ; // Spectral Selection End
int value = (scan.successive_approximation_high << 4)
| scan.successive_approximation_low ;
outputstream.writeByte (value) ; // Successive Approximation
outputstream.enterBitMode (CHAR_BIT) ;
firstAcData (outputstream, scan, true, &JpegEncoderComponent::printAcData) ;
outputstream.exitBitMode () ;
return ;
}
//
// Descriptio:
//
// This function outputs the data for a scan that refines AC coefficients
// through successive approximation.
//
//
// Parameters:
// scan: The structure that contains the scan parameters.
//
void JpegEncoder::printAcRefine (JpegOutputStream &outputstream, const Scan &scan)
{
// Reset the Huffman statistics counters.
if ((scan.component_mask & (1<<YCOMPONENT)) != 0)
ac_tables [0].reset () ;
else
ac_tables [1].reset () ;
outputRestartInterval (outputstream, restart_interval) ;
// Gather the Huffman statistics.
refineAcData (outputstream, scan, false, &JpegEncoderComponent::gatherAcData) ;
// Create the Huffman Table.
if ((scan.component_mask & (1 <<YCOMPONENT)) != 0)
{
ac_tables [0].buildTable () ;
}
else
{
ac_tables [1].buildTable () ;
}
printHuffmanTables (outputstream, scan, false, true) ; // Only output the AC table.
// Create the scan header.
// Section B.2.3
outputMarker (outputstream, SOS) ;
outputstream.writeBigEndianWord (6 + 2 * scan_component_count) ; // Length
outputstream.writeByte (scan_component_count) ; // Component Count
if ((scan.component_mask & (1<<YCOMPONENT)) != 0)
{
outputstream.writeByte (YCOMPONENT) ;
outputstream.writeByte (0x00) ; // Entropy Tables
}
if ((scan.component_mask & (1<<CBCOMPONENT)) != 0)
{
outputstream.writeByte (CBCOMPONENT) ;
outputstream.writeByte (0x11) ; // Entropy Tables
}
if ((scan.component_mask & (1<<CRCOMPONENT)) != 0)
{
outputstream.writeByte (CRCOMPONENT) ;
outputstream.writeByte (0x11) ; // Entropy Tables
}
outputstream.writeByte (scan.spectral_selection_start) ; // Spectral Selection Start
outputstream.writeByte (scan.spectral_selection_end) ; // Spectral Selection End
int value = (scan.successive_approximation_high << 4)
| scan.successive_approximation_low ;
outputstream.writeByte (value) ; // Successive Approximation
// Output the scan data.
outputstream.enterBitMode (CHAR_BIT) ;
refineAcData (outputstream, scan, true, &JpegEncoderComponent::printAcData) ;
outputstream.exitBitMode () ;
return ;
}
//
// Description:
//
// This function loops through the data in an initial AC scan. For
// all scans other than AC progressive ones we use the same function for
// this purpose. Due to the excessive complexity of AC progressive scans
// we use a specialized function.
//
// This function gets called twice for each scan. The first pass is used
// to gather Huffman statistics. The second pass is to output the scan.
// Having a common function ensures that Huffman statistics are gathered
// in the exact same manner as the scan data is output.
//
// Parameters:
// scan: The structure that contains the scan parameters.
// outputrestarts: flag to indicate if restart markers are to be output
// acfunction: The member function to process a data unit
//
void JpegEncoder::firstAcData (
JpegOutputStream &outputstream,
const Scan &scan,
bool outputrestarts,
JpegEncoderComponent::ACOUTPUTFUNCTION acfunction)
{
// We use a scale integer to keep trake of progress to lessen the
// change that the progress increment will be zero.
const int progressscale = 8 ;
unsigned int progress ;
unsigned int progressincrement ;
if (outputrestarts)
progress = 50 << progressscale ;
else
progress = 0 ;
progressincrement = (100 << progressscale)
/ (2 * scan_components [0]->dataUnitRows ()) ;
scan_components [0]->resetEobRun () ;
unsigned int intervalcount = 0 ; // Count between restarts
unsigned int restartmarker = 0 ; // Value 0..7
for (unsigned int row = 0 ;
row < scan_components [0]->dataUnitRows () ;
++ row)
{
for (unsigned int col = 0 ;
col < scan_components [0]->dataUnitCols () ;
++ col, ++ intervalcount)
{
// See if we are using restart markers.
if (restart_interval != 0)
{
// Is a restart marker needed.
if (intervalcount == restart_interval)
{
// If there are any outstanding EOB runs we flush them before the
// restart marker. This is not explicitly stated in the JPEG
// standard. The definition of "Restart Interval" in section 4.1
// states that restart markers separate independent sequences,
// something we would not have if we did not output the EOB run
// here.
scan_components [0]->printEobRun (acfunction) ;
// Here we rely on the relationship RST0|n = RSTn [n = 0..7]
// Section E.1.4
if (outputrestarts)
outputRestartMarker (outputstream, restartmarker) ;
++ restartmarker ;
restartmarker %= 8 ;
intervalcount = 0 ;
}
}
// Process the data unit
scan_components [0]->progressiveAcFirst (
row,
col,
acfunction,
scan.spectral_selection_start,
scan.spectral_selection_end,
scan.successive_approximation_low) ;
}
progress += progressincrement ;
callProgressFunction (progress >> progressscale) ;
}
// If there is a final end of band run then write it out.
scan_components [0]->printEobRun (acfunction) ;
if (outputrestarts)
callProgressFunction (100) ;
else
callProgressFunction (50) ;
return ;
}
//
// Description
//
// This function loops through the DC using in a refining AC scan. For
// all scans other than AC progressive ones we use the same function for
// this purpose. Due to the excessive complexity of AC progressive scans
// we use a specialized function.
//
// This function gets called twice for each scan. The first pass is used
// to gather Huffman statistics. The second pass is to output the scan.
// Having a common function ensures that Huffman statistics are gathered
// in the exact same manner as the scan data is output.
//
// Parameters:
// scan: The structure that contains the scan parameters.
// outputrestarts: flag to indicate if restart markers are to be output
// acfunction: The member function to process a data unit
//
void JpegEncoder::refineAcData (
JpegOutputStream &outputstream,
const Scan &scan,
bool outputrestarts,
JpegEncoderComponent::ACOUTPUTFUNCTION acfunction)
{
// We use a scale integer to keep trake of progress to lessen the
// change that the progress increment will be zero.
const int progressscale = 8 ;
unsigned int progress ;
unsigned int progressincrement ;
if (outputrestarts)
progress = 50 << progressscale ;
else
progress = 0 ;
progressincrement = (100 << progressscale)
/ (2 * scan_components [0]->dataUnitRows ()) ;
scan_components [0]->resetEobRun () ;
unsigned int intervalcount = 0 ; // Count between restart markers
unsigned int restartmarker = 0 ; // 0..7 => RST0..RST7
for (unsigned int row = 0 ;
row < scan_components [0]->dataUnitRows () ;
++ row)
{
for (unsigned int col = 0 ;
col < scan_components [0]->dataUnitCols () ;
++ col, ++ intervalcount)
{
// Are we using restart markers?
if (restart_interval != 0)
{
// Do we need to output a restart marker?
if (intervalcount == restart_interval)
{
// If there are any outstanding EOB runs we flush them before the
// restart marker. This is not explicitly stated in the JPEG
// standard. The definition of "Restart Interval" in section 4.1
// states that restart markers separate independent sequences,
// something we would not have if we did not output the EOB run
// here.
scan_components [0]->printRefineEobRun (
acfunction,
scan.spectral_selection_start,
scan.spectral_selection_end,
scan.successive_approximation_low) ;
// Section E.1.4
if (outputrestarts)
outputRestartMarker (outputstream, restartmarker) ;
++ restartmarker ;
restartmarker %= 8 ;
intervalcount = 0 ;
}
}
scan_components [0]->progressiveAcRefine (
row,
col,
acfunction,
scan.spectral_selection_start,
scan.spectral_selection_end,
scan.successive_approximation_low
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -