📄 jpgencoder.~cpp
字号:
resetDcValues () ;
unsigned int intervalcount = 0 ;
unsigned int restartmarker = 0 ;
for (unsigned int mcurow = 0 ;
mcurow < mcu_rows ;
++ mcurow)
{
for (unsigned int mcucol = 0 ;
mcucol < mcu_cols ;
++ mcucol, ++ intervalcount)
{
// Handle Restart Markers
if (restart_interval != 0)
{
if (intervalcount == restart_interval && restart_interval != 0)
{
if (writedata)
outputRestartMarker (outputstream, restartmarker) ;
resetDcValues () ;
++ restartmarker ;
restartmarker %= 8 ;
intervalcount = 0 ;
}
}
for (unsigned int cc = 0 ; cc < scan_component_count ; ++ cc)
{
for (unsigned int cy = 0 ;
cy < scan_components [cc]->getVerticalFrequency () ;
++ cy)
{
unsigned int durow = scan_components [cc]->getVerticalFrequency ()
* mcurow + cy ;
for (unsigned int cx = 0 ;
cx < scan_components [cc]->getHorizontalFrequency () ;
++ cx)
{
unsigned int ducol
= scan_components [cc]->getHorizontalFrequency ()
* mcucol + cx ;
(scan_components [cc]->*passfunction) (durow, ducol,
dcfunction, acfunction,
sss, sse, ssa) ;
}
}
}
}
progress += progressincrement ;
callProgressFunction (progress >> progressscale) ;
}
if (writedata)
callProgressFunction (100) ;
else
callProgressFunction (50) ;
return ;
}
//
// Description:
//
// This function writes the Huffman tables used by a scan to the output
// stream.
//
// We only use two DC and two AC tables to be compatible with baseline
// JPEG. In progressive JPEG there is really no reason for more than
// two tables for RGB images. If we ever go to four colors then things
// may need to change.
//
// The Y component always uses table ID 0. The Cb and Cr components always
// use table ID 1.
//
// Parameters:
// scan: Here the scan structure is used to determine which components
// are part of the scan (Y and/or Cb/Cr)
// usedc: Set to true if the scan includes DC components. (Sequential
// Scan or Progressive Scan with the spectral selection 0)
// useac: Set to true if the scan includes AC components. (Sequential
// Scan or Progressive Scan with the spectral selection start
// not zero)
//
void JpegEncoder::printHuffmanTables (JpegOutputStream &outputstream,
const Scan &scan,
bool usedc,
bool useac)
{
// Section B.2.4.2
if ((scan.component_mask & (1 << YCOMPONENT)) != 0)
{
// See if this is a color image.
if (scan_component_count != 1)
{
// We have at least two components and the first is the Y component.
// This means we need the both of the huffman tables.
// B.2.4.2
outputMarker (outputstream, DHT) ;
unsigned int size = sizeof (UBYTE2) ;
if (usedc)
{
size += dc_tables [0].outputSize ()
+ dc_tables [1].outputSize () ;
}
if (useac)
{
size += ac_tables [0].outputSize ()
+ ac_tables [1].outputSize () ;
}
outputstream.writeBigEndianWord (size) ;
if (usedc)
{
outputstream.writeByte (0x00) ;
dc_tables [0].printTable (outputstream) ;
}
if (useac)
{
outputstream.writeByte (0x10) ;
ac_tables [0].printTable (outputstream) ;
}
if (usedc)
{
outputstream.writeByte (0x01) ;
dc_tables [1].printTable (outputstream) ;
}
if (useac)
{
outputstream.writeByte (0x11) ;
ac_tables [1].printTable (outputstream) ;
}
}
else
{
// The only component is Y
unsigned int size = sizeof (UBYTE2) ;
if (usedc)
{
size += dc_tables [0].outputSize () ;
}
if (useac)
{
size += ac_tables [0].outputSize () ;
}
outputMarker (outputstream, DHT) ;
outputstream.writeBigEndianWord (size) ;
if (usedc)
{
outputstream.writeByte (0x00) ;
dc_tables [0].printTable (outputstream) ;
}
if (useac)
{
outputstream.writeByte (0x10) ;
ac_tables [0].printTable (outputstream) ;
}
}
}
else
{
// The Y component is not present. Output is the same for
// Cb, Cr, or Cb & Cr.
unsigned int size = sizeof (UBYTE2) ;
if (usedc)
{
size += dc_tables [1].outputSize () ;
}
if (useac)
{
size += ac_tables [1].outputSize () ;
}
outputMarker (outputstream, DHT) ;
outputstream.writeBigEndianWord (size) ;
if (usedc)
{
outputstream.writeByte (0x01) ;
dc_tables [1].printTable (outputstream) ;
}
if (useac)
{
outputstream.writeByte (0x11) ;
ac_tables [1].printTable (outputstream) ;
}
}
return ;
}
//
// Description:
//
// This function resets the DC difference values for all
// all the components in the scan. We do this at the start of
// each scan and whenever we output a restart marker.
//
void JpegEncoder::resetDcValues ()
{
for (unsigned int ii = 0 ; ii < scan_component_count ; ++ ii)
scan_components [ii]->resetDcDifference () ;
return ;
}
//
// Description:
//
// This function determines the dimensions of an MCU using the maximum
// sampling frequencies of the components.
//
void JpegEncoder::calculateMcuDimensions ()
{
max_horizontal_frequency = 1 ;
max_vertical_frequency = 1 ;
if (! gray_scale)
{
for (unsigned int ii = YCOMPONENT ; ii <= CRCOMPONENT ; ++ ii)
{
if (image_components [ii].getHorizontalFrequency ()
> max_horizontal_frequency)
{
max_horizontal_frequency
= image_components [ii].getHorizontalFrequency () ;
}
if (image_components [ii].getVerticalFrequency ()
> max_vertical_frequency)
{
max_vertical_frequency
= image_components [ii].getVerticalFrequency () ;
}
}
}
else
{
max_horizontal_frequency
= image_components [YCOMPONENT].getHorizontalFrequency () ;
max_vertical_frequency
= image_components [YCOMPONENT].getVerticalFrequency () ;
}
unsigned int mcuheight = max_vertical_frequency * JPEGSAMPLEWIDTH ;
unsigned int mcuwidth = max_horizontal_frequency * JPEGSAMPLEWIDTH ;
mcu_rows = (frame_height + mcuheight - 1) / mcuheight ;
mcu_cols = (frame_width + mcuwidth - 1) / mcuwidth ;
return ;
}
//
// Description:
//
// This function writes a progressive scan to the output stream.
//
// Parameters:
// scan: The structure that contains the scan parameters.
//
void JpegEncoder::printProgressiveScan (JpegOutputStream &outputstream,
const Scan &scan)
{
ASSERT (scan_component_count != 0) ; // No components in progressive scan
if (scan.spectral_selection_start == 0)
{
if (scan.successive_approximation_high == 0)
{
printDcFirst (outputstream, scan) ;
}
else
{
printDcRefine (outputstream, scan) ;
}
}
else
{
ASSERT (scan_component_count == 1) ; // AC Scan does not have 1 component
if (scan.successive_approximation_high == 0)
{
printAcFirst (outputstream, scan) ;
}
else
{
printAcRefine (outputstream, scan) ;
}
}
return ;
}
//
// Description:
//
// This function handles scans containing the first pass for DC
// coefficients. If successive approximation is not used then
// this would be the only DC coefficient pass. DC progressive
// scans may be interleaved, unlike AC scans.
//
// Parameters:
// scan: The structure that contains the scan parameters.
//
void JpegEncoder::printDcFirst (JpegOutputStream &outputstream, const Scan &scan)
{
// Reset the Huffman statistics counters.
if ((scan.component_mask & (1 << YCOMPONENT)) != 0)
{
dc_tables [0].reset () ;
}
if ((scan.component_mask & (1 << YCOMPONENT)) == 0
|| scan_component_count > 1)
{
dc_tables [1].reset () ;
}
outputRestartInterval (outputstream, restart_interval) ;
// Gather the Huffman statistics
if (scan_component_count != 1)
{
interleavedPass (
outputstream,
false,
&JpegEncoderComponent::progressiveDcFirst,
&JpegEncoderComponent::gatherDcData, 0,
0, 0,
scan.successive_approximation_low) ;
}
else
{
noninterleavedPass (
outputstream,
false,
&JpegEncoderComponent::progressiveDcFirst,
&JpegEncoderComponent::gatherDcData, 0,
0, 0,
scan.successive_approximation_low) ;
}
// Create the Huffman tables from the statistics
if ((scan.component_mask & (1 << YCOMPONENT)) != 0)
{
dc_tables [0].buildTable () ;
}
if ((scan.component_mask & (1 << YCOMPONENT)) == 0
|| scan_component_count > 1)
{
dc_tables [1].buildTable () ;
}
printHuffmanTables (outputstream, scan, true, false) ;
// Output 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 (! gray_scale)
{
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 (0) ; // Spectral Selection Start
outputstream.writeByte (0) ; // 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) ;
if (scan_component_count != 1)
{
interleavedPass (
outputstream,
true,
&JpegEncoderComponent::progressiveDcFirst,
&JpegEncoderComponent::printDcData, 0,
0, 0,
scan.successive_approximation_low) ;
}
else
{
noninterleavedPass (
outputstream,
true,
&JpegEncoderComponent::progressiveDcFirst,
&JpegEncoderComponent::printDcData, 0,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -