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 ); 
}