📄 jpdecomp.cpp
字号:
//
// Copyright (c) 1997,1998 Colosseum Builders, Inc.
// All rights reserved.
//
// Colosseum Builders, Inc. makes no warranty, expressed or implied
// with regards to this software. It is provided as is.
//
// See the README.TXT file that came with this software for restrictions
// on the use and redistribution of this file or send E-mail to
// info@colosseumbuilders.com
//
//
// JPEG Decoder Component Class Implementation
//
// Author: John M. Miano miano@colosseumbuilders.com
//
#include "jpdecomp.h"
#include "jpgexcep.h"
#include "jpdequan.h"
#include "jpegdeco.h"
#include "jpdecobk.h"
#include "jpeg.h"
#include "bitimage.h"
//
// Description:
//
// SequentialOnly
//
// This function extends the sign bit of a decoded value.
//
// Parameters:
// vv: The bit value
// tt: The length of the bit value
//
static inline int Extend (int vv, int tt)
{
// Extend function defined in Section F.2.2.1 Figure F.12
// The tt'th bit of vv is the sign bit. One is for
// positive values and zero is for negative values.
int vt = 1 << (tt - 1) ;
if (vv < vt)
{
vt = (-1 << tt) + 1 ;
return vv + vt ;
}
else
{
return vv ;
}
}
//
// 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 = NULL ;
dc_table = NULL ;
quantization_table = NULL ;
noninterleaved_rows = 0 ;
noninterleaved_cols = 0 ;
data_units = NULL ;
upsample_data = NULL ;
return ;
}
//
// Description:
//
// Class Destructor
//
JpegDecoderComponent::~JpegDecoderComponent ()
{
delete [] data_units ; data_units = NULL ;
delete [] upsample_data ; upsample_data = NULL ;
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 EJpegValueOutOfRange () ;
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 EJpegValueOutOfRange () ;
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 == NULL)
{
// 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 = (decoder.FrameHeight ()
+ v_sampling * JpegSampleWidth - 1)
/ (v_sampling * JpegSampleWidth) ;
noninterleaved_cols = (decoder.FrameWidth ()
+ h_sampling * JpegSampleWidth - 1)
/ (h_sampling * JpegSampleWidth) ;
du_rows = decoder.McuRows () * vertical_frequency ;
du_cols = decoder.McuCols () * horizontal_frequency ;
data_units = new JpegDecoderDataUnit [du_rows * du_cols] ;
}
return ;
}
//
// Description:
//
// This function frees the memory allocated by the component
// during the decompression process.
//
void JpegDecoderComponent::FreeComponentBuffers ()
{
delete [] data_units ; data_units = NULL ;
delete [] upsample_data ; upsample_data = NULL ;
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.
if (ac_table == NULL)
throw EJpegFatal ("INTERNAL ERROR - AC Table Not Assigned") ;
if (! ac_table->Defined ())
throw EJpegError ("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 ()
{
if (dc_table == NULL)
throw EJpegFatal ("INTERNAL ERROR - DC Table Not Assigned") ;
// This condition could be caused by a corrupt JPEG stream.
if (! dc_table->Defined ())
throw EJpegFatal ("INTERNAL ERROR - 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 == NULL)
throw EJpegFatal ("INTERNAL ERROR - Quantization Table Not Assigned") ;
if (! quantization_table->Defined ())
throw EJpegError ("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 (JpegDecoder &decoder,
unsigned int mcurow,
unsigned int mcucol)
{
JpegDecoderCoefficientBlock 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 (decoder) ;
int bits = decoder.Receive (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][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 (decoder) ;
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 EJpegFatal ("Value out of range") ;
// Receive and extend the additional bits.
// Section F2.2.2 Figure F.14
int bits = decoder.Receive (ssss) ;
int value = Extend (bits, ssss) ;
(&data [0][0])[JpegZigZagInputOrder (kk)] = value ;
}
}
data_units [mcurow * du_cols + mcucol].InverseDCT (data,
*quantization_table) ;
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.
//
void JpegDecoderComponent::Upsample ()
{
unsigned int imagesize = du_rows * v_sampling * du_cols
* h_sampling * JpegSampleSize ;
if (imagesize == 0)
return ; // No data for this component yet.
if (upsample_data == NULL)
upsample_data = new JPEGSAMPLE [imagesize] ;
// Simple case where component does not need to be upsampled.
if (v_sampling == 1 && h_sampling == 1)
{
unsigned output = 0 ;
unsigned int startdu = 0 ;
for (unsigned int durow = 0 ; durow < du_rows ; ++ durow)
{
for (unsigned int ii = 0 ; ii < JpegSampleWidth ; ++ ii)
{
unsigned int du = startdu ;
for (unsigned int ducol = 0 ; ducol < du_cols ; ++ ducol)
{
upsample_data [output] = data_units [du][ii][0] ; ++ output ;
upsample_data [output] = data_units [du][ii][1] ; ++ output ;
upsample_data [output] = data_units [du][ii][2] ; ++ output ;
upsample_data [output] = data_units [du][ii][3] ; ++ output ;
upsample_data [output] = data_units [du][ii][4] ; ++ output ;
upsample_data [output] = data_units [du][ii][5] ; ++ output ;
upsample_data [output] = data_units [du][ii][6] ; ++ output ;
upsample_data [output] = data_units [du][ii][7] ; ++ output ;
++ du ;
}
}
startdu += du_cols ;
}
}
else
{
unsigned output = 0 ;
unsigned int startdu = 0 ;
for (unsigned int durow = 0 ; durow < du_rows ; ++ durow)
{
for (unsigned int ii = 0 ; ii < JpegSampleWidth ; ++ ii)
{
for (unsigned int vv = 0 ; vv < v_sampling ; ++ vv)
{
unsigned int du = startdu ;
for (unsigned int ducol = 0 ; ducol < du_cols ; ++ ducol)
{
unsigned int jj ;
for (jj = 0 ; jj < h_sampling ; ++ jj)
{
upsample_data [output] = data_units [du][ii][0] ; ++ output ;
}
for (jj = 0 ; jj < h_sampling ; ++ jj)
{
upsample_data [output] = data_units [du][ii][1] ; ++ output ;
}
for (jj = 0 ; jj < h_sampling ; ++ jj)
{
upsample_data [output] = data_units [du][ii][2] ; ++ output ;
}
for (jj = 0 ; jj < h_sampling ; ++ jj)
{
upsample_data [output] = data_units [du][ii][3] ; ++ output ;
}
for (jj = 0 ; jj < h_sampling ; ++ jj)
{
upsample_data [output] = data_units [du][ii][4] ; ++ output ;
}
for (jj = 0 ; jj < h_sampling ; ++ jj)
{
upsample_data [output] = data_units [du][ii][5] ; ++ output ;
}
for (jj = 0 ; jj < h_sampling ; ++ jj)
{
upsample_data [output] = data_units [du][ii][6] ; ++ output ;
}
for (jj = 0 ; jj < h_sampling ; ++ jj)
{
upsample_data [output] = data_units [du][ii][7] ; ++ output ;
}
++ du ;
}
}
}
startdu += du_cols ;
}
}
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::GrayscaleConvert (JpegDecoderComponent &cc,
BitmapImage &image)
{
unsigned int rowstart = 0 ;
for (unsigned int ii = 0 ; ii < image.Height () ; ++ ii)
{
unsigned int offset = rowstart ;
UBYTE1 *outrow = image [ii] ;
for (unsigned int jj = 0 ; jj < image.Width () ; ++ jj)
{
outrow [jj] = cc.upsample_data [offset] ;
++ offset ;
}
rowstart += cc.du_cols * cc.h_sampling * JpegSampleWidth ;
}
return ;
}
//
// Description:
//
// This static member function converts the upsample_data in three
// components from YCbCr to RGB and writes it to an image.
//
// Parameters:
// c1: The component containing the Y data
// c2: Ditto for Cb
// c3: Ditto for Cr
// image: The output image
//
void JpegDecoderComponent::RGBConvert (JpegDecoderComponent &c1,
JpegDecoderComponent &c2,
JpegDecoderComponent &c3,
BitmapImage &image)
{
if (c1.upsample_data == NULL
|| c2.upsample_data == NULL
|| c3.upsample_data == NULL)
{
// If we get here then do do not yet have data for all components.
return ;
}
unsigned int rowstart = 0 ;
for (unsigned int ii = 0 ; ii < image.Height () ; ++ ii)
{
unsigned int offset = rowstart ;
UBYTE1 *outrow = image [ii] ;
for (unsigned int jj = 0 ; jj < 3 * image.Width () ; jj += 3)
{
JPEGSAMPLE red = YCbCrToR (c1.upsample_data [offset],
c2.upsample_data [offset],
c3.upsample_data [offset]) ;
JPEGSAMPLE green = YCbCrToG (c1.upsample_data [offset],
c2.upsample_data [offset],
c3.upsample_data [offset]) ;
JPEGSAMPLE blue = YCbCrToB (c1.upsample_data [offset],
c2.upsample_data [offset],
c3.upsample_data [offset]) ;
outrow [jj + BitmapImage::RedOffset] = red ;
outrow [jj + BitmapImage::GreenOffset] = green ;
outrow [jj + BitmapImage::BlueOffset] = blue ;
++ offset ;
}
rowstart += c1.du_cols * c1.h_sampling * JpegSampleWidth ;
}
return ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -