📄 jpenhuff.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 Encoder Library.
//
// Title: EncoderHuffmanTable Class Implementation
//
// Author: John M. Miano miano@colosseumbuilders.com
//
//
#include "jpenhuff.h"
#include "jpegenco.h"
#include "jpgexcep.h"
//
// Description:
//
// Class default constructor
//
JpegEncoderHuffmanTable::JpegEncoderHuffmanTable ()
{
Reset () ;
return ;
}
//
// Description:
//
// After Huffman codes have been generated the object is in a state
// where it cannot be used to create a new set of code. This function
// places the object in a state where it can be reused to generate a
// new set of Huffman Codes.
//
void JpegEncoderHuffmanTable::Reset ()
{
memset (frequencies, 0, sizeof (frequencies)) ;
// We add a dummy Huffman value at the end of the table with a minimumal
// frequency. Since we create the Huffman codes using the in the frequency
// table this dummy value will be assigned the longest all one huffman code.
// This ensures that no Huffman code consists entirely of 1s.
frequencies [256] = 1 ;
sizes_found = false ;
return ;
}
//
// Description:
//
// Function to increment the frequency for a value.
//
// Parameters:
// value: The value whose frequency is to be incremented
//
void JpegEncoderHuffmanTable::IncrementFrequency (unsigned int value)
{
// Once the Huffman codes have been generated for this object, the Reset()
// function must be called before we can gather data again.
if (sizes_found)
throw EJpegFatal ("INTERNAL ERROR - Huffman Code sizes already found") ;
if (value >= JpegMaxNumberOfHuffmanCodes)
throw EJpegIndexOutOfRange () ;
++ frequencies [value] ;
return ;
}
//
// Description:
//
// This function generates the Huffman Codes using the frequency data. The code
// generation process is taken directly from the JPEG standard.
//
// The outputs from this function are the following member variables:
//
// ehufsi [n] : The length of the Huffman Code for value "n"
// ehufco [n] : The Huffman Code for value "n"
// huff_bits [n] : The number of Huffman codes of length "n+1"
// huff_values [n] : The Huffman Values sorted by code length.
//
// The first two arrays are used to encode Huffman values. The last two
// are for writing the table to the output file.
//
// The code generation process is:
//
// 1. Arrange the Huffman Values into a binary tree so that the most
// frequently used codes are closest to the root of the tree. At the end
// of this process the temporary array codesize [n] contains the length
// of the pure Huffman code for the value "n"
//
// 2. Determine the number of Huffman Codes of for each code length. This
// step places the number of codes of length "n+1" in huff_bits[].
//
// 3. The JPEG standard only allows Huffman codes of up to 16-bits. If any
// codes longer than 16-bits were generated in the previous steps then
// we need to reduce the maximum depth of the tree created in step 1.
// The input and output to this step is the array huff_bits[] created in
// the previous step.
//
// 4. Remove the dummy all 1-bit code (See the Reset() function).
//
// 5. Sort the Huffman values in code length order. codesize [n] is the
// input to this step and huff_values [n] is the output. At this point
// all the information needed to write the Huffman Table to the output
// stream has been found.
//
// 6. Determine the code size for each value. At the end of this step
// the temporary array huffsizes [n] is the Huffman code length for
// huff_values [n].
//
// 7. Determine the Huffman code for each value. The temporary array
// huffcodes [n] is the Huffman Code of length huffsizes [n] for
// the value huff_value [n].
//
// 8. Using huffsizes [] and huffcodes created in steps 6 and 7 create
// the arrays ehufco [n] and ehufsi [n] giving the Huffman Code and
// Code Size for n.
//
void JpegEncoderHuffmanTable::BuildTable ()
{
// We need this because MSVC++ does not support standard
// scoping in for statements.
int ii, kk ;
// See if we have already calculated the Huffman codes.
if (sizes_found)
return ;
// The tmp array is used for validating the integrity of the Huffman code
// table. We need a temporary array since frequencies [] gets trashed
// during the code generation process.
unsigned int tmp [JpegMaxNumberOfHuffmanCodes + 1] ;
for (ii = 0 ; ii < JpegMaxNumberOfHuffmanCodes + 1 ; ++ ii)
tmp [ii] = frequencies [ii] ;
// Figure K.1
// Build the Huffman Code Length Lists
int others [JpegMaxNumberOfHuffmanCodes + 1] ;
for (ii = 0 ; ii < JpegMaxNumberOfHuffmanCodes + 1 ; ++ ii)
others [ii] = -1 ;
unsigned int codesize [JpegMaxNumberOfHuffmanCodes + 1] ;
memset (codesize, 0, sizeof (codesize)) ;
while (true)
{
// Find the two smallest non-zero values
int v1 = -1 ;
int v2 = -1 ;
for (unsigned int ii = 0 ; ii < JpegMaxNumberOfHuffmanCodes + 1 ; ++ ii)
{
if (frequencies [ii] != 0)
{
// K.2 says to take the highest value value for v1 and v2
// in case of a tie. This ensures the dummy value gets
// the last Huffman code.
if (v1 < 0 || frequencies [ii] <= frequencies [v1])
{
v2 = v1 ;
v1 = ii ;
}
else if (v2 < 0 || frequencies [ii] <= frequencies [v2])
{
v2 = ii ;
}
}
}
if (v2 < 0)
break ;
// Join the two tree nodes.
frequencies [v1] = frequencies [v1] + frequencies [v2] ;
frequencies [v2] = 0 ;
for (++ codesize [v1] ; others [v1] >= 0 ; ++ codesize [v1])
v1 = others [v1] ;
others [v1] = v2 ;
for (++ codesize [v2] ; others [v2] >= 0 ; ++ codesize [v2])
v2 = others [v2] ;
}
// Figure K.2
// Determine the number of codes of length [n]
memset (huff_bits, 0, sizeof (huff_bits)) ;
for (ii = 0 ; ii < JpegMaxNumberOfHuffmanCodes + 1 ; ++ ii)
{
if (codesize [ii] != 0)
{
++ huff_bits [codesize [ii] - 1] ;
}
}
// Figure K.3
// Ensure that no code is longer than 16-bits.
for (ii = 2 * JpegMaxHuffmanCodeLength - 1 ;
ii >= JpegMaxHuffmanCodeLength ;
-- ii)
{
while (huff_bits [ii] != 0)
{
unsigned int jj = ii - 1 ;
do
{
-- jj ;
}
while (huff_bits [jj] == 0) ;
huff_bits [ii] -= 2 ;
++ huff_bits [ii - 1] ;
huff_bits [jj + 1] += 2 ;
-- huff_bits [jj] ;
}
}
// Remove the reserved code from the end of the list.
for (ii = JpegMaxHuffmanCodeLength - 1 ; ii >= 0 ; -- ii)
{
if (huff_bits [ii] != 0)
{
-- huff_bits [ii] ;
break ;
}
}
// Make sure that the total number of symbols is correct.
unsigned int count = 0 ;
for (ii = 0 ; ii < JpegMaxHuffmanCodeLength ; ++ ii)
{
count += huff_bits [ii] ;
}
if (count >= JpegMaxNumberOfHuffmanCodes)
throw EJpegFatal ("INTERNAL ERROR - Too many codes defined") ;
// Figure K.4
// Sort the values in order of code length
memset (huff_values, 0, sizeof (huff_values)) ;
for (ii = 1, kk = 0 ; ii < 2 * JpegMaxHuffmanCodeLength ; ++ ii)
{
for (unsigned int jj = 0 ; jj < JpegMaxNumberOfHuffmanCodes ; ++ jj)
{
if (codesize [jj] == ii)
{
huff_values [kk] = jj ;
++ kk ;
}
}
}
// Section C.2 Figure C.1
// Convert the array "huff_bits" containing the count of codes for each
// length 1..16 into an array containing the length for each code.
unsigned int huffsizes [JpegMaxNumberOfHuffmanCodes] ;
memset (huffsizes, 0, sizeof (huffsizes)) ;
for (ii = 0, kk = 0 ; ii < JpegMaxHuffmanCodeLength ; ++ ii)
{
for (int jj = 0 ; jj < huff_bits [ii] ; ++ jj)
{
huffsizes [kk] = ii + 1 ;
++ kk ;
}
huffsizes [kk] = 0 ;
}
// Section C.2 Figure C.2
// Calculate the Huffman code for each Huffman value.
UBYTE2 code = 0 ;
unsigned int huffcodes [JpegMaxNumberOfHuffmanCodes] ;
memset (huffcodes, 0, sizeof (huffcodes)) ;
unsigned int si ;
for (kk = 0, si = huffsizes [0] ;
huffsizes [kk] != 0 ;
++ si, code <<= 1)
{
for ( ; huffsizes [kk] == si ; ++ code, ++ kk)
{
huffcodes [kk] = code ;
}
}
// Section C.2 Figure C.3
memset (ehufco, 0, sizeof (ehufco)) ;
memset (ehufsi, 0, sizeof (ehufsi)) ;
for (kk = 0 ; kk < JpegMaxNumberOfHuffmanCodes ; ++ kk)
{
if (huffsizes [kk] != 0)
{
unsigned int ii = huff_values [kk] ;
ehufco [ii] = huffcodes [kk] ;
ehufsi [ii] = huffsizes [kk] ;
}
}
// Validations
// This remaining code is not necessary other than to ensure the
// integrity of the Huffman table that is generated.
// Make sure each value is used exactly once.
for (ii = 0 ; ii < JpegMaxNumberOfHuffmanCodes ; ++ ii)
{
int count = 0 ;
if (tmp [ii] != 0)
{
if (ehufsi [ii] == 0)
throw EJpegFatal ("INTERNAL ERROR - Missing Huffman Code Size") ;
for (unsigned int jj = 0 ; jj < JpegMaxNumberOfHuffmanCodes ; ++ jj)
{
if (ii == huff_values [jj] && huffsizes [jj] != 0)
++ count ;
if (count > 1)
throw EJpegFatal ("INTERNAL ERROR - Duplicate Huffman Value") ;
}
if (count == 0)
throw EJpegFatal ("INTERNAL ERROR - Missing Huffman Value") ;
}
}
// Ensure that each huffman code is used once annd that the values
// are in range.
for (ii = 0 ; ii < JpegMaxNumberOfHuffmanCodes ; ++ ii)
{
if (ehufsi [ii] != 0)
{
if (ehufsi [ii] > JpegMaxHuffmanCodeLength)
throw EJpegFatal ("INTERNAL ERROR - Invalid Huffman Range") ;
for (int jj = ii + 1 ; jj < JpegMaxNumberOfHuffmanCodes ; ++ jj)
{
if (ehufco [ii] == ehufco [jj] && ehufsi [jj] != 0)
throw EJpegFatal ("INTERNAL ERROR - Duplicate Huffman Code") ;
}
}
}
sizes_found = true ;
return ;
}
//
// Description:
//
// This function returns the Huffman Code and Code Size for a given value.
//
// Parameters:
// value: The value to encode
// code: The Huffman Code
// size: The Huffman Code Length
//
void JpegEncoderHuffmanTable::Encode (unsigned int value,
UBYTE2 &code,
UBYTE1 &size) const
{
if (value >= JpegMaxNumberOfHuffmanCodes)
throw EJpegIndexOutOfRange () ;
if (ehufsi [value] == 0)
throw EJpegFatal ("INTERNAL ERROR - Missing Huffman Code") ;
code = ehufco [value] ;
size = ehufsi [value] ;
return ;
}
//
// Description:
//
// This function writes the Huffman table data to the output stream in the
// format specified by the JPEG standard.
//
// Parameters:
// encoder: The JpegEncoder that defines the output stream.
//
void JpegEncoderHuffmanTable::PrintTable (JpegEncoder &encoder) const
{
// We need this declaration here because MSVC++ does not support
// standard scoping in for statements.
unsigned int ii ;
// B.2.4.2
UBYTE1 data ;
unsigned int count = 0 ; // Number of codes in the table.
// Write 16 1-byte values containing the count of codes for
// each possible Huffman code length and count the number of
// codes used.
for (ii = 0 ; ii < JpegMaxHuffmanCodeLength ; ++ ii)
{
count += huff_bits [ii] ;
data = huff_bits [ii] ;
encoder.OutputByte (data) ;
}
// Write the variable length part of the table, the Huffman values
// sorted by Huffman Code.
for (ii = 0 ; ii < count ; ++ ii)
{
data = huff_values [ii] ;
encoder.OutputByte (data) ;
}
return ;
}
//
// Description:
//
// This function determines the size of the Huffman table when it is
// written to a DHT marker. This function is used to calculate the
// 2-byte marker length that comes right after the FF-DHT sequence in
// the output stream. Therefore we need to find the length before we
// actually write the table.
//
unsigned int JpegEncoderHuffmanTable::OutputSize () const
{
unsigned int count = 0 ;
for (unsigned int ii = 0 ; ii < JpegMaxHuffmanCodeLength ; ++ ii)
{
count += huff_bits [ii] ;
}
// 1 byte for each value + one byte for each of 16 code lengths +
// 1 byte for the table class and ID.
return count + JpegMaxHuffmanCodeLength + 1 ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -