mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
526 lines
17 KiB
C
526 lines
17 KiB
C
/*
|
|
Bit plane encoder
|
|
Please note:
|
|
(1) Before you download and use the program, you must read and agree the license agreement carefully.
|
|
(2) We supply the source code and program WITHOUT ANY WARRANTIES. The users will be responsible
|
|
for any loses or damages caused by the use of the source code and the program.
|
|
|
|
Author:
|
|
Hongqiang Wang
|
|
Department of Electrical Engineering
|
|
University of Nebraska-Lincoln
|
|
Email: hqwang@bigred.unl.edu, hqwang@eecomm.unl.edu
|
|
|
|
Your comment and suggestions are welcome. Please report bugs to me via email and I would greatly appreciate it.
|
|
Nov. 3, 2006
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include "global.h"
|
|
|
|
extern void BlockScanEncode(StructCodingPara *PtrCoding, BitPlaneBits *BlockInfo);
|
|
|
|
extern void StagesEnCoding(StructCodingPara *PtrCoding, BitPlaneBits *BlockInfo);
|
|
|
|
extern void StagesDeCoding(StructCodingPara *PtrCoding, BitPlaneBits *BlockInfo);
|
|
|
|
void ACDepthEncoder(StructCodingPara *PtrCoding, BitPlaneBits *BlockInfo);
|
|
|
|
short ACDepthDecoder(StructCodingPara *PtrCoding, BitPlaneBits *BlockInfo);
|
|
|
|
void ACGaggleEncoding(StructCodingPara *PtrCoding,
|
|
BitPlaneBits *BlockInfo,
|
|
int StartIndex,
|
|
int gaggles,
|
|
int Max_k,
|
|
int ID_Length)
|
|
{
|
|
int i = 0;
|
|
int k = 0;
|
|
int min_k = 0;
|
|
|
|
DWORD32 min_bits = 0xFFFF;
|
|
DWORD32 total_bits = 0;
|
|
|
|
/* --- Begin bug fix (Kiely) --- */
|
|
UCHAR8 uncoded_flag = ~0; // this is the flag indicating that uncoded option used
|
|
|
|
// determine code choice min_k to use, either via brute-force optimum calculation, or heuristic approach
|
|
// nkeffix : typo, it should be OptACSelect see 122x0b1c3 section 4.2.4.1.2
|
|
if(PtrCoding->PtrHeader->Header.Part3.OptACSelect == TRUE) { // brute-force optimum code selection
|
|
min_k = uncoded_flag; // uncoded option used, unless we find a better option below
|
|
|
|
for ( k = 0; k <= Max_k; k ++)
|
|
{
|
|
if (StartIndex==0)
|
|
total_bits = PtrCoding->N; // cost of uncoded first sample
|
|
else
|
|
total_bits = 0;
|
|
|
|
for (i = max(StartIndex,1); i < StartIndex + gaggles; i ++)
|
|
total_bits += ((BlockInfo[i].MappedAC >> k ) + 1) + k; // coded sample cost
|
|
|
|
if((total_bits < min_bits) && (total_bits < PtrCoding->N * gaggles)) {
|
|
min_bits = total_bits;
|
|
min_k = k;
|
|
}
|
|
}
|
|
} else { // heuristic code option selection
|
|
int delta = 0;
|
|
int J = gaggles;
|
|
int offset = 0;
|
|
|
|
if (StartIndex==0)
|
|
{
|
|
J = gaggles-1;
|
|
offset = 1;
|
|
}
|
|
|
|
// nkeffix : As specified in 122x0b1c3 section 4.2.4.1.2 the method for
|
|
// CODING QUANTIZED DC COEFFICIENTS specified in 4.3.2 is used for coding BitDepthAC_Block.
|
|
// In eq.20 in 4.3.2.11 Delta sum for the first gaggle should not include the first uncoded value.
|
|
for (i = StartIndex + offset; i < StartIndex + gaggles; i ++)
|
|
delta += BlockInfo[i].MappedAC;
|
|
|
|
if (64*delta >= 23*J*(1<<(PtrCoding->N)))
|
|
min_k = uncoded_flag; // indicate that uncoded option is to be used
|
|
else if (207 * J > 128 * delta)
|
|
min_k = 0;
|
|
else if ((long)(J * (1<<(PtrCoding->N + 5))) <= (long)(128 * delta + 49 * J))
|
|
min_k = PtrCoding->N - 2;
|
|
else {
|
|
min_k = 0;
|
|
while ((long)(J * (1 << (min_k + 7))) <= (long)(128 * delta + 49 * J))
|
|
min_k++;
|
|
min_k--;
|
|
}
|
|
}
|
|
|
|
// Indicate the selected coding option
|
|
BitsOutput(PtrCoding, min_k, ID_Length); // code choice
|
|
|
|
// Now output coded (or uncoded) values
|
|
for (i = StartIndex; i < StartIndex + gaggles; i ++){
|
|
if ((min_k == uncoded_flag) || (i==0))
|
|
BitsOutput(PtrCoding, BlockInfo[i].MappedAC, PtrCoding->N); // uncoded
|
|
else
|
|
BitsOutput(PtrCoding, 1, ((BlockInfo[i].MappedAC) >> min_k)+1); // coded (first part)
|
|
}
|
|
// if we have coded samples, then we also have to send the second part
|
|
if (min_k != uncoded_flag)
|
|
for (i = max(StartIndex,1); i < StartIndex + gaggles; i ++)
|
|
BitsOutput(PtrCoding, BlockInfo[i].MappedAC, min_k);
|
|
/* --- End bug fix (Kiely) --- */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DPCM_ACMapper(BitPlaneBits *BlockInfo,
|
|
int size,
|
|
short N)
|
|
{
|
|
short *diff_AC;
|
|
short theta = 0;
|
|
long i;
|
|
int X_Min = 0;
|
|
int X_Max = ((1 << N) - 1) ;
|
|
|
|
diff_AC = (short *)calloc(size,sizeof(short));
|
|
diff_AC[0] = BlockInfo[0].BitMaxAC;
|
|
BlockInfo[0].MappedAC = BlockInfo[0].BitMaxAC;
|
|
for(i = 1; i < size; i ++)
|
|
diff_AC[i] = BlockInfo[i].BitMaxAC - BlockInfo[i-1].BitMaxAC;
|
|
|
|
for ( i = 1; i < size; i ++) {
|
|
theta = min(BlockInfo[i-1].BitMaxAC - X_Min, X_Max - BlockInfo[i-1].BitMaxAC);
|
|
if (diff_AC[i] >= 0 && diff_AC[i] <= theta)
|
|
BlockInfo[i].MappedAC = 2 * diff_AC[i];
|
|
else if(diff_AC[i] < 0 && diff_AC[i] >= -theta)
|
|
BlockInfo[i].MappedAC = - 2 * diff_AC[i] - 1;
|
|
else
|
|
BlockInfo[i].MappedAC = theta + abs(diff_AC[i]);
|
|
}
|
|
free(diff_AC);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void ACDepthEncoder(StructCodingPara *PtrCoding,
|
|
BitPlaneBits *BlockInfo)
|
|
{
|
|
SINT GaggleStartIndex;
|
|
UCHAR8 Max_k;
|
|
UCHAR8 ID_Length;
|
|
UCHAR8 gaggles ; // initial value is 15.
|
|
|
|
PtrCoding->N = 0;
|
|
while( PtrCoding->PtrHeader->Header.Part1.BitDepthAC_5Bits>>PtrCoding->N > 0)
|
|
PtrCoding->N++;
|
|
|
|
DPCM_ACMapper(BlockInfo, PtrCoding->PtrHeader->Header.Part3.S_20Bits, PtrCoding->N);
|
|
|
|
if ( PtrCoding->N == 2) {
|
|
Max_k = 0;
|
|
ID_Length = 1;
|
|
}
|
|
else if (PtrCoding->N <=4) {
|
|
Max_k = 2;
|
|
ID_Length = 2;
|
|
}
|
|
else if (PtrCoding->N <=5) {
|
|
Max_k = 6;
|
|
ID_Length = 3;
|
|
}
|
|
else {
|
|
ErrorMsg(BPE_DATA_ERROR);
|
|
// added the following two lines to eliminate a compiler warning message
|
|
Max_k = 0;
|
|
ID_Length = 0;
|
|
}
|
|
|
|
/* --- Begin bug fix (Kiely) --- */
|
|
GaggleStartIndex = 0;
|
|
while( GaggleStartIndex < PtrCoding->PtrHeader->Header.Part3.S_20Bits ){
|
|
gaggles = min(GAGGLE_SIZE, PtrCoding->PtrHeader->Header.Part3.S_20Bits - GaggleStartIndex);
|
|
ACGaggleEncoding(PtrCoding, BlockInfo, GaggleStartIndex, gaggles, Max_k, ID_Length);
|
|
if(PtrCoding->SegmentFull == TRUE)
|
|
return;
|
|
GaggleStartIndex += gaggles;
|
|
}
|
|
/* --- End bug fix (Kiely) --- */
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void ACBpeEncoding(StructCodingPara *PtrCoding, BitPlaneBits *BlockInfo)
|
|
{
|
|
DWORD32 i = 0;
|
|
UCHAR8 BitPlane = 0;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
// The link nodes PlaneSym are used to coding of the bit planes. Contains a
|
|
// Link data structure. It encodes more than 16 blocks at this time.
|
|
// Need to modify it to encode up to 16 blocks only. May 20 2004
|
|
if (PtrCoding->PtrHeader->Header.Part1.BitDepthAC_5Bits != 0)
|
|
// bit plane encoder is not necessary if BitDepthAC = 0.
|
|
{
|
|
if (PtrCoding->PtrHeader->Header.Part1.BitDepthAC_5Bits == 1)
|
|
//only the lowest bit plane has valud AC component manitude.
|
|
for ( i = 0; i < PtrCoding->PtrHeader->Header.Part3.S_20Bits; i++)
|
|
BitsOutput(PtrCoding, BlockInfo[i].BitMaxAC, 1);
|
|
else
|
|
// returned is the mapped ac value.
|
|
ACDepthEncoder(PtrCoding, BlockInfo);
|
|
|
|
// 3.2 Family tree scaning sequence in a segment.
|
|
|
|
for ( BitPlane = PtrCoding->PtrHeader->Header.Part1.BitDepthAC_5Bits ;
|
|
BitPlane > 0; BitPlane --)
|
|
{
|
|
PtrCoding->BitPlane = BitPlane;
|
|
if((PtrCoding->PtrHeader->Header.Part2.BitPlaneStop_5Bits == BitPlane)
|
|
// nkeffix : No need to check again BitPlaneStop_5Bits is either the default value 0 or
|
|
// or the specified value in the header
|
|
//&&(PtrCoding->PtrHeader->Header.Part1.Part2Flag == TRUE))
|
|
)
|
|
return;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
////////////////////////// Stage 0 ///////////////////////////////////
|
|
// encode the DC component (single bit only)
|
|
// if ( B && ( A || (C && D) ) ){}
|
|
if ( (BitPlane <= PtrCoding->QuantizationFactorQ) &&
|
|
((PtrCoding->PtrHeader->Header.Part4.DWTType != INTEGER_WAVELET) ||
|
|
((PtrCoding->QuantizationFactorQ >
|
|
PtrCoding->PtrHeader->Header.Part4.CustomWtLL3_2bits ) &&
|
|
(PtrCoding->PtrHeader->Header.Part4.CustomWtLL3_2bits < BitPlane)) )
|
|
)
|
|
{
|
|
// output the DC bits that have been shifted out
|
|
for(i = 0; i < PtrCoding->PtrHeader->Header.Part3.S_20Bits; i++)
|
|
BitsOutput(PtrCoding, ((BlockInfo[i].DCRemainder >> (BitPlane - 1)) & 0x01), 1);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
if(PtrCoding->SegmentFull == TRUE)
|
|
return;
|
|
|
|
BlockScanEncode(PtrCoding, BlockInfo);
|
|
|
|
if(PtrCoding->SegmentFull == TRUE)
|
|
return;
|
|
|
|
// *************************** 4. Stages coding *********************************//
|
|
StagesEnCoding(PtrCoding, BlockInfo);
|
|
|
|
if(PtrCoding->SegmentFull == TRUE)
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CheckUsefill(StructCodingPara * PtrCoding)
|
|
{
|
|
|
|
if(PtrCoding->PtrHeader->Header.Part2.SegByteLimit_27Bits != 0
|
|
&& PtrCoding->PtrHeader->Header.Part2.UseFill == TRUE)
|
|
{
|
|
if((PtrCoding->PtrHeader->Header.Part2.SegByteLimit_27Bits << 3) <
|
|
PtrCoding->Bits->SegBitCounter)
|
|
{
|
|
int RemainderBits = 0;
|
|
DWORD32 TempWord = 0;
|
|
RemainderBits = PtrCoding->Bits->SegBitCounter
|
|
- (PtrCoding->PtrHeader->Header.Part2.SegByteLimit_27Bits <<3);
|
|
|
|
while(RemainderBits > 0)
|
|
{
|
|
BitsRead(PtrCoding, &TempWord, 1);
|
|
if(PtrCoding->SegmentFull == TRUE)
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
void ACGaggleDecoding(StructCodingPara *PtrCoding,
|
|
BitPlaneBits *BlockInfo,
|
|
int StartIndex,
|
|
int gaggles,
|
|
int Max_k,
|
|
short ID_Length)
|
|
{
|
|
long int i;
|
|
UCHAR8 min_k;
|
|
DWORD32 TempWord =0;
|
|
int counter = 0;
|
|
UCHAR8 ones = ~0;
|
|
BOOL uncoded = FALSE;
|
|
|
|
// makes the least ID_Length bits to ones.
|
|
ones = ((ones << (8 - ID_Length)) >> ((8 - ID_Length)));
|
|
|
|
BitsRead(PtrCoding, &TempWord, ID_Length);
|
|
|
|
min_k = (UCHAR8) TempWord;
|
|
|
|
if((ID_Length == 1 && min_k == 1) || (ID_Length == 2 && min_k == 3) ||
|
|
(ID_Length == 3 && min_k == 7) || (ID_Length == 4 && min_k == 15))
|
|
uncoded = TRUE;
|
|
|
|
/* --- Begin bug fix (Kiely) --- */
|
|
for( i = StartIndex; i < StartIndex + gaggles; i ++){
|
|
if ((uncoded == TRUE)||(i==0)){ // if first value in segment, then it's an uncoded reference
|
|
BitsRead(PtrCoding, &TempWord, PtrCoding->N);
|
|
BlockInfo[i].MappedAC = (WORD16) TempWord;
|
|
if(PtrCoding->RateReached == TRUE)
|
|
return;
|
|
} else {
|
|
// read first part
|
|
counter = 0;
|
|
// rice decoding
|
|
BitsRead(PtrCoding, &TempWord, 1);
|
|
while ((TempWord == 0)&&(PtrCoding->RateReached != TRUE)){
|
|
counter++;
|
|
BitsRead(PtrCoding, &TempWord, 1);
|
|
}
|
|
if (PtrCoding->RateReached == TRUE)
|
|
break;
|
|
BlockInfo[i].MappedAC = counter;
|
|
BlockInfo[i].MappedAC <<= min_k;
|
|
}
|
|
}
|
|
if(PtrCoding->RateReached == TRUE)
|
|
return;
|
|
// If we have coded samples, and we haven't reached the limit, then decode each second part
|
|
if ((uncoded == FALSE) && (PtrCoding->RateReached != TRUE)){
|
|
// i==0 indicates a reference sample, which was already decoded above
|
|
for( i = max(StartIndex,1); i < StartIndex + gaggles; i ++){
|
|
BitsRead(PtrCoding, &TempWord, min_k);
|
|
BlockInfo[i].MappedAC += (WORD16)TempWord;
|
|
if (PtrCoding->RateReached == TRUE)
|
|
break;
|
|
}
|
|
}
|
|
/* --- End bug fix (Kiely) --- */
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DPCM_ACDeMapper(BitPlaneBits *BlockCodingInfo, //UCHAR8 *ACmax_blocks,
|
|
int size,
|
|
short N)
|
|
{
|
|
short * diff_AC;
|
|
short theta = 0;
|
|
long i;
|
|
int X_Min = 0;
|
|
int X_Max = ((1 << N) - 1) ;
|
|
|
|
diff_AC = (short *)calloc(size,sizeof(short));
|
|
|
|
BlockCodingInfo[0].BitMaxAC = (UCHAR8)BlockCodingInfo[0].MappedAC;
|
|
|
|
for ( i = 1; i < size; i ++)
|
|
{
|
|
theta = min(BlockCodingInfo[i-1].BitMaxAC - X_Min, X_Max - BlockCodingInfo[i-1].BitMaxAC );
|
|
if((float)BlockCodingInfo[i].MappedAC / 2 == BlockCodingInfo[i].MappedAC / 2)
|
|
{
|
|
diff_AC[i] = (short)(BlockCodingInfo[i].MappedAC / 2);
|
|
if(diff_AC[i] >= 0 && diff_AC[i] <= theta)
|
|
{
|
|
BlockCodingInfo[i].BitMaxAC = diff_AC[i] + BlockCodingInfo[i - 1].BitMaxAC;
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
diff_AC[i] = - (short)((BlockCodingInfo[i].MappedAC + 1) / 2) ;
|
|
if(diff_AC[i] <= 0 && diff_AC[i] >= -theta)
|
|
{
|
|
BlockCodingInfo[i].BitMaxAC = diff_AC[i] + BlockCodingInfo[i - 1].BitMaxAC;
|
|
continue;
|
|
}
|
|
}
|
|
diff_AC[i] = (short)(BlockCodingInfo[i].MappedAC - theta);
|
|
|
|
BlockCodingInfo[i].BitMaxAC = diff_AC[i] + BlockCodingInfo[i - 1].BitMaxAC;
|
|
|
|
if( BlockCodingInfo[i].BitMaxAC < X_Min || BlockCodingInfo[i].BitMaxAC > X_Max)
|
|
{
|
|
diff_AC[i] = -diff_AC[i];
|
|
BlockCodingInfo[i].BitMaxAC = diff_AC[i] + BlockCodingInfo[i - 1].BitMaxAC;
|
|
}
|
|
}
|
|
free(diff_AC);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
short ACDepthDecoder(StructCodingPara *PtrCoding,
|
|
BitPlaneBits *BlockInfo)
|
|
{
|
|
SINT Max_k = 0;
|
|
UINT32 GaggleStartIndex = 0;
|
|
UCHAR8 ID_Length = 0;
|
|
WORD16 gaggles = 0;
|
|
|
|
PtrCoding->N = 0;
|
|
while( PtrCoding->PtrHeader->Header.Part1.BitDepthAC_5Bits >> PtrCoding->N > 0)
|
|
PtrCoding->N++;
|
|
|
|
if ( PtrCoding->N == 2) {
|
|
Max_k = 0;
|
|
ID_Length = 1;
|
|
}
|
|
else if (PtrCoding->N <=4) {
|
|
Max_k = 2;
|
|
ID_Length = 2;
|
|
}
|
|
else if (PtrCoding->N <=5) {
|
|
Max_k = 6;
|
|
ID_Length = 3;
|
|
}
|
|
else
|
|
ErrorMsg(BPE_DATA_ERROR);
|
|
|
|
|
|
/* --- Begin bug fix (Kiely) --- */
|
|
while( GaggleStartIndex < PtrCoding->PtrHeader->Header.Part3.S_20Bits ){
|
|
gaggles = min(GAGGLE_SIZE, PtrCoding->PtrHeader->Header.Part3.S_20Bits - GaggleStartIndex);
|
|
ACGaggleDecoding(PtrCoding, BlockInfo, GaggleStartIndex, gaggles, Max_k, ID_Length);
|
|
GaggleStartIndex += gaggles;
|
|
}
|
|
/* --- End bug fix (Kiely) --- */
|
|
|
|
DPCM_ACDeMapper(BlockInfo, PtrCoding->PtrHeader->Header.Part3.S_20Bits, PtrCoding->N);
|
|
|
|
return BPE_OK;
|
|
}
|
|
|
|
|
|
void ACBpeDecoding(StructCodingPara *PtrCoding,
|
|
BitPlaneBits *BlockCodingInfo)
|
|
{
|
|
UINT32 i = 0;
|
|
DWORD32 TempWord = 0;
|
|
UCHAR8 BitPlane = 0;
|
|
|
|
/////////// 3. Organize the AC component/////////////////////////////
|
|
// 3.1 Specify the number of bit planes in each block.
|
|
if(PtrCoding->RateReached == TRUE)
|
|
return;
|
|
if (PtrCoding->PtrHeader->Header.Part1.BitDepthAC_5Bits != 0) // bit plane encoder is not necessary if PtrHeader->Header.Part1.BitDepthAC_5Bits = 0.
|
|
{
|
|
if (PtrCoding->PtrHeader->Header.Part1.BitDepthAC_5Bits == 1)
|
|
{ //only the lowest bit plane has valud AC component manitude.
|
|
DWORD32 TempWord;
|
|
for ( i = 0; i < PtrCoding->PtrHeader->Header.Part3.S_20Bits; i++)
|
|
{
|
|
BitsRead(PtrCoding, &TempWord, 1);
|
|
BlockCodingInfo[i].BitMaxAC = (UCHAR8)TempWord;
|
|
}
|
|
}
|
|
else
|
|
ACDepthDecoder(PtrCoding, BlockCodingInfo);
|
|
}
|
|
if(PtrCoding->SegmentFull == TRUE)
|
|
return ;
|
|
|
|
// 3.2 Family tree scaning sequence in a segment.
|
|
|
|
for ( BitPlane = PtrCoding->PtrHeader->Header.Part1.BitDepthAC_5Bits; BitPlane > 0; BitPlane --)
|
|
{
|
|
// nkeffix : No need to check again BitPlaneStop_5Bits is either the default value 0 or
|
|
// or the specified value in the header
|
|
if(PtrCoding->PtrHeader->Header.Part2.BitPlaneStop_5Bits == BitPlane)
|
|
return;
|
|
|
|
if(PtrCoding->SegmentFull == TRUE || PtrCoding->RateReached == TRUE)
|
|
return;
|
|
|
|
PtrCoding->BitPlane = BitPlane;
|
|
|
|
// if ( B && ( A || (C && D) ) ){}
|
|
if ( (BitPlane <= PtrCoding->QuantizationFactorQ) &&
|
|
((PtrCoding->PtrHeader->Header.Part4.DWTType != INTEGER_WAVELET) ||
|
|
((PtrCoding->QuantizationFactorQ >
|
|
PtrCoding->PtrHeader->Header.Part4.CustomWtLL3_2bits ) &&
|
|
(PtrCoding->PtrHeader->Header.Part4.CustomWtLL3_2bits < BitPlane)) )
|
|
)
|
|
{
|
|
// read DC bits that have been shifted out
|
|
for(i = 0; i < PtrCoding->PtrHeader->Header.Part3.S_20Bits; i++)
|
|
{
|
|
if(PtrCoding->SegmentFull == TRUE)
|
|
break;
|
|
BitsRead(PtrCoding, &TempWord, 1);
|
|
BlockCodingInfo[i].DecodingDCRemainder += (WORD16)(TempWord << (BitPlane - 1)) ;
|
|
}
|
|
}
|
|
|
|
if(PtrCoding->SegmentFull != TRUE)
|
|
StagesDeCoding(PtrCoding, BlockCodingInfo);
|
|
}
|
|
CheckUsefill(PtrCoding);
|
|
return;
|
|
}
|
|
|