satdump/plugins/stereo_support/stereo/instruments/secchi/rice_decomp.cpp
2023-08-22 15:52:36 -04:00

886 lines
34 KiB
C++

/********************************************************************
*
* MODULE NAME : RECON.C
*
* TITLE : Reconstruction (De-Compression) Software for SOHO LASCO/EIT
*
* CC # : ??
*
* AUTHOR : Mitchell R Grunes (ATSC/NRL)
* Karl Hoppel (NRL)
*
* DATE : 07/11/96
*
* PURPOSE : This is the software to perform image reconstruction
* for the LASCO/EIT experiments on board the ESA/NASA
* SOHO spacecraft. It will be run on the ground.
* FUNCTIONAL
* DESCRIPTION : A sample call is located in sohorecon.c.
*
* CONTROL DATE : 07/11/96
*
* REVISION
* HISTORY : It is requsted by NRL that Lockheed/Avionics make
* no revisions to this file.
*
*************************************************************************/
/*============================================================================
The documentation for the interface to this software is contained in file
sohorecon.c and in the final report.
NOTE: Although we have used named parameters for clarity, they cannot be easily
changed, because some other parameters here and elsewhere depend on them,
increasing values could produce arithmetic overflows, and because the DCT size
must match BlkSz. Furthermore, the compression and reconstruction programs
must also match.*/
/*============================================================================*/
/* #define DEBUG 0 */
#define PRINTBAT 1 /*To print bit allocation table. \
This might be set to 0 for the final \
code. */
#define UseCheckSum /*Don't process a packet if it contains \
a CheckSum. If errors turn out to \
be very common, we will have to think \
about this. */
/*The following #define's must be the same as in the calling program
(sohorecon.c): */
#include "logger.h"
#include <stdio.h>
#include <stdlib.h>
#include "rice_decomp.h"
#ifndef _MSC_VER
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#endif
namespace soho_compression
{
/* =======================Form of Call=======================
void Recon(int *ncol, int *nrow, int *SignFlag, uword Image[]);
void Recon(&ncol,&nrow,SignFlag,Image);
======================Input Variables=====================
none--all input will come from routine ReadPack.
=====================Output Variables=====================
ncol,nrow =# of columns and rows of pixels in transmitted image.
Image =Array holding the output image.
The pixel in 0-origin column i and 0-origin row j will
be stored at Image[i+j*(long)ncol]. */
/*============================================================================*/
void SOHORiceDecompressor::Recon(int *ncol2, int *nrow2, int *SignFlag2, uword Image[])
{
/*Reconstruct an image */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
long *Block0, Pix;
uword *Image0;
int i, j, iBlkVold, iblkold;
int nBlock, nBlockGood;
long nPixel;
FoundHeader = 0;
iBlkVold = -1;
iblkold = -1;
Valid = 1;
nBlock = 0;
nBlockGood = 0;
a:
StartPacket();
// Aang23 : Prevent div by 0
if ((BCol2 - BCol1 + 1) == 0)
{
output_was_valid = false;
*ncol2 = 0;
*nrow2 = 0;
return;
}
iBlkV = iblk / (BCol2 - BCol1 + 1); /*Convert block # to block row and */
iBlkH = iblk % (BCol2 - BCol1 + 1); /* block column # */
if (AtEnd == 0)
{
nBlock++;
ReconPacket(); /*Reconstruct (De-compress) block */
if (Valid == 0)
{ /*Was not a valid packet: */
nBitP = 0;
goto a;
}
if (Valid && iblk < MaxBlk)
{
#if ENABLE_PRINTF_OUT
if (iBlkV != iBlkVold)
printf("\nBlock Row %d Col ", iBlkV);
printf("%d ", iBlkH);
#endif
iBlkVold = iBlkV;
if (iBlkH >= ncol / BlkSz || iBlkV >= nrow / BlkSz)
{
Error((char *)"Out of range block # (%d)", 0, iblk, 0);
goto a;
}
if (UseBlock(iBlkH, iBlkV) == 0)
{
Error((char *)"Block was not usable (occulted)", 0, 0, 0);
goto a;
}
if (iblkold >= iblk)
Error((char *)"Out of sequence Block #", 0, 0, 0);
iblkold = iblk;
for (j = 0; j < BlkSz; j++)
{ /*Copy Block into Image */
Image0 = &Image[iBlkH * BlkSz + (j + iBlkV * BlkSz) * (long)ncol];
Block0 = &Block[j * BlkSz];
for (i = 0; i < BlkSz; i++)
{
Pix = Block0[i];
if ((Pix < (long)(ulong)MinPixAll) || (Pix > (long)(ulong)MaxPixAll))
{
if (Method >= 2)
{ /*Lossy--just clip */
if (Pix < (long)(ulong)MinPixAll)
Pix = (long)(ulong)MinPixAll;
else
Pix = (long)(ulong)MaxPixAll;
}
else
{ /*Lossless--should not happen */
Error((char *)"Out of Bounds Pixel Value (%ld at pixel %d)",
0, (int)Pix, i);
}
}
if (SqrtFlag)
Pix = Pix * Pix + Pix;
if (nshift)
Pix = (Pix << (long)nshift) + TwoP[nshift - 1];
if (SignFlag)
Pix -= 32768L;
Image0[i] = (uword)Pix;
}
}
}
if (Valid)
nBlockGood++;
goto a;
}
nPixel = ncol * (long)nrow;
#if ENABLE_PRINTF_OUT
printf("\nreconstructed image took %ld bytes.\n", nPixel * 2);
printf("(Following #'s do not include Science Packet overhead)\n");
printf("Compressed image took %ld bytes (%ld without packet overhead),\n",
MaxPTot, (MaxPTo2 + 7) / 8);
printf(" which is %lf bits/pixel.\n",
(double)MaxPTot * 8. / (double)(nPixel));
printf("Compression Factor=%lf from 16 bits/pixel",
(2. * nPixel) / MaxPTot);
printf(" (%lf from %d).\n", (nPixel * 2. * nBitPix) / (MaxPTot * 16), nBitPix);
printf("Without packet overhead bpp=%lf CF=%lf\n",
(MaxPTo2) / ((double)nPixel), ((double)nPixel) * 16. / (MaxPTo2));
#endif
if (nBlock < (ncol / BlkSz) * (nrow / BlkSz))
{
nPixel = (long)nBlock * (long)nPixBlk;
#if ENABLE_PRINTF_OUT
printf("If we only consider the %d transmitted blocks, we get:\n", nBlock);
printf(" %lf bits/pixel.\n",
(double)MaxPTot * 8. / nPixel);
printf(" Compression Factor=%lf from 16 bits/pixel",
(2. * nPixel) / MaxPTot);
printf(" (%lf from %d).\n", (nPixel * 2. * nBitPix) / (MaxPTot * 16), nBitPix);
printf(" Without packet overhead bpp=%lf CF=%lf\n",
(MaxPTo2) / ((double)nPixel), ((double)nPixel) * 16. / (MaxPTo2));
#endif
}
#if ENABLE_PRINTF_OUT
printf("--%d out of %d blocks were good--\n", nBlockGood, nBlock);
#endif
*ncol2 = ncol; /*Copy statics back to caller */
*nrow2 = nrow;
*SignFlag2 = SignFlag;
}
/*============================================================================*/
void SOHORiceDecompressor::StartPacket()
{ /*Start a Compression Packet */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
// static unsigned long totalnWdP = 0l;
int nWdP;
OldValid = Valid;
ReadPack(Pack, &Valid, &AtEnd, &nByteP, &nBitP, &nBytePacket);
if (AtEnd)
return;
nByteP = nBitP = Ended = CheckSum = 0;
nBytePacket = 4;
iblk = RdBit(nBksBit);
#ifdef DEBUG
printf("StartPacket: iblk = %u\n", iblk);
#endif
if (FoundHeader == 0 && iblk != 2045 && iblk != 2047)
{
#if ENABLE_PRINTF_OUT
Error("Have not yet read image header packet!", 0, 0, 0);
#endif
}
else
{
nWdP = RdBit(MaxWBit);
CheckSum -= nWdP; /*Was 0 at time checksum written */
nBytePacket = nWdP * 2;
MaxPTot += nBytePacket;
MaxPTo2 += nBytePacket * 8 - nBksBit - MaxWBit - 4;
#ifdef DEBUG
printf("StartPacket(): nWdP = %u total_bytes %lu Start CheckSum = %d\n",
nWdP, MaxPTot, CheckSum);
#endif
}
}
/*============================================================================*/
void SOHORiceDecompressor::EndPacket()
{ /*End a Compression Packet */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
int CheckSumAct, idummy;
if (AtEnd != 0 || Ended != 0)
return;
Ended = 1;
CheckSumAct = 15 & ((CheckSum) + (CheckSum >> 4) +
(CheckSum >> 8) + (CheckSum >> 12));
CheckSum = RdBit(4);
#ifdef DEBUG
printf("EndPacket(): Calc checksum = %u Block Checksum = %u\n", CheckSumAct, CheckSum);
#endif
if ((nByteP + 1) / 2 * 2 != nBytePacket)
Error((char *)"Wrong # of words in Packet", 0, 0, 0);
if (CheckSumAct != CheckSum)
{
#ifdef UseCheckSum
Error((char *)"Error:Invalid CheckSum: (Nominal, Actual)", 0, CheckSum, CheckSumAct);
#endif
#ifndef UseCheckSum
Warning("Invalid CheckSum: Nominal %d Actual %d", CheckSum, CheckSumAct);
#endif
}
/*Flush to start of next word */
while (((nBitP != 0) || nByteP % 2 != 0) && AtEnd == 0)
idummy = RdBit(1);
}
/*============================================================================*/
void SOHORiceDecompressor::ReconPacket()
{ /*Reconstruct one block of pixels.
--OUTPUTS--
Block= BlkSz*BlkSz element block of
image pixels, stored in BlkSz*BlkSz*2
contiguous bytes.
--ALSO MODIFIED OR USED--
nBitP,Pack,CheckSum,Method */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
if (AtEnd)
return;
if (iblk < MaxBlk)
{ /*Valid packet type */
if (Method == 0)
{ /*Uncompressed data */
NoRecon();
}
else if (Method == 1)
{ /*Rice Reconstruction */
RiceRecon();
}
else
{
#if ENABLE_PRINTF_OUT
Error("Invalid reconstruction method", 0, 0, 0);
#endif
}
}
else if (iblk == 2047)
{ /*Error Packet */
ErrorPacket();
}
else if (iblk == 2045)
{ /*Image Header Packet */
if (FoundHeader)
{
Error((char *)"Header has already been read!", 0, 0, 0);
}
else
{
FoundHeader = 1;
ImageHeader(&BCol1, &BCol2, &BRow1, &BRow2,
&MinPixAll, &MaxPixAll,
&Method, &SignFlag, &nshift, &SqrtFlag,
&ncol, &nrow, &Valid);
if (Method < 0 || Method > 3 || MinPixAll > MaxPixAll ||
SignFlag < 0 || SignFlag > 1 ||
nshift < 0 || nshift > 15 || SqrtFlag < 0 || SqrtFlag > 1 ||
ncol < 0 || ncol > maxncol || BCol1 < 0 || BCol1 > BCol2 ||
BCol2 >= MaxBlkH || BRow1 < 0 || BRow1 > BRow2 || BRow2 >= MaxBlkV)
Error((char *)"Incorrect header parameter", 0, 0, 0);
nBitPix = nBitNeed((ulong)(MaxPixAll - MinPixAll));
if (Valid == 0)
FoundHeader = 0;
}
}
else
{
if (Valid)
OtherBlock(iblk);
}
EndPacket();
}
/*============================================================================*/
#define RiceBlk 16 /*Rice block size (factor of BlkSz), \
one side */
#define RiceBlks (BlkSz / RiceBlk)
#define RiceBlks2 (RiceBlks * RiceBlks)
#define nRiceBit 4 /*log base 2 of RiceBlk */
#define nRiceBits 2 /*log base 2 of RiceBlks */
/*============================================================================*/
void SOHORiceDecompressor::RiceRecon()
{ /*Called by ReconPacket to Reconstruct
1 block using Rice Algorithm */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
uword Predict[nPixBlk]; /*Predict values for pixels */
uword MaxPix; /*Maximum pixel value */
uword MaxPixBit; /*# of bits needed to send MaxPix */
int nSum, Bit, i, ii, jj;
int RiceAdapt[RiceBlks2], MinAdapt;
uword MSB, MaxMSB, Adapt;
long Sum, Diff, Theta, Pix;
MaxPix = (uword)RdBit(nBitPix) + MinPixAll;
MaxPixBit = nBitNeed((ulong)MaxPix);
Pix = (ulong)((uword)RdBit(MaxPixBit) + MinPixAll);
Predict[0] = (uword)Pix;
Block[0] = Pix;
MinAdapt = RdBit(4);
Adapt = (uword)RdBit(3);
for (i = 0; i < RiceBlks2; i++)
RiceAdapt[i] = RdBit((int)Adapt) + MinAdapt;
for (i = 1; i < nPixBlk; i++)
{
jj = i >> nBlkBit;
ii = i - (jj << nBlkBit);
Sum = nSum = 0;
if (jj > 0)
{
if (ii > 0)
{
Sum += (long)(ulong)Predict[i - BlkSz - 1];
nSum++;
}
Sum += (long)(ulong)Predict[i - BlkSz];
nSum++;
if (ii < BlkSz - 1)
{
Sum += (long)(ulong)Predict[i - BlkSz + 1];
nSum++;
}
}
if (ii > 0)
{
Sum += (long)(ulong)Predict[i - 1];
nSum++;
}
Predict[i] = (uword)((Sum + (nSum >> 1)) / nSum);
jj = jj >> nRiceBit;
ii = ii >> nRiceBit;
Adapt = RiceAdapt[ii + (jj << nRiceBits)];
if (Adapt == 15u)
{
Pix = (ulong)((uword)RdBit(MaxPixBit) + MinPixAll);
}
else if (Adapt > 0u)
{
MSB = 0;
MaxMSB = MaxPix >> Adapt;
while ((Bit = RdBit(1)) == 0 && AtEnd == 0 && MSB < (uword)(MaxMSB - 1u))
MSB++;
if (Bit == 0)
MSB++;
Diff = (ulong)((uword)(MSB << Adapt) | (uword)RdBit(Adapt));
Theta = (long)(ulong)MaxPix - (long)(ulong)Predict[i];
if (Theta > (long)(ulong)Predict[i])
Theta = (long)(ulong)Predict[i];
if (Diff <= Theta + Theta)
{
if (Diff & 1)
Diff = -(Diff + 1) / 2;
else
Diff = Diff / 2;
}
else
{
Diff = Diff - Theta;
if (Theta != (long)(ulong)Predict[i])
Diff = -Diff;
}
Pix = (long)(ulong)Predict[i] + Diff;
}
else
{
Pix = (long)(ulong)Predict[i];
}
if (Pix > (long)(ulong)MaxPix)
{
Error((char *)"Out of bounds predict value (%d at pixel %d)", 0, (short)Pix, i);
return;
}
Predict[i] = (uword)Pix;
Block[i] = Pix;
}
}
/*============================================================================*/
void SOHORiceDecompressor::NoRecon()
{ /*Called by ReconPacket to use
uncompressed data */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
int i;
for (i = 0; i < nPixBlk; i++)
Block[i] = (long)(ulong)RdBit(16);
}
/*============================================================================*/
void SOHORiceDecompressor::ErrorPacket()
{ /*Read an error packet */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
long iblk2, error, Method, Phase, Process;
iblk2 = RdBitL(32);
error = RdBitL(32);
Method = RdBitL(32);
Phase = RdBitL(32);
Process = RdBitL(32);
#if ENABLE_PRINTF_OUT
Error("===Encountered Error Packet Error Code %d===", 0, (int)error, 0);
printf("iblk=%ld error=%ld Method=%ld Phase=%ld Process=%ld\n",
iblk2, error, Method, Phase, Process);
#endif
if (error == 1)
printf("Incorrect Method or Phase detected by InitComp\n");
if (error == 2)
printf("Incorrect Method, Phase or iblk detected by Comp\n");
if (error == 3)
printf("Out of range nByteP\n");
if (error == 4)
printf("ADCT Binary search for # of words did not converge\n");
if (error == 5)
printf("Invalid Scaling factor on initial packet\n");
if (error == 6)
printf("Invalid ADCT decision table scaling\n");
if (error == 7)
printf("Invalid ADCT coefficient scaling\n");
if (error == 8)
printf("Invalid ADCT Block Class\n");
if (error == 9)
printf("Invalid ADCT intermediate scaling\n");
if (error == 10)
printf("Incorrect block detected by Compress\n");
if (error == 11)
printf("Incorrect input parameters detected by Compress\n");
if (error == 12)
printf("Pixel value has more than nPixBit bits\n");
if (error == 13)
printf("Maximum pixel value has more than nPixBit bits\n");
if (error == 14)
printf("Average pixel value has too many bits\n");
}
/*============================================================================*/
void SOHORiceDecompressor::Error(char *Mes, int iexit, int Var1, int Var2)
{ /*Process error codes */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
if (Valid != 0 && OldValid != 0)
{ /*Don't keep giving errors if
This packet or the previous
one has already been flagged*/
printf("\n=ERROR=");
printf("%s %d %d", Mes, Var1, Var2);
printf("\n");
}
Valid = 0;
if (iexit != 0)
logger->critical("Wanted to exit!"); // exit(0);
}
/*============================================================================*/
void SOHORiceDecompressor::Warning(char *Mes, long Var1, long Var2)
{ /*Process warning codes */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
printf("\n\a====================WARNING====================\n");
printf(Mes, Var1, Var2);
printf("\n");
}
/*============================================================================*/
int SOHORiceDecompressor::RdBit(int ibit)
{ /*Read ival from Pack buffer in ibit
bits */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
uword nDiscard, ival, MSB;
if (ibit < 0 || ibit > 32)
Error((char *)"Invalid RdBit %d \n", 0, ibit, 0);
if (AtEnd)
return 0;
CheckSum += ibit;
ival = 0;
while (ibit > 0)
{
if (nBitP <= 0)
{
if (nByteP >= nBytePacket || nByteP < 0)
{
AtEnd = 1; /*End of file flag */
Error((char *)"Packet extended past end of file", 0, nByteP, nBytePacket);
}
NextByte = Pack[nByteP++];
nBitP = 8;
}
if (ibit <= nBitP)
{
nDiscard = nBitP - ibit;
MSB = NextByte >> nDiscard;
ival = (ival << (uword)ibit) | MSB;
NextByte -= MSB << nDiscard;
nBitP -= ibit;
ibit = 0;
}
else
{
ival = (ival << nBitP) | NextByte;
ibit -= nBitP;
nBitP = 0;
}
}
CheckSum += ival;
return (int)(unsigned)ival;
}
/*============================================================================*/
long SOHORiceDecompressor::RdBitL(int ibit)
{ /*Same as RdBit, for longs */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
long ival;
ival = 0;
if (ibit > 16)
{
ival = (long)RdBit(ibit - 16);
ibit = 16;
}
ival = (ival << 16) | (long)RdBit(ibit);
return ival;
}
/*============================================================================*/
int SOHORiceDecompressor::nBitNeed(ulong i)
{ /*# of bits needed to represent i
(i must be >= 0) */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
ulong j;
int need;
j = i;
need = 0;
while (j > 0)
{
j = j >> 1u;
need++;
}
return need;
}
///////////////////////////////////////////////////////// rice64.c
/*============================================================================*/
void SOHORiceDecompressor::ReadPack(uchar Pack[], int *Valid, int *AtEnd, int *nByteP,
int *nBitP, int *nBytePacket)
{ /*Read 1 packet into Pack.
Set AtEnd=0 if there was a packet,
1 if end of image reached.
For right now we ignore Science
super-packet structure, and we assume
no transmission errors. */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
static int FirstPacket = 1; /*First packet? */
static int byterev = 0; /*Need to byte reverse file? */
static long PrevStart; /*Previous packet start position */
int iblk, nWdP;
uchar c;
int i;
#ifndef SEEK_SET
#define SEEK_SET 0 /*Should be part of C language--but \
isn't for gcc. */
#endif
if (*Valid == 0)
{ /*Handle invalid packets */
*Valid = 1;
PrevStart += 2;
/*&&&printf("Re-trying at file position %ld\n",PrevStart); */
#if RICE_MEMORY_VERSION
if (bfseek(PrevStart, SEEK_SET))
#else
if (fseek(fp1, PrevStart, SEEK_SET))
#endif
Error((char *)"Bad fseek call", 1, 0, 0);
}
else
{
*Valid = 1;
}
#if RICE_MEMORY_VERSION
if ((PrevStart = bftell()) < 0)
#else
if ((PrevStart = ftell(fp1)) < 0)
#endif
Error((char *)"Bad ftell call", 1, 0, 0);
*AtEnd = 0; /*Initialize */
#if RICE_MEMORY_VERSION
if (bfeof() != 0 || bfread(Pack, (size_t)2, (size_t)2) != (size_t)2)
#else
if (feof(fp1) != 0 || fread(Pack, (size_t)2, (size_t)2, fp1) != (size_t)2)
#endif
{
*AtEnd = 1;
return;
}
if (byterev)
{
for (i = 0; i < 4; i += 2)
{
c = Pack[i];
Pack[i] = Pack[i + 1];
Pack[i + 1] = c;
}
}
*nByteP = *nBitP = 0;
*nBytePacket = 4; /*So we can use RdBit to get length */
iblk = RdBit(nBksBit); /*Block # */
if (FirstPacket)
{ /*Check for byte reversal */
if (iblk == 2045 || iblk == 2047)
{ /*Found first packet or error packet! */
FirstPacket = 0;
}
else
{ /*If not, try byte reversal */
for (i = 0; i < 4; i += 2)
{
c = Pack[i];
Pack[i] = Pack[i + 1];
Pack[i + 1] = c;
}
*nByteP = *nBitP = 0;
iblk = RdBit(nBksBit);
if (iblk == 2045 || iblk == 2047)
{
FirstPacket = 0;
byterev = 1;
/*printf("Words being byte reversed!\n");*/
}
else
{
Error((char *)"First block not image header--", 0, 0, 0);
}
}
}
nWdP = RdBit(MaxWBit);
if (nWdP > 2)
{
#if RICE_MEMORY_VERSION
if (bfread(&Pack[4], (size_t)(nWdP - 2), (size_t)2) != (size_t)2)
#else
if (fread(&Pack[4], (size_t)(nWdP - 2), (size_t)2, fp1) != (size_t)2)
#endif
{
Error((char *)"Packet extended past end of file", 0, 0, 0);
}
}
if (byterev)
{
*nBytePacket = nWdP * 2;
for (i = 4; i < *nBytePacket; i += 2)
{
c = Pack[i];
Pack[i] = Pack[i + 1];
Pack[i + 1] = c;
}
}
}
/*The user must supply an ImageHeader routine to read the image header packet:
=======================Form of Call=======================
void ImageHeader(int *BCol1, int *BCol2, int *BRow1, int *BRow2,
uword *MinPixAll, uword *MaxPixAll,
int *Method, int *SignFlag, int *nshift, int *SqrtFlag,
int *ncol, int *nrow, int *Valid);
ImageHeader(&BCol1,&BCol2,&BRow1,&BRow2,
&MinPixAll,&MaxPixAll,
&Method,&SignFlag,&nshift,&SqrtFlag)
&ncol,&nrow,&Valid);
======================Input Variables=====================
Input is through RdBit routine
Valid =non-zero if everything in block was valid--may be
changed by RdBit mid-way through.
============================Output=============================
BCol1 =Starting 0-Origin block column number.
BCol2 =Ending 0-Origin block column number.
Means software will transmit 0-origin columns
BCol1*BlkSz to BCol2*BlkSz+BlkSz-1
BRow1 =Starting 0-Origin block row number.
BRow2 =Ending 0-Origin block row number.
Means software will transmit 0-origin rows
BRow1*BlkSz to BRow2*BlkSz+BlkSz-1
MaxPixAll=Maximum pixel value
MinPixAll=Minimum pixel value:
Method =Compression Method.
0=Uncompressed (used only to debug system)
1=(Rice Algorithm) Lossless Compression
2=(ADCT Algorithm) Lossy Compression
3-7 Reserved
SignFlag=0 if image pixels unsigned, non-zero if signed
nshift =# of bits input should be is to be right shifted
SqrtFlag=non-zero if square root is to be taken
ncol =# of columns in output image&&&
nrow =# of rows in output image
Our example follows. The user may change ImageHeader to match a particular
format. If that is done, the ImageHeader routine in the compression program
must also be changed. This program, if modified, must still set all of the
variables included in this example: */
/*============================================================================*/
void SOHORiceDecompressor::ImageHeader(int *BCol1, int *BCol2, int *BRow1, int *BRow2,
uword *MinPixAll, uword *MaxPixAll,
int *Method, int *SignFlag, int *nshift, int *SqrtFlag,
int *ncol, int *nrow, int * /*Valid*/)
{ /*Reconstruct Image Header Packet */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
long index;
uword *Image0;
*Method = RdBit(3);
*BCol1 = RdBit(nBitNeed((ulong)(MaxBlkH - 1)));
*BCol2 = RdBit(nBitNeed((ulong)(MaxBlkH - 1)));
*BRow1 = RdBit(nBitNeed((ulong)(MaxBlkV - 1)));
*BRow2 = RdBit(nBitNeed((ulong)(MaxBlkV - 1)));
*ncol = (*BCol2 - *BCol1 + 1) * BlkSz;
*nrow = (*BRow2 - *BRow1 + 1) * BlkSz;
*MaxPixAll = (uword)RdBit(16);
*MinPixAll = (uword)RdBit(nBitNeed((ulong)*MaxPixAll));
*SignFlag = RdBit(1);
*nshift = RdBit(4);
*SqrtFlag = RdBit(1);
#if ENABLE_PRINTF_OUT
printf("Method=%d BCol1=%d BCol2=%d BRow1=%d BRow2=%d ncol=%d nrow=%d\n",
*Method, *BCol1, *BCol2, *BRow1, *BRow2, *ncol, *nrow);
printf("MinPixAll=%hu MaxPixAll=%hu SignFlag=%d nshift=%d SqrtFlag=%d\n",
*MinPixAll, *MaxPixAll, *SignFlag, *nshift, *SqrtFlag);
#endif
#ifdef DEBUG2
/* test pattern */
printf("Checking DEBUG2 ImageHeader\n");
uword icount = 0, power[12];
uword power2[12] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};
for (icount = 0; icount < 12; icount++)
{
power[icount] = RdBit(nBitNeed(power2[icount]));
if (power[icount] != power2[icount])
{
printf("Imageheader() : DEBUG2 error\n");
}
}
#endif
// Aang23 : FIX OVERFLOW
if (maxncol < *ncol || maxnrow < *nrow || *nrow < 0 || *ncol < 0)
{
output_was_valid = false;
*ncol = maxncol;
*nrow = maxnrow;
}
Image0 = Image; /*Zero fill image. */
for (index = *ncol * (long)*nrow; index; index--)
{
*Image0 = 0;
Image0++;
}
EndPacket();
#if ENABLE_PRINTF_OUT
if (*Valid)
printf("(Successful Read of Image Header Packet)--\n");
printf("--------------------------------------------------------\n");
#endif
}
/*The user must supply an OtherBlock routine to handle block types (as stated
earlier, code 7666 is free to assign other block types 2021-2040) not specified
by code 7230. Our example simply prints a message: */
/*============================================================================*/
void SOHORiceDecompressor::OtherBlock(int /*iblk*/)
{ /*Interpret other types of block */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
static unsigned int firstOther = 0;
#if ENABLE_PRINTF_OUT
if (firstOther == 0)
printf("\n--Undefined Block type %d- ", iblk);
else
printf("%d-");
#endif
firstOther++;
}
/*The user must supply a UseBlock routine to specify which blocks may have been
sent. (Certain blocks in the images will be occulted, and so do not need to be
sent.) All blocks in the ranges specified by BCol, BCol2, BRow1 and BRow2 will
have been sent unless the UseBlock routine returned zero on board the
spacecraft; ideally UseBlock should return the same values on the ground so that
invalid block numbers will be detectable. However, if no transmission errors
occur, that will not be necessary.
=======================Form of Call=======================
result=UseBlock(iBlkH,iBlkV)
======================Input Variables=====================
iBlkH =(int) 0-origin sub-image block column #
iBlkV =(int) 0-origin sub-image block row #
(The sub image block referred to by iBlkH,iBlkV includes the following pixels:
Image[iBlkH*BlkSz to (iBlkH+1)*BlkSz-1, iBlkV*BlkSz to (iBlkV+1)*BlkSz-1]
=====================Output Variables=====================
result =(int)0 if block is not to be transmitted.
non-zero if block is to be sent
In our example, UseBlock will always indicate that the block number was valid:*/
/*============================================================================*/
int SOHORiceDecompressor::UseBlock(int /*iBlkH*/, int /*iBlkV*/)
{ /*Return 0 if sub-image block is to be
sent, else return non-zero. */
/* Written by Mitchell R Grunes, ATSC/NRL, 07/11/96 */
return 1; /*For this example we always send. */
}
}
#ifndef _MSC_VER
#pragma GCC diagnostic pop
#endif