📄 advancejpeg-lscode.cpp
字号:
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 + -