⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 advancejpeg-lscode.cpp

📁 改进的JPEG-LS算法
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	J[20]=J[21]=6;
	J[22]=J[23]=7;
	J[24]=8;
	J[25]=9;
	J[26]=10;
	J[27]=11;
	J[28]=12;
	J[29]=13;
	J[30]=14;
	J[31]=15;

/*4.	Initialise the two run interruption variables Nn[365], Nn[366]=0。*/
	Nn[0]=Nn[1]=0;

	MAX_C=127;
	MIN_C=-128;
	
}
BOOL CAdvanceJepgLSOneLineCode::CanEnterRUN()
{//游程编码入口条件检测
	int d1,d2,d3;
	if((d1=Rd-Rb)<0)d1=-d1;
	if((d2=Rb-Rc)<0)d2=-d2;
	if((d3=Rc-Ra)<0)d3=-d3;
	if((d1<=RunContext&&d2<=RunContext&&d3<=RunContext))return TRUE;
	else return FALSE;
}
int CAdvanceJepgLSOneLineCode::DoEncodeLine(LPBYTE lpImageBuf,
											int OneSampleBytes,
											LPBYTE lpCompressBuf,
											int CompressBitcp,
											double *lpErrorMse)
{//完成全部的编码操作,即由图象数据产生编码比特流。

	int D1,D2,D3,Continu,Seat,pp,ppx,pc,*lpI;
	int i,j;
	lpCodeStream=lpCompressBuf;
	CodeBitcp=CompressBitcp;
	//波段预测时,将图像数据转化为预测误差值
	for(i=0;i<X;i++)
	{
		if(OpenOffBandPrediction==TRUE)
		{
			pp=lpPredictionBandCode->lpReconstructCurrentLine[i];
			if((ppx=(A_Mul*pp/UNIFORM_FLOAT_TO_INT_MUL+B_Add))>Pixel_ADD)ppx=pp;
			lpImage[i]=((*((int *)(lpImageBuf+OneSampleBytes*i)))&AndCode)-ppx+Pixel_ADD;
		}
		else
		{
			lpImage[i]=(*((int *)(lpImageBuf+OneSampleBytes*i)))&AndCode;
		}
	}
//初始位置上下文值
	Rc=lpPrecedingLine[0];
	lpI=lpThirdLine;//交换用于空域预测的重建象素指针。
	lpThirdLine=lpPrecedingLine;
	lpPrecedingLine=lpCurrentLine;
	lpCurrentLine=lpI;

	lpI=lpReconstructPrecedingLine;//交换用于波段预测的重建象素指针。
	lpReconstructPrecedingLine=lpReconstructCurrentLine;
	lpReconstructCurrentLine=lpI;

	Ra=lpPrecedingLine[0];//每行第一象素时
	Raa=Ra;
	Rb=lpPrecedingLine[0];
	Rd=lpPrecedingLine[1];
//一行象素编码循环
	for(x=-1,EOLine=FALSE;EOLine==FALSE&&x<(X-1);)
	{
		if(GetNextSample()==FALSE)break;
//2.	Compute the local gradients according to Figure A.1.
		D1=Rd-Rb;
		D2=Rb-Rc;
		D3=Rc-Ra;
//3.	Select the mode following the procedure in Figure A.2.  
//	If run mode is selected, go to Step 17, otherwise continue with the regular mode.

		if(CanEnterRUN()==FALSE)
		{//regular mode
//4.	Quantize the local gradients according to the steps detailed in Figure A.4.

			if(D1<=-T3)Q1=-4;
			else if(D1<=-T2)Q1=-3;
			else if(D1<=-T1)Q1=-2;
			else if(D1<-qNEAR)Q1=-1;
			else if(D1<=qNEAR)Q1=0;
			else if(D1<T1)Q1=1;
			else if(D1<T2)Q1=2;
			else if(D1<T3)Q1=3;
			else Q1=4;

			if(D2<=-T3)Q2=-4;
			else if(D2<=-T2)Q2=-3;
			else if(D2<=-T1)Q2=-2;
			else if(D2<-qNEAR)Q2=-1;
			else if(D2<=qNEAR)Q2=0;
			else if(D2<T1)Q2=1;
			else if(D2<T2)Q2=2;
			else if(D2<T3)Q2=3;
			else Q2=4;

			if(D3<=-T3)Q3=-4;
			else if(D3<=-T2)Q3=-3;
			else if(D3<=-T1)Q3=-2;
			else if(D3<-qNEAR)Q3=-1;
			else if(D3<=qNEAR)Q3=0;
			else if(D3<T1)Q3=1;
			else if(D3<T2)Q3=2;
			else if(D3<T3)Q3=3;
			else Q3=4;

//5.	Check and change if necessary the sign of the context, modifying accordingly the variable SIGN (see A.3.4).
			i=0;
			if(Q1==0)
			{
				i=1;
				if(Q2==0)
				{
					i=2;
					if(Q3<0)SIGN=-1;
					else SIGN=1;
				}
				else if(Q2<0)SIGN=-1;
				else SIGN=1;
			}
			else if(Q1<0)SIGN=-1;
			else SIGN=1;

			if(SIGN==-1){Q1=-Q1;Q2=-Q2;Q3=-Q3;}

			Q=Q1*81+Q2*9+Q3;//相当于9进制

//6.	Compute Px according to Figure A.5.

			if(Rc>=max(Ra,Rb))Px=min(Ra,Rb);
			else
			{
				if(Rc<=min(Ra,Rb))Px=max(Ra,Rb);
				else Px=Ra+Rb-Rc;
			}

//7.	Correct Px using C[Q] and the variable SIGN, and clamp the value of the corrected prediction to the interval [0..MAXVAL ] according to the procedure in Figure A.6.
			Px+=(SIGN*C[Q]);
			if(Px>MAXVAL)Px=MAXVAL;
			else if(Px<0)Px=0;

//8.	Compute the prediction error and, if necessary, invert its sign according to the procedure in Figure A.7.

			Errval=SIGN*(Ix-Px);

//9.	For near-lossless coding, quantize the error and compute the reconstructed value of the current sample according to Figure A.8.  For lossless coding, update the reconstructed value by setting Rx equal to Ix.

			Errval=Quantize(Errval,qNEAR);

			Rx=ComputeRx(qNEAR);
			lpCurrentLine[x]=Rx;

//10.	Reduce the error to the relevant range according to Figure A.9.

			Errval=ModRange(Errval,RANGE);

//11.	Compute the context-dependent Golomb variable k according to the procedure in Figure A.10.

			for(K=0;(N[Q]<<K)<A[Q];K++);//此处 k 是逐象素变化,因只与N[Q]和A[Q]有关,收方是可以跟踪的

//12.	Perform the error mapping according to the procedure in Figure A.11.

			if((qNEAR==0)&&(K==0)&&( (2*B[Q]) <= -N[Q]))
			{
				if(Errval>=0)MErrval=Errval+Errval+1;
				else MErrval= -Errval-Errval-2;
			}
			else
			{
				if(Errval>=0)MErrval=Errval+Errval;
				else MErrval=-Errval-Errval-1;
			}

//13.	Encode the mapped error value MErrval using the limited length Golomb code function LG(k, LIMIT) specified in A.5.3.

			j=MErrval>>K;
			if(j<(LIMIT-qbpp-1))
			{
				AppendToBitStream(0,j);//加上j个0
				AppendToBitStream(1,1);
				AppendToBitStream(MErrval,K);
			}
			else
			{
				AppendToBitStream(0,LIMIT-qbpp-1);
				AppendToBitStream(1,1);
				AppendToBitStream(MErrval-1,qbpp);
			}

//14.	Update the variables according to Figure A.12.

			B[Q]+=(Errval*(qNEAR+qNEAR+1));
			A[Q]+=((Errval>0)?Errval:-Errval);
			if(N[Q]==RESET)
			{
				A[Q]>>=1;
				B[Q]>>=1;
				N[Q]>>=1;
			}
			N[Q]++;

//15.	Update the prediction correction value C[Q] according to the procedure in Figure A.13.

			if(B[Q]<=(-N[Q]))
			{
				B[Q]+=N[Q];
				if(C[Q]>MIN_C)C[Q]--;
				if(B[Q]<=(-N[Q]))B[Q]=-N[Q]+1;
			}
			else if(B[Q]>0)
			{
				B[Q]-=N[Q];
				if(C[Q]<MAX_C)C[Q]++;
				if(B[Q]>0)B[Q]=0;
			}

//16.	Go to step 2 to process the next sample.
		}
//17.	Run mode coding:
		else
		{
	//a.	Set RUNval = Ra.  While ( abs (Ix - RUNval) <= qNEAR), increment RUNcnt, 
	//		and if not at the end of a line, read a new sample.  Set Rx = RUNval each 
	//		time the sample x is added to the run (see Figure A.14).
			
			Px=RUNval=RunPredicate();//repetitive reconstructed sample value in a run重建样本值是重复的
			RUNcnt=0;//repetitive sample count for run mode游程长度计数
			i=Ix-RUNval;
			for(j=0,Continu=0;1;)//游程检测
			{//误差绝对值在允许的误差界下就符合游程编码条件。
				if(i>qNEAR||i<(-qNEAR))
				{
					if(i>DoubleMaxError||i<-DoubleMaxError)
					{
						if(Continu)
						{
							j-=Continu;
							RUNcnt-=Continu;
							x-=Continu;
							Ix=lpImage[x];
							ResetContext(x);
							Px=RunPredicate();
						}
						if(EOLine==TRUE)
						{
							EOLine=FALSE;
						}
						break;
					}
					else 
					{
						Continu++;
						if(j==0)Seat=x;
						j++;
					}
				}
				else Continu=0;
				RUNcnt++;
				lpCurrentLine[x]=Rx=RUNval;
				if(EOLine==TRUE)
				{
	//				if(Continu)
	//				{
	//					j-=Continu;
	//					RUNcnt-=Continu;
	//					x-=(Continu-1);
	//					Ix=lpImage[x];
	//					ResetContext(x);
	//					Px=RunPredicate();
	//					EOLine=FALSE;
	//				}
					break;
				}//到行尾就中止,游程长度是到行尾的长度.
				else GetNextSample();
				Px=RUNval=RunPredicate();
				i=Ix-RUNval;
			}
			if(j)
			{
				if(RUNcnt<AdjustWinLength)
				{
					RUNcnt-=(x-Seat);
					x=Seat;
					Ix=lpImage[x];
					ResetContext(x);
					Px=RunPredicate();
					if(EOLine==TRUE)
					{
						RUNcnt--;
						EOLine=FALSE;
					}
				}
			}
	//b.	While RUNcnt 32 J[RUNIndex], do (see Figure A.15):
		//i.	Append '1' to the bit stream.
		//ii.	RUNcnt = RUNcnt - 2^J[RUNIndex]
		//iii.	If RUNindex < 31 then increment RUNindex by one.
			for(j=RUNcnt;RUNcnt>=(1<<J[RUNindex]);)//此处对游程长度编码.
			{//是一个较大数时,大于(1<<J[RUNindex])部分用‘1’表示。
				AppendToBitStream(1,1);
				RUNcnt-=(1<<J[RUNindex]);
				if(RUNindex<31)
				{
					RUNindex++;//index for run mode order指示RUN的一种方式
				}
			}
	//c.	If  the run was aborted by the end of a line (see Figure A.16):
		//i.	if RUNcnt > 0, append '1' to the bit stream.
		//ii.	Go to Step 16.
	//d.	Append '0' to the bit stream (see Figure A.16).
	//e.	Append RUNcnt in binary representation (using J[RUNindex] bits) to the bit stream 
	//		(MSB first, see Figure A.16).
	//f.	If RUNindex > 0 then decrement RUNindex by one (see Figure A.16).
			if(EOLine==FALSE||j==0)
			{//没有到尾的情况
				AppendToBitStream(0,1);//'0'指示没到行尾,相对于前面的‘1’而言的,
				AppendToBitStream(RUNcnt,J[RUNindex]);//余数用J[RUNindex]个比特表示。
				if(RUNindex>0)
				{
					RUNindex--;
				}
			}
			else 
			{//到行尾就不必对游程长度编码,以一个‘1’表示,与前面的
				//"大于(1<<J[RUNindex])部分用‘1’表示。"并不矛盾,
				//译码时,‘1’表示两种可能性,1、到尾;2、游程长度大于(1<<J[RUNindex])。
				//译码时到尾长度是已知的,据此可以区别。
				//if(RUNindex>0)RUNindex--;
				if(RUNcnt>0)AppendToBitStream(1,1);//此一比特要输出,译码时据此比特要判定

				if(j>1&&TestErrorMeLimen>0)AppendRunEncode(X-j,j);

				continue;
			}
			if(j>1&&TestErrorMeLimen>0)
			{
				AppendRunEncode(x-j,j);
			}
//18.	Run interruption sample encoding: perform the operations in A.7.2, and then go to Step 16.
	//1.	Compute the index RItype, which defines the context, as indicated in Figure A.17.
			//零游程未到行尾时的第一象素编码。
			
			i=Ra-Rb;
			if(i<=qNEAR&&i>=(-qNEAR))RItype=1;//index for run interruption coding
			else RItype=0;
	//2.	Compute the prediction error, as indicated in Figure A.18
			Errval=Ix-Px;
	//3.	Correct, if necessary, the sign of Errval (see Figure  A.19).  
	//		This step is analogous to the context-merging procedure in the regular coding 
	//		mode.  For qNEAR-lossless coding Errval shall be quantized and Rx computed, 
	//		as shown in Figure A.8.  The error shall then be reduced using the variable 
	//		RANGE, following the same steps as in A.4.5 (this reduction is performed by 
	//		the function ModRange below). 
			ResetContext(x);
			if(RItype==0&&Ra>Rb)
			{
				Errval=-Errval;
				SIGN=-1;
			}
			else SIGN=1;
			if(qNEAR>0)
			{
				Errval=Quantize(Errval,qNEAR);
				Rx=ComputeRx(qNEAR);
			}
			else Rx=Ix;
			lpCurrentLine[x]=Rx;

			Errval=ModRange(Errval,RANGE);

	//4.	Compute the auxiliary variable TEMP.  This variable is used for the computation
	//		of the Golomb variable k.
			
			if(RItype==0)TEMP=A[365];
			else TEMP=A[366]+(N[366]>>1);

	//5.	Set Q = RItype + 365.  The Golomb variable k shall be computed, following 
	//		the same procedure as in the regular mode, Figure A.10, but using TEMP 
	//		instead of A[Q].

			Q=RItype+365;//取值:1 or 0
			for(K=0;(N[Q]<<K)<TEMP;K++);

	//6.	Compute the flag map, as indicated in Figure A.21. This variable influences
	//		the mapping of Errval to non-negative values, as indicated in Figure A.22.

			if((K==0)&&Errval>0&&(2*Nn[Q-365])<N[Q])map=1;
			else if(Errval<0&&(2*Nn[Q-365])>=N[Q])map=1;
			else if(Errval<0&&K!=0)map=1;
			else map=0;

	//7.	Errval is now mapped:

			if((i=Errval)<0)i=-i;
			EMErrval=2*i-RItype-map;

	//8.	Encode EMErrval following the same procedures as in the regular mode 
	//		(see A.5.3), but using the limited length Golomb code function LG(k, glimit), 
	//		where glimit = LIMIT - J[RUNindex] - 1 and RUNindex corresponds to the value 
	//		of the variable before the update specified in A.7.1.2.

			j=EMErrval>>K;
			glimit=LIMIT-J[RUNindex]-1;
			if(j<(glimit-qbpp-1))
			{
				AppendToBitStream(0,j);//加上j个0
				AppendToBitStream(1,1);
				AppendToBitStream(EMErrval,K);
			}
			else
			{
				AppendToBitStream(0,glimit-qbpp-1);
				AppendToBitStream(1,1);
				AppendToBitStream(EMErrval-1,qbpp);
			}

	//9.	Update the variables for run interruption sample encoding, according to Figure A.23

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -