home *** CD-ROM | disk | FTP | other *** search
- //
- // 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 ;
- }
-
-