www.pudn.com > EZW_.rar > EZW.C
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/* EZW2 - Embedded Zerotree Wavelet Coder
*
* Author : Mow-Song, Ng
* Data : 20-07-2002
*
* Last update : 31-08-2002
*
* A large portion/idea of the codes come from:
* C. Valens - Embedded Zerotree Wavelet Encoder Tutorial.
* G. Davis - Baseline Wavelet Transform Coder Construction Kit
*
* The authors copyrights to the codes are acknowledged.
* The EZW coder is patented by Jerome Shapiro. As far as I know, these are
* the patent numbers
* 5315670 (Issued May 24, 1994), 5321776 (Issued June 14, 1994) and
* 5412741 (Issued May 2, 1995).
*
*
* Well, I wrote the coder with some one else codes, add some lines, remove
* some lines, sometimes just verbatim. Any way, if you feel that I am worth
* the acknowledgement, please do so, or perhaps drop me an e-mail.
*
* Please refer to my website for more info.
*
* My contact:
* msng@mmu.edu.my
* http://www.pesona.mmu.edu.my/~msng
*
*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
#include "ezw.h"
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
void EZW2Encode(WTRANSFORM *transform, ArithEncoder *encoder,
int threshold, int HistoCount, int ByteBudget,
int ScanOrder);
void EZW2BuildZerotreeMap(WTRANSFORM *transform, SubbandSymbol *ztmap);
void EncodeDominantPassMortonScan(DLNode *DomList, SLNode *SubList,
int *SubListSize, WTRANSFORM *transform,
MAP *map, int threshold,
ArithEncoder *encoder,
BasicCoder **DominantPassCoder,
SubbandSymbol *ztmap, int ByteBudget);
void EncodeNode(SLNode *SubList, int *SubListSize, WTRANSFORM *transform,
DLNode *node, SubbandSymbol *ztmap, int threshold);
void EncodeSubordinatePass(SLNode *SubList, int SubListSize, int threshold,
ArithEncoder *encoder, BasicCoder *SubordinateListCoder,
int ByteBudget);
void EZW2Error(char *fmt, ...);
void EZW2Warning(char *fmt, ...);
/* termination flag */
Boolean EndEncoding;
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
void main(int argc, char **argv)
{
FIMAGE *InputImage, *DecomposeImage;
WAVELET *wavelet;
WTRANSFORM *transform;
char InputImageFileName[_MAX_PATH];
char DecomposeImageFileName[_MAX_PATH];
char EncodeImageFileName[_MAX_PATH];
int NScale;
int ByteBudget;
Boolean KeepDecompose = FALSE;
Boolean EncodeFileNameSpecify = FALSE;
ArithEncoder *encoder;
BIT_FILE *EncodeStream;
float AbsMaxCoeff;
float ImageMean;
int Threshold;
int i, j;
int MaxHistogramCount;
int *bin, nbin;
int total;
double TargetBitRate;
char *ProgramName, *InputImageName;
int WaveletIndex;
FILTERSET *Filter[16];
int ScanOrder;
double t1;
EndEncoding = FALSE;
fprintf(stdout, "Embedded Zerotree Wavelet Coder - EZW2 (Encoder)\n");
InitializeFilterSets();
/* Initialize the filters used */
Filter[0] = Antonini;
Filter[1] = Adelson;
Filter[2] = Odegard;
Filter[3] = Villa1810;
Filter[4] = Brislawn;
Filter[5] = Brislawn2;
Filter[6] = Haar;
Filter[7] = Daub4;
Filter[8] = Daub6;
Filter[9] = Daub8;
Filter[10] = Villa1;
Filter[11] = Villa2;
Filter[12] = Villa3;
Filter[13] = Villa4;
Filter[14] = Villa5;
Filter[15] = Villa6;
ProgramName = argv[0];
/* default settings */
NScale = 6;
TargetBitRate = 0.25;
MaxHistogramCount = 256;
WaveletIndex = 0;
ScanOrder = 0;
if (argc<3){
fprintf(stderr, "Usage: %s [image] [bitrate]\n", ProgramName);
fprintf(stderr, "\t -l \n");
fprintf(stderr, "\t -w \n");
fprintf(stderr, "\t 0 =Antonini 1 =Adelson 2 =Odegard 3 =Villa1810\n");
fprintf(stderr, "\t 4 =Brislawn 5 =Brislawn2 6 =Haar 7 =Daub4\n");
fprintf(stderr, "\t 8 =Daub6 9 =Daub8 10=Villa1 11=Villa2\n");
fprintf(stderr, "\t 12=Villa3 13=Villa4 14=Villa5 15=Villa6\n");
fprintf(stderr, "\t -h \n");
fprintf(stderr, "\t -e \n");
fprintf(stderr, "\t -k keep decompose image\n");
//fprintf(stderr, "\t -s \n");
//fprintf(stderr, "\t 0=Morton/1=Raster\n");
return;
}
InputImageName = argv[1];
TargetBitRate = atof(argv[2]);
argv+=3; argc-=3;
while (argc > 0){
if (!strcmp("-l", *argv)){
argv++; argc--;
NScale = atoi(*argv);
argv++; argc--;
}
else if (!strcmp("-h", *argv)){
argv++; argc--;
MaxHistogramCount = atoi(*argv);
argv++; argc--;
}
else if (!strcmp("-w", *argv)){
argv++; argc--;
WaveletIndex = atoi(*argv);
if (WaveletIndex<0 || WaveletIndex > 15){
WaveletIndex = 0;
}
argv++; argc--;
}
else if (!strcmp("-e", *argv)){
argv++; argc--;
sprintf(EncodeImageFileName, "%s.ezw", *argv);
EncodeFileNameSpecify = TRUE;
argv++; argc--;
}
else if (!strcmp("-k", *argv)){
argv++; argc--;
KeepDecompose = TRUE;
}
/*
else if (!strcmp("-s", *argv)){
argv++; argc--;
ScanOrder = atoi(*argv);
if (ScanOrder<0 || ScanOrder > 1){
ScanOrder = 0;
}
argv++; argc--;
}
*/
else{
fprintf(stderr, "Invalid arguement %s\n", *argv);
fprintf(stderr, "Usage: %s [image] [bitrate]\n", ProgramName);
fprintf(stderr, "\t -l \n");
fprintf(stderr, "\t -w \n");
fprintf(stderr, "\t 0 =Antonini 1 =Adelson 2 =Odegard 3 =Villa1810\n");
fprintf(stderr, "\t 4 =Brislawn 5 =Brislawn2 6 =Haar 7 =Daub4\n");
fprintf(stderr, "\t 8 =Daub6 9 =Daub8 10=Villa1 11=Villa2\n");
fprintf(stderr, "\t 12=Villa3 13=Villa4 14=Villa5 15=Villa6\n");
fprintf(stderr, "\t -h \n");
fprintf(stderr, "\t -e \n");
fprintf(stderr, "\t -k keep decompose image\n");
//fprintf(stderr, "\t -s \n");
//fprintf(stderr, "\t 0=Morton/1=Raster\n");
return;
}
}
/* build filenames */
sprintf(InputImageFileName, "%s.pgm", InputImageName);
sprintf(DecomposeImageFileName, "%s_%d_%s.decompose.pgm",
InputImageName, NScale, FilterName[WaveletIndex]);
if(!EncodeFileNameSpecify){
sprintf(EncodeImageFileName, "%s_%.6f_%d_%s_%d_%d.ezw", InputImageName,
TargetBitRate, NScale, FilterName[WaveletIndex],
MaxHistogramCount, ScanOrder);
}
/* read data */
if ((InputImage = ReadPGMToFloat(InputImageFileName))==NULL){
fprintf(stderr, "Fail to read input image: %s\n", InputImageFileName);
exit(-1);
}
if ((InputImage->xsize>>NScale)<xsize ||
(InputImage->ysize>>NScale)<ysize){
EZW2Error("Image size is not consistent with number of scales.\n");
}
/* get image mean */
ImageMean = 0.0;
for (i=0; ixsize*InputImage->ysize; i++){
ImageMean += (float)InputImage->pixelLinear[i];
}
ImageMean /=(InputImage->xsize*InputImage->ysize);
/* subtract mean */
for (i=0; ixsize*InputImage->ysize; i++){
InputImage->pixelLinear[i] -=ImageMean;
}
/* initialize wavelet filter */
wavelet = WaveletAlloc(Filter[WaveletIndex]);
/* transform */
transform = WaveletTransformAlloc(wavelet, InputImage, NScale, -1);
/* decompose image */
if (KeepDecompose){
DecomposeImage = WaveletTransformCodeCoeff(transform, 1);
WriteFloatToPGM(DecomposeImage, DecomposeImageFileName);
FImageFree(DecomposeImage);
}
fprintf(stdout, "Original Image: %s\nEncoded Image : %s\n",
InputImageFileName, EncodeImageFileName);
fprintf(stdout, "Width: %d Height: %d ",
InputImage->xsize, InputImage->ysize);
fprintf(stdout, "Mean : %.3f ", ImageMean);
/* compute the byte budget */
ByteBudget = (int)(InputImage->xsize*InputImage->ysize*TargetBitRate / 8.0);
fprintf(stdout, "Bytes: %d (%.5fbpp)\n", ByteBudget, TargetBitRate);
/* get largest magnitude coefficient */
AbsMaxCoeff = -1.0;
for (i=0; ivsize*transform->hsize; i++){
if (fabs(transform->value[i]) > AbsMaxCoeff){
AbsMaxCoeff = (float)fabs(transform->value[i]);
}
}
fprintf(stdout, "Abs Max Coeff : %f\n", AbsMaxCoeff);
/* get threshold */
Threshold = 1 << (int)(floor(log10(AbsMaxCoeff)/log10(2)));
fprintf(stdout, "Initial threshold: %d Levels: %d Wavelet: %s Scan: %d\n\n",
Threshold, NScale, FilterName[WaveletIndex], ScanOrder);
/* - debug
printf("Analysing data.\n");
nbin=log2(Threshold)+2;
bin = (int*)malloc(sizeof(int)*nbin);
for (i=0; ivsize*transform->hsize; i++){
for (j=0; jvalue[i]) < (1<xsize, ImageXSizeBits);
BasicCoderWriteNBits(encoder, InputImage->ysize, ImageYSizeBits);
BasicCoderWriteNBits(encoder, ScanOrder, ScanOrderBits);
BasicCoderWriteNBits(encoder, NScale, ScaleBits);
BasicCoderWriteNBits(encoder, WaveletIndex, WaveletIndexBits);
BasicCoderWriteNBits(encoder, *((unsigned int *)&ImageMean), ImageMeanBits);
BasicCoderWriteNBits(encoder, log2(Threshold), ThresholdBits);
BasicCoderWriteNBits(encoder, MaxHistogramCount, MaxHistoCountBits);
/* EZW coding */
EZW2Encode(transform, encoder, Threshold, MaxHistogramCount,
ByteBudget, ScanOrder);
/* Clean up */
ArithEncoderDone(encoder);
ArithEncoderDealloc(encoder);
CloseOutputBitFile(EncodeStream);
FImageFree(InputImage);
WaveletTransformDealloc(transform);
WaveletDealloc(wavelet);
RemoveFilterSets();
fprintf(stderr, "Done\n");
PrintLeaks();
return;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
void EZW2Encode(WTRANSFORM *transform, ArithEncoder *encoder,
int threshold, int HistoCount, int ByteBudget, int ScanOrder)
{
//定义4个主编码扫描和一个从属编码扫描
BasicCoder *DominantPassCoder[4];
BasicCoder *SubordinateListCoder;
int i, nPass=0;
int BitsCount, TempCount;
MAP *map;
SubbandSymbol *ztmap;
DLNode *DomList, *DomListTemp1, *DomListTemp2;
SLNode *SubList;
int SubListSize;
//建立图像小波系数的零树图
if ((ztmap=SubbandSymbolAlloc(transform->hsize,
transform->vsize, transform->nsteps)) == NULL)
{
EZW2Error("Fail to allocate subband symbol.\n");
}
EZW2BuildZerotreeMap(transform, ztmap);
//建立主编码扫描的小波系数表
if ((DomList = (DLNode *)malloc(sizeof(DLNode)
*transform->vsize*transform->hsize))==NULL)
{
EZW2Error("Fail to allocate dominant list.\n");
}
//建立从属编码扫描的小波系数表
if ((SubList = (SLNode *)malloc(sizeof(SLNode)
*transform->vsize*transform->hsize))==NULL)
{
EZW2Error("Fail to allocate subordinate list.\n");
}
//在主编码扫描未完成的时候,从属过程的系数表为空
SubListSize = 0;
//主编码扫描过程建立4张系数表
for (i=0; i<4; i++)
{
if ((DominantPassCoder[i] = BasicCoderAlloc(4, HistoCount)) == NULL)
{
EZW2Error("Fail to allocate dominanat pass coder.\n");
}
}
//建立一个从属过程的小波系数上下文表
if ((SubordinateListCoder = BasicCoderAlloc(2, HistoCount)) == NULL){
EZW2Error("Fail to allocate subordinate list coder.\n");
}
//记录编码为POS和NEG的小波系数信息
if ((map=MapAlloc(transform->hsize, transform->vsize,
transform->nsteps))==NULL){
EZW2Error("Fail to allocate map.\n");
}
//统计目前为止编码器的输出数据流量
BitsCount = ArithEncoderNBitsOutput(encoder);
while((threshold!=0) && (EndEncoding!=TRUE))
{
printf("Pass #%2d - ", ++nPass);
if (ScanOrder==0){
//主编码扫描过程
EncodeDominantPassMortonScan(DomList, SubList, &SubListSize,
transform, map, threshold, encoder,
DominantPassCoder, ztmap, ByteBudget);
}
else{
//否则,空操作
}
//统计当前编码输出流量
TempCount = ArithEncoderNBitsOutput(encoder);
//从属编码过程
EncodeSubordinatePass(SubList, SubListSize, threshold>>1, encoder,
SubordinateListCoder, ByteBudget);
//统计输出流量
BitsCount = ArithEncoderNBitsOutput(encoder);
printf("Sign Coeff: %6d (%5d) Bytes: %-6d (SB:%d)\n",
SubListSize, threshold, ROUND((BitsCount/8.0)), BitsCount-TempCount);
//完成编码后,将编码器复位
if (EndEncoding != TRUE){
threshold >>= 1;
for (i=0; i<4; i++){
BasicCoderReset(DominantPassCoder[i]);
}
BasicCoderReset(SubordinateListCoder);
}
}
printf("\n");
//释放编码器占据的数据空间
for (i=0; i< 4; i++){
BasicCoderDealloc(DominantPassCoder[i]);
}
BasicCoderDealloc(SubordinateListCoder);
free(DomList);
free(SubList);
//删除零树图占据的数据空间
MapDealloc(map);
SubbandSymbolDealloc(ztmap);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/* as described in "A Fast Technique For Identifying Zerotrees In
* The EZW Algorithm", ...
*/
void EZW2BuildZerotreeMap(WTRANSFORM *transform, SubbandSymbol *ztmap)
{
int i, j;
int n, temp;
for (n=transform->nSubbands-1; n>=0; n--){
if (n>=transform->nSubbands-3){
//由最高频带开始
for (j=0; jsubbandVSize[n]; j++){
for (i=0; isubbandHSize[n]; i++){
temp = log2((int)fabs(transform->subbandPtr[n]
[j*transform->subbandHSize[n]+i]));
if (temp==0){
ztmap->subbandPtr[n][j*ztmap->subbandHSize[n]+i] = 0;
}
else{
ztmap->subbandPtr[n][j*ztmap->subbandHSize[n]+i] = 1<subbandVSize[0]; j++){
for (i=0; isubbandHSize[0]; i++){
temp = log2((int)fabs(transform->subbandPtr[0]
[j*transform->subbandHSize[0]+i]));
ztmap->subbandPtr[0][j*ztmap->subbandHSize[0]+i]
= ztmap->subbandPtr[1][j*ztmap->subbandHSize[1] + i]
| ztmap->subbandPtr[2][j*ztmap->subbandHSize[2] + i]
| ztmap->subbandPtr[3][j*ztmap->subbandHSize[3] + i];
if (temp!=0){
ztmap->subbandPtr[0][j*ztmap->subbandHSize[0]+i]
= (1<subbandPtr[0][j*ztmap->subbandHSize[0]+i];
}
}
}
}
else{
for (j=0; jsubbandVSize[n]; j++){
for (i=0; isubbandHSize[n]; i++){
temp = log2((int)fabs(transform->subbandPtr[n]
[j*transform->subbandHSize[n]+i]));
ztmap->subbandPtr[n][j*ztmap->subbandHSize[n]+i]
= ztmap->subbandPtr[n+3]
[2*j*ztmap->subbandHSize[n+3] + 2*i]
| ztmap->subbandPtr[n+3]
[2*j*ztmap->subbandHSize[n+3] + 2*i+1]
| ztmap->subbandPtr[n+3]
[(2*j+1)*ztmap->subbandHSize[n+3] + 2*i]
| ztmap->subbandPtr[n+3]
[(2*j+1)*ztmap->subbandHSize[n+3] + 2*i+1];
if (temp!=0){
ztmap->subbandPtr[n][j*ztmap->subbandHSize[n]+i]
= (1<subbandPtr[n][j*ztmap->subbandHSize[n]+i];
}
}
}
}
}
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
void EncodeDominantPassMortonScan(DLNode *DomList,SLNode *SubList,
int *SubListSize, WTRANSFORM *transform,
MAP *map, int threshold,
ArithEncoder *encoder,
BasicCoder **DominantPassCoder,
SubbandSymbol *ztmap, int ByteBudget)
{
int i, j, m, n;
DLNode node;
char NodeStatus;
Boolean HighestSubband=FALSE;
int IZCount;
BasicCoder *Coder;
Boolean ParentSignificant;
Boolean PreviousCoeffSignificant;
Boolean CurrentCoeffSignificant = FALSE;
int DomListSize=0, DomListIndex;
/* initialize LL_0 subband */
for (j=0; jsubbandVSize[0]; j+=2){
for (i=0; isubbandHSize[0]; i+=2){
/* begin quad_coeff */
for (m=0; m<4; m++){
node.x = i + ScanOrderX[m];
node.y = j + ScanOrderY[m];
node.scale = 0;
node.orientation = 0;
NodeStatus = MapGetNodeSymbol(map, node.scale, node.orientation,
node.x, node.y);
/* output code */
if (!NodeStatus){
/* not a significant coeff in the previous dominant pass */
PreviousCoeffSignificant = CurrentCoeffSignificant;
CurrentCoeffSignificant = FALSE;
EncodeNode(SubList, SubListSize, transform, &node, ztmap, threshold);
if (node.code == POS || node.code == NEG){
MapSetNodeSymbol(map, node.scale, node.orientation,
node.x, node.y, 1);
CurrentCoeffSignificant = TRUE;
}
if (ROUND(ArithEncoderNBitsOutput(encoder)/8.0) > ByteBudget-1){
EndEncoding = TRUE;
return;
}
/* perform context switching */
ParentSignificant = BASEBAND_PARENT_SIGNIFICANT;
if (ParentSignificant && PreviousCoeffSignificant){
Coder = DominantPassCoder[0];
}
else if (ParentSignificant){
Coder = DominantPassCoder[1];
}
else if (PreviousCoeffSignificant){
Coder = DominantPassCoder[2];
}
else{
Coder = DominantPassCoder[3];
}
BasicCoderEncode(Coder, encoder, node.code, TRUE);
}
else{
/* no code since the node is already significant in previous pass */
CurrentCoeffSignificant = TRUE;
}
if (node.code!=ZTR || NodeStatus){
/* insert the offsprings - do the LH_1 first */
/* LH_0 subband in the main list */
DomList[DomListSize].x = node.x;
DomList[DomListSize].y = node.y;
DomList[DomListSize].scale = 1;
DomList[DomListSize].orientation = 0;
DomListSize++;
}
}
/* end quad_coeff */
}
}
/* add the HL_1 and HH_1 etries into the list */
m = DomListSize;
/* HL_1 */
for (i=0; i ByteBudget-1){
EndEncoding = TRUE;
return;
}
if ((node.scale == transform->nsteps) && !HighestSubband){
/* prevent entering the code again */
HighestSubband = TRUE;
/* switch to 3 symbols */
for (i=0; i<4;i++){
IZCount = ContextGetProb(DominantPassCoder[i]->context, IZ);
ContextPutValue(DominantPassCoder[i]->context, -IZCount, IZ);
ContextPutValue(DominantPassCoder[i]->context, IZCount, ZTR);
}
}
/* check if parent is significant by looking at the map */
/* special treatment for scale 1 subbands */
if (node.scale==1){
if (MapGetNodeSymbol(map, 0, 0, node.x, node.y)){
ParentSignificant = TRUE;
}
else{
ParentSignificant = FALSE;
}
}
else{
if (MapGetNodeSymbol(map, node.scale - 1, node.orientation,
node.x>>1, node.y>>1)){
ParentSignificant = TRUE;
}
else{
ParentSignificant = FALSE;
}
}
/* perform context switching */
if (ParentSignificant && PreviousCoeffSignificant){
Coder = DominantPassCoder[0];
}
else if (ParentSignificant){
Coder = DominantPassCoder[1];
}
else if (PreviousCoeffSignificant){
Coder = DominantPassCoder[2];
}
else{
Coder = DominantPassCoder[3];
}
BasicCoderEncode(Coder, encoder, node.code, TRUE);
}
else{
CurrentCoeffSignificant = TRUE;
}
/* check if need to insert children */
if ((node.code != ZTR || NodeStatus) && node.scalensteps){
i = node.x<<1;
j = node.y<<1;
node.scale = node.scale+1;
/* same orientation */
for (m=0; m<4; m++){
DomList[DomListSize].x = i+ScanOrderX[m];
DomList[DomListSize].y = j+ScanOrderY[m];
DomList[DomListSize].scale = node.scale;
DomList[DomListSize].orientation = node.orientation;
DomListSize++;
}
}
DomListIndex++;
}
else{
break;
}
}while(1);
return;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
void EncodeNode(SLNode *SubList, int *SubListSize, WTRANSFORM *transform,
DLNode *node, SubbandSymbol *ztmap, int threshold)
{
double value;
int idx;
static i=0;
if (node->scale==0){
idx=0;
}
else{
idx = 3*node->scale - 2 + node->orientation;
}
value = transform->subbandPtr[idx]
[node->y*transform->subbandHSize[idx] + node->x];
/* NOTE:
* We need to use integer conparison. Without rounding to integer,
* there may be some coefficients that are less than threshold by
* 0.5, but are not being coded as significant.
* Previous version of code ignore this and obtain less number of
* significant coefficients.
*/
if (ROUND(fabs(value))>=threshold){
/*
if (ROUND(fabs(value))==threshold){
printf("%d\n", i++);
}
*/
if (value>0.0){
node->code = POS;
}
else{
node->code = NEG;
}
/* put node into subordinate list */
SubList[*SubListSize].x = node->x;
SubList[*SubListSize].y = node->y;
SubList[*SubListSize].scale = node->scale;
SubList[*SubListSize].orientation = node->orientation;
SubList[*SubListSize].qvalue = (int)(ROUND(fabs(value)));
SubList[*SubListSize].rvalue = 3*(threshold>>1);
(*SubListSize)++;
/* set magnitude to 0 */
transform->subbandPtr[idx]
[node->y*transform->subbandHSize[idx] + node->x] = 0.0;
}
else{
if ((ztmap->subbandPtr[idx][node->y*ztmap->subbandHSize[idx]+node->x]
& threshold)==0){
node->code = ZTR;
}
else{
node->code = IZ;
}
}
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
void EncodeSubordinatePass(SLNode *SubList, int SubListSize, int threshold,
ArithEncoder *encoder, BasicCoder *SubordinateListCoder,
int ByteBudget)
{
int i;
if (threshold>0){
for (i=0; i ByteBudget-1){
EndEncoding = TRUE;
break;
}
if ((SubList[i].qvalue & threshold) != 0){
/* output '1' */
BasicCoderEncode(SubordinateListCoder, encoder, 1, TRUE);
SubList[i].rvalue += (threshold>>1);
}
else{
/* output '0' */
BasicCoderEncode(SubordinateListCoder, encoder, 0, TRUE);
SubList[i].rvalue -= (threshold>>1);
}
}
}
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
void EZW2Error(char *fmt, ...)
{
va_list argptr;
va_start( argptr, fmt );
fprintf(stderr, "EZW2Error: " );
vprintf( fmt, argptr );
va_end( argptr );
exit( -1 );
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
void EZW2Warning(char *fmt, ...)
{
va_list argptr;
va_start( argptr, fmt );
fprintf( stderr, "EZW2Warning: " );
vprintf( fmt, argptr );
va_end( argptr );
}