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

📄 advancejpeg-lscode.cpp

📁 改进的JPEG-LS算法
💻 CPP
📖 第 1 页 / 共 5 页
字号:
				else lpDoubleErrList[DoubleErrN].Sign=-1;
			}
			else
			{//非大误差时
				lpDoubleErrList[DoubleErrN].Sign=0;
			}
			DoubleErrN++;//可能产生大误差象素数
		}
		DErrN+=i;//一级大误差数的累计
		DDErrN+=ii;//二级大误差数的累计
	}
}
void CAdvanceJepgLSOneLineCode::EncodeTwoAdjust(int *lpAdjustSequence,int AdjustLength,int TwoAdjustLength)
{//二级象素调节状态编码
	//已知大误差数TwoAdjustLength,和大误差象素数AdjustLength,序列存放在lpAdjustSequence中
	int bitn,b,d,N,RunL;
	//编码二级调节数
	bitn=lpTwoAdjustNumberFastCoding->OneEncodePass(AdjustLength,TwoAdjustLength,lpCodeStream,CodeBitcp);
	CodeBitcp+=bitn;
	if(TwoAdjustLength>0)
	{//二级调节数非零时,作相应游程编码
		for(b=0,d=0,N=AdjustLength;d<TwoAdjustLength;d++)
		{//b当前编码点位置,d调节数计数,相当于游程数,N剩余象素数
			for(RunL=b;RunL<AdjustLength;RunL++)//当前游程检测
			{
				if(lpAdjustSequence[RunL]!=0)
				{
					break;
				}
			}
			RunL-=b;//当前检出的游程长度
			bitn=lpTwoAdjustRunFastCoding->OneEncodePass(N,//后向象素数,用于编码参数估算
														TwoAdjustLength-d,//后向调节数,用于编码参数估算
														RunL,//游程长度
														lpCodeStream,
														CodeBitcp);//当前游程编码
			CodeBitcp+=bitn;
			b+=(RunL+1);//下一个游程编码的象素位置
			N=AdjustLength-b;//余下的象素数
		}
	}
}
void CAdvanceJepgLSOneLineCode::EncodeAdjust(int *lpAdjustSequence,int AllAdjustLength,int AdjustLength)
{//一级象素调节状态游程编码
	//已知大误差数AdjustLength,和大误差象素数AllAdjustLength,序列存放在lpAdjustSequence中
	int bitn,b,d,N,RunL;
	//编码一级调节数
	bitn=lpAdjustNumberFastCoding->OneEncodePass(AllAdjustLength,AdjustLength,lpCodeStream,CodeBitcp);
	CodeBitcp+=bitn;
	if(AdjustLength>0)
	{//一级调节数非零时,作相应游程编码
		for(b=0,d=0,N=AllAdjustLength;d<AdjustLength;d++)
		{//b当前编码点位置,d调节数计数,相当于游程数,N剩余象素数
			for(RunL=b;RunL<AllAdjustLength;RunL++)//当前游程检测
			{
				if(lpAdjustSequence[RunL]!=0)
				{
					break;
				}
			}
			RunL-=b;//当前检出的游程长度
			bitn=lpAdjustRunFastCoding->OneEncodePass(N,//后向象素数,用于编码参数估算
													AdjustLength-d,//后向调节数,用于编码参数估算
													RunL,//游程长度
													lpCodeStream,
													CodeBitcp);//当前游程编码
			CodeBitcp+=bitn;
			//追加1比特符号编码
			if(lpAdjustSequence[RunL+b]>0)AppendToBitStream(0x1,1);
			else AppendToBitStream(0x0,1);
			b+=(RunL+1);//下一个游程编码的象素位置
			N=AllAdjustLength-b;//余下的象素数
		}
	}
}
void CAdvanceJepgLSOneLineCode::EncodeDoubleError()
{//行尾大误差纠正编码
	//已知大误差数DErrN,和大误差象素数DoubleErrN,序列存放在lpDoubleErrList中
	int b,d,bit,bitn,RunL,N;
	//编码一级大误差数
	bitn=lpDErrNumberFastCoding->OneEncodePass(DoubleErrN,DErrN,lpCodeStream,CodeBitcp);
	CodeBitcp+=bitn;
	if(DErrN>0)
	{//一级大误差数非零时,作相应游程编码
		for(b=0,d=0,N=DoubleErrN;d<DErrN;d++)
		{//b当前编码点位置,d大误差数计数,相当于游程数,N剩余象素数
			for(RunL=b;RunL<DoubleErrN;RunL++)//当前游程检测
			{
				if(lpDoubleErrList[RunL].Sign!=0)
				{
					if(lpDoubleErrList[RunL].Sign<0)bit=0;
					else bit=1;//符号位的比特表示
					break;
				}
			}
			RunL-=b;//当前检出的游程长度
			bitn=lpDErrRunFastCoding->OneEncodePass(N,//后向象素数,用于编码参数估算
													DErrN-d,//后向大误差数,用于编码参数估算
													RunL,//游程长度
													lpCodeStream,
													CodeBitcp);//当前游程编码
			CodeBitcp+=bitn;
			AppendToBitStream(bit,1);//输出符号位
			b+=(RunL+1);//下一个游程编码的象素位置
			N=DoubleErrN-b;//余下的象素数
		}
	}
}
void CAdvanceJepgLSOneLineCode::EncodeDDoubleError()
{//行尾二级大误差纠正编码
	//已知大误差数DDErrN,和大误差象素数DErrN,序列存放在lpDoubleErrList中
	int b,d,bitn,RunL,N;
	//编码一级大误差数
	bitn=lpDDErrNumberFastCoding->OneEncodePass(DErrN,DDErrN,lpCodeStream,CodeBitcp);
	CodeBitcp+=bitn;
	if(DDErrN>0)
	{//二级大误差数非零时,作相应游程编码
		for(b=0,d=0,N=DErrN;d<DDErrN;d++)
		{//b当前编码点位置,d大误差数计数,相当于游程数,N剩余象素数
			for(RunL=b;RunL<DErrN;RunL++)//当前游程检测
			{
				if(lpDoubleErrList[RunL].Sign>1||lpDoubleErrList[RunL].Sign<-1)
				{
					break;
				}
			}
			RunL-=b;//当前检出的游程长度
			bitn=lpDDErrRunFastCoding->OneEncodePass(N,//后向象素数,用于编码参数估算
													DDErrN-d,//后向大误差数,用于编码参数估算
													RunL,//游程长度
													lpCodeStream,
													CodeBitcp);//当前游程编码
			CodeBitcp+=bitn;
			b+=(RunL+1);//下一个游程编码的象素位置
			N=DErrN-b;//余下的象素数
		}
	}
}
BOOL CAdvanceJepgLSOneLineCode::GetNextSample()
{//取下一个象素,含相邻重建的更新,及行尾图像尾标志设置。
	if((++x)>0)
	{
		Raa=Ra;
		Ra=Rx;
		Rc=lpPrecedingLine[x-1];
		Rb=lpPrecedingLine[x];
		if(x>=(X-1))
		{
			EOLine=TRUE;//每行象素尾时置标志
			Rd=lpPrecedingLine[x];
		}
		else{Rd=lpPrecedingLine[x+1];}
	}
	Ix=lpImage[x];
	return TRUE;
}
void CAdvanceJepgLSOneLineCode::AppendToBitStream(int a,int b)
{//在当前的码流位置上接上 b  比特,比特来自状态 a 的低位。一般不能大24比特。
	if(b<=0)return;
	int i=0;
	for(i=b-1;i>=0;i--)
	{
		if(a&(1<<i))*(lpCodeStream+(CodeBitcp>>3))|=(1<<(CodeBitcp&7));
		else *(lpCodeStream+(CodeBitcp>>3))&=(~(1<<(CodeBitcp&7)));
		++CodeBitcp;
	}
}
int CAdvanceJepgLSOneLineCode::Quantize(int a,int pNEAR)
{//量化
	if(a>0)a=(a+pNEAR)/(pNEAR+pNEAR+1);
	else a=-(pNEAR-a)/(pNEAR+pNEAR+1);
	return a;
}
int CAdvanceJepgLSOneLineCode::ModRange(int a,int pRANGE)
{//在-(RANGE/2)—(RANGE+1)/2)范围内取模
	if(a<-(pRANGE/2))a+=pRANGE;
	else if(a>=((pRANGE+1)/2))a-=pRANGE;
	return a;
}
int CAdvanceJepgLSOneLineCode::ComputeRx(int pNEAR)
{//计算重建象素值
	int a;
	a=Px+SIGN*Errval*(pNEAR+pNEAR+1);
	if(a<0)a=0;
	else if(a>MAXVAL)a=MAXVAL;
	return a;
}
int CAdvanceJepgLSOneLineCode::DoDecodeLine(LPBYTE lpImageBuf,int OneSampleBytes,LPBYTE lpCompressBuf,int CompressBitcp)
{//完成全部的编码操作,即由图象数据产生编码比特流。
	int D1,D2,D3,R;
	int i,j,*lpI;
	lpCodeStream=lpCompressBuf;
	CodeBitcp=CompressBitcp;
//初始位置上下文值
	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(SetNextSample()==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 context-dependent Golomb variable k according to the procedure 
//		in Figure A.10.

			for(K=0;(N[Q]<<K)<A[Q];K++);

//9.	Decode the mapped error value MErrval:
		//a.	Read the unary code.  If it contains less than LIMIT-qbpp-1 zeros, 
		//	    use it to form the most significant bits of MErrval and read k 
		//		additional bits, to compose the k least significant bits of MErrval. 
		//b.	If the unary code contains LIMIT-qbpp-1 zeros, read qbpp additional 
		//		bits to get a binary representation of MErrval -1.
		
			j=ReturnZeroBitNumber();
			if(j<(LIMIT-qbpp-1))
			{
				CodeBitcp+=j;//加上j个0
				GetFromBitStream(1);
				MErrval=GetFromBitStream(K);
				MErrval+=(j<<K);
			}
			else
			{
				CodeBitcp+=j;//加上j个0
				GetFromBitStream(1);//不直接加这一'1'比特位,是因为j可能为0
				MErrval=GetFromBitStream(qbpp)+1;
			}

//10.	Perform the inverse of the error mapping indicated in Figure A.11, 
//		where now MErrval is given and Errval is computed.

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

//11.	Update the variables according to Figure A.12.
//因为此处的上下文参数的更新,用到的Errval是当前状态下的.

			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]++;

//12.	For near-lossless coding, multiply Errval by (2*NEAR+1).
//13.	Invert sign of Errval if  the variable SIGN is negative.

			Errval*=(SIGN*(qNEAR+qNEAR+1));

//14.	Compute Rx = (Errval + Px) modulo [RANGE*(2*NEAR+1)]. For near-lossless 
//		coding map Rx to the interval [-NEAR..RANGE*(2*NEAR+1)-1-NEAR].  
//		Clamp Rx to [0..MAXVAL ].  This is done by the following procedure:
			Rx=Errval+Px;
			if(Rx<-qNEAR)
			{
				Rx+=(RANGE*(qNEAR+qNEAR+1));//用重建值的区间限制来识别对Error所作的取模操作

			}
			else if(Rx>(MAXVAL+qNEAR))
			{
				Rx-=(RANGE*(qNEAR+qNEAR+1));
			}

			if(Rx<0)Rx=0;
			else if(Rx>MAXVAL)Rx=MAXVAL;
			lpCurrentLine[x]=Rx;

//15.	Map Rx using the inverse point transform Pt specified by the parameter Al (see B.2.3 of ITU-T T.81 | ISO/IEC 10918-1) and the applicable mapping table, if any, as specified in Annex  C.
//16.	Compute 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;
			}

//17.	Process next sample of the same component or of next component, 
//		starting from Step 2, as specified in Annex B.
		}

//18.	Run mode decoding:		
		else
		{
			Px=RUNval=RunPredicate();
			for(RUNcnt=0;1;)
			{//游程长度译码循环
				
				R=GetFromBitStream(1);
//		a.	Read a bit, R, from the bit stream.
				if(R==1)
//		b.	If R='1' then
				{
//			i)	Fill the image with 2J[RUNindex] samples of value Ra, 
//				or until a line is completed.
					for(i=0,j=(1<<J[RUNindex]);i<j;i++)
					{
						RUNcnt++;
						lpCurrentLine[x]=Rx=RUNval;
						if(EOLine==TRUE)break;
						SetNextSample();
						Px=RUNval=RunPredicate();
					}

//			ii)	If exactly 2^J[RUNindex] samples were filled in the previous step, 
//				and RUNindex<31, then increase RUNindex by one.  If the last sample 
//				in the line has not yet been decoded return to step 18.a to read more 
//				bits from the bit stream.  Otherwise, go to Step 17.  
					
					if(EOLine==TRUE&&i<j)//未达(1<<J[RUNindex])且到了尾部
					{//达行尾中断时(注: 存在有行尾标志但非中断情况)
						if(i==(j-1))if(RUNindex<31)RUNindex++;
						break;
					}
					else if(RUNindex<31)RUNindex++;
				}

⌨️ 快捷键说明

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