📄 jpgdecodercomponent.~cpp
字号:
//
// Description:
//
// This function copies the component values at the edge of a data
// unit to the 8 surrounding data units so that each value at the edge
// of the center is the same as the adjacent value in the ajoining
// data unit. This is used to create dummy data units at the edge of an
// image.
//
// Parameters:
// center: The data unit to copy
// upperleft, uppercenter, upperight,
// left, right,
// lowerleft, lowercenter, lowerright: The dummy data units to copy to.
//
inline void FillEdges (
const JpegDecoderDataUnit ¢er,
JpegDecoderDataUnit &upperleft,
JpegDecoderDataUnit &uppercenter,
JpegDecoderDataUnit &upperright,
JpegDecoderDataUnit &left,
JpegDecoderDataUnit &right,
JpegDecoderDataUnit &lowerleft,
JpegDecoderDataUnit &lowercenter,
JpegDecoderDataUnit &lowerright)
{
const int LAST = JPEGSAMPLEWIDTH - 1 ;
upperleft [LAST][LAST] = center [0][0] ;
lowerleft [0][LAST] = center [LAST][0] ;
upperright [LAST][0] = center [0][LAST] ;
lowerright [0][0] = center [LAST][LAST] ;
for (unsigned int ii = 0 ; ii < JPEGSAMPLEWIDTH ; ++ ii)
{
left [ii][LAST] = center [ii][0] ;
uppercenter [LAST][ii] = center [0][ii] ;
right [ii][0] = center [ii][LAST] ;
lowercenter [0][ii] = center [LAST][ii] ;
}
}
}
namespace ColosseumPrivate
{
//
// Description:
//
// Class default constructor
//
JpegDecoderComponent::JpegDecoderComponent ()
: component_id (0),
horizontal_frequency (0),
vertical_frequency (0),
v_sampling (0),
h_sampling (0),
last_dc_value (0),
ac_table (0),
dc_table (0),
quantization_table (0),
eob_run (0),
noninterleaved_rows (0),
noninterleaved_cols (0),
data_units (0),
coefficient_blocks (0),
upsample_data (0)
{
return ;
}
//
// Description:
//
// Class Destructor
//
JpegDecoderComponent::~JpegDecoderComponent ()
{
delete [] data_units ; data_units = 0 ;
delete [] upsample_data ; upsample_data = 0 ;
return ;
}
//
// Description:
//
// This function sets the horizontal sampling frequency
// for the component.
//
// Parameters:
// value: The sampling factor (1..4)
//
void JpegDecoderComponent::horizontalFrequency (unsigned int value)
{
if (value < JPEGMINSAMPLINGFREQUENCY || value > JPEGMAXSAMPLINGFREQUENCY)
throw JpegDecoder::JpegError ("Sampling Frequency Outside the Range 1-4") ;
horizontal_frequency = value ;
return ;
}
//
// Description:
//
// This function sets the vertical sampling frequency
// for the component.
//
// Parameters:
// value: The sampling factor (1..4)
//
void JpegDecoderComponent::verticalFrequency (unsigned int value)
{
if (value < JPEGMINSAMPLINGFREQUENCY || value > JPEGMAXSAMPLINGFREQUENCY)
throw JpegDecoder::JpegError ("Vertical Sampling Frequency Outside the Range 1-4") ;
vertical_frequency = value ;
return ;
}
//
// Description:
//
// This function associates a quantization table with the component.
//
// Parameters:
// table: The quantization table
//
void JpegDecoderComponent::setQuantizationTable (
JpegDecoderQuantizationTable &table)
{
quantization_table = &table ;
return ;
}
//
// Description:
//
// This function determines the dimensions for the component and allocates
// the storage to hold the component's data.
//
// Parameters:
// decoder: The jpeg decoder this component belongs to.
//
void JpegDecoderComponent::allocateComponentBuffers (
const JpegDecoder &decoder)
{
if (data_units == 0)
{
image_height = decoder.frameHeight () ;
image_width = decoder.frameWidth () ;
// Determine sampling for the component. This is the amount of
// stretching needed for the component.
v_sampling = decoder.maxVFrequency () / vertical_frequency ;
h_sampling = decoder.maxHFrequency () / horizontal_frequency ;
// Determine the component's dimensions in a non-interleaved scan.
noninterleaved_rows = (image_height
+ v_sampling * JPEGSAMPLEWIDTH - 1)
/ (v_sampling * JPEGSAMPLEWIDTH) ;
noninterleaved_cols = (image_width
+ h_sampling * JPEGSAMPLEWIDTH - 1)
/ (h_sampling * JPEGSAMPLEWIDTH) ;
du_rows = decoder.mcuRows () * vertical_frequency ;
du_cols = decoder.mcuCols () * horizontal_frequency ;
pdu_rows=du_rows;
pdu_cols=du_cols;
data_units = new JpegDecoderDataUnit [du_rows * du_cols] ;
}
if (decoder.isProgressive () && coefficient_blocks == 0)
{
unsigned int count = du_rows * du_cols ;
coefficient_blocks = new JpegCoefficientBlock [count] ;
memset (coefficient_blocks,
0,
sizeof (JpegCoefficientBlock) * count) ;
}
return ;
}
//
// Description:
//
// This function frees the memory allocated by the component
// during the decompression process.
//
void JpegDecoderComponent::freeComponentBuffers ()
{
delete [] data_units ; data_units = 0 ;
delete [] coefficient_blocks ; coefficient_blocks = 0 ;
delete [] upsample_data ; upsample_data = 0 ;
return ;
}
//
// Description:
//
// This function asigned Huffman tables to the component.
//
// Parameters:
// dc: The DC Huffman table
// ac: The AC Huffman table
//
void JpegDecoderComponent::setHuffmanTables (JpegHuffmanDecoder &dc,
JpegHuffmanDecoder &ac)
{
dc_table = &dc ;
ac_table = &ac ;
return ;
}
//
// Description:
//
// This function ensures that this component has a defined
// AC table assigned to it. If not, it throws an exception.
//
void JpegDecoderComponent::checkAcTable ()
{
// If this occurs then we have a programming error.
ASSERT (ac_table != 0) ;
if (! ac_table->tableDefined ())
throw JpegDecoder::JpegBadStream ("AC Table Not Defined") ;
return ;
}
//
// Sequential and Progressive
//
// This function is called before processing a scan. It ensures that the
// DC Huffman table used by the component has actually been defined.
//
void JpegDecoderComponent::checkDcTable ()
{
ASSERT (dc_table != 0)
// This condition could be caused by a corrupt JPEG stream.
if (! dc_table->tableDefined ())
throw JpegDecoder::JpegError ("DC Table Not Defined") ;
return ;
}
//
// Description:
//
// Sequential and Progressive
//
// This function is called before processing a scan. It ensures that the
// Quantization table used by the component has actually been defined.
//
void JpegDecoderComponent::checkQuantizationTable ()
{
if (quantization_table == 0)
throw JpegDecoder::JpegError ("INTERNAL ERROR - Quantization Table Not Assigned") ;
if (! quantization_table->tableDefined ())
throw JpegDecoder::JpegBadStream ("Quantization Table Not Defined") ;
return ;
}
//
// Description:
//
// This function decodes a data unit in a sequential scan.
//
// Parameters:
// decoder: The decoder that owns this component
// mcurow, mcucol: The row and column for this data unit.
//
void JpegDecoderComponent::decodeSequential (JpegInputStream &inputstream,
unsigned int mcurow,
unsigned int mcucol)
{
JpegCoefficientBlock data ;
memset (&data, 0, sizeof (data)) ;
// Decode the DC differce value.
// Section F.2.2.1
unsigned int count ; // called T in F.2.2.1
count = dc_table->decode (inputstream) ;
int bits = inputstream.getBits (count) ;
int diff = Extend (bits, count) ;
// Create the DC value from the difference and the previous DC value.
int dc = diff + last_dc_value ;
last_dc_value = dc ;
data [0] = dc ;
// Decode the AC coefficients.
// Section F.2.2.2 Figure F.13
for (unsigned int kk = 1 ; kk < JPEGSAMPLESIZE ; ++ kk)
{
UBYTE2 rs = ac_table->decode (inputstream) ;
UBYTE2 ssss = (UBYTE2) (rs & 0xF) ;
UBYTE2 rrrr = (UBYTE2) (rs >> 0x4) ;
if (ssss == 0)
{
// ssss is zero then rrrr should either be 15 or zero according to
// Figure F.1. 0 means that the rest of the coefficients are zero
// while 15 means the next 16 coefficients are zero. We are not checking
// for other values because Figure F.13 shows values other than 15
// as being treated as zero.
if (rrrr != 15)
break ;
kk += 15 ; // Actually 16 since one more gets added by the loop.
}
else
{
// If ssss is non-zero then rrrr gives the number of zero coefficients
// to skip.
kk += rrrr ;
if (kk >= JPEGSAMPLESIZE)
throw JpegDecoder::JpegBadStream ("Coefficient Index out of Range") ;
// Receive and extend the additional bits.
// Section F2.2.2 Figure F.14
int bits = inputstream.getBits (ssss) ;
int value = Extend (bits, ssss) ;
data [JpegZigZagInputOrder (kk)] = value ;
}
}
data_units [mcurow * du_cols + mcucol].inverseDCT (data,
*quantization_table) ;
//ShowMessage(data_units [mcurow * du_cols + mcucol].values[0][0]);
return ;
}
//
// Description:
//
// This function upsamples the data for the component. Here we take
// the values from the data_units array and copy it to the
// upsample_data. If the horizontal or vertical sampling frequencies
// are less than the maximum for the image then we need to
// stretch the data during the copy.
//
// Parameters:
//
// usefilter: true => Upsample using triangle filter if appropriate.
//
void JpegDecoderComponent::upsampleImage (bool usefilter)
{
const unsigned int rowwidth = du_cols * h_sampling * JPEGSAMPLEWIDTH ;
const unsigned int imagesize = rowwidth * du_rows * v_sampling * JPEGSAMPLEWIDTH ;
if (imagesize == 0)
return ; // No data for this component yet.
if (upsample_data == 0)
upsample_data = new JPEGSAMPLE [imagesize] ;
// Simple case where component does not need to be upsampled.
if (v_sampling == 1 && h_sampling == 1)
{
upSample1To1 () ;
}
else
{
// The triangle filter only workd for 2:1 and 4:1 sampling.
if (usefilter
&& (v_sampling % 2 == 0 || v_sampling == 1)
&& (h_sampling % 2 == 0 || h_sampling == 1))
{
triangleFilter () ;
}
else
{
blockFilter () ;
}
}
return ;
}
//
// Description:
//
// This static member function grayscale converts component
// image data in the upsample_data array and writes it to the
// the output image. Actually for a grayscale conversion all
// we do is copy.
//
// Parameters:
// cc: The component
// image: The output image
//
void JpegDecoderComponent::convertGrayscale (JpegDecoderComponent &cc,
BitmapImage &image)
{
unsigned int rowstart = 0 ;
BitmapImage::Pixel *pixel = &image [0] ;
for (unsigned int ii = 0 ; ii < image.getHeight () ; ++ ii)
{
unsigned int offset = rowstart ;
for (unsigned int jj = 0 ; jj < image.getWidth () ; ++ jj, ++ pixel)
{
pixel->red = cc.upsample_data [offset] ;
ShowMessage(pixel->red);
pixel->green = cc.upsample_data [offset] ;
pixel->blue = cc.upsample_data [offset] ;
pixel->alpha = 0xFFU ;
++ offset ;
}
rowstart += cc.du_cols * cc.h_sampling * JPEGSAMPLEWIDTH ;
}
return ;
}
//
// Description:
//
// This static member function converts the upsample_data in three
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -