static int DecodeACSign(WinZipJPEGDecompressor *self,int comp,unsigned int k,int absvalue, const WinZipJPEGBlock *current,const WinZipJPEGBlock *north,const WinZipJPEGBlock *west, const WinZipJPEGQuantizationTable *quantization) { // Decode sign. (5.6.6.4) // Calculate sign context, or decode with fixed probability. (5.6.6.4.1) int predictedsign; if(IsFirstRowOrColumn(k)) { int bdr=BDR(k,current,north,west,quantization); if(bdr==0) return NextBitFromWinZipJPEGArithmeticDecoder(&self->decoder,&self->fixedcontext); predictedsign=(bdr<0); } else if(k==4) { int sign1=Sign(north->c[k]); int sign2=Sign(west->c[k]); if(sign1+sign2==0) return NextBitFromWinZipJPEGArithmeticDecoder(&self->decoder,&self->fixedcontext); predictedsign=(sign1+sign2<0); } else if(IsSecondRow(k)) { if(north->c[k]==0) return NextBitFromWinZipJPEGArithmeticDecoder(&self->decoder,&self->fixedcontext); predictedsign=(north->c[k]<0); } else if(IsSecondColumn(k)) { if(west->c[k]==0) return NextBitFromWinZipJPEGArithmeticDecoder(&self->decoder,&self->fixedcontext); predictedsign=(west->c[k]<0); } else { return NextBitFromWinZipJPEGArithmeticDecoder(&self->decoder,&self->fixedcontext); } static const int n_for_k[64]={ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 0,11,12, 13,14, 0, 0,15,16, 17,18, 0, 0, 0,19,20, 21,22, 0, 0, 0, 0,23,24, 25, 0, 0, 0, 0, 0,26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; int n=n_for_k[k]; int signcontext1=Min(Category(absvalue)/2,2); return NextBitFromWinZipJPEGArithmeticDecoder(&self->decoder, &self->acsignbins[comp][n][signcontext1][predictedsign]); }
static void CompressACSign(JPEGCompressor *self,int comp,unsigned int k,int absvalue, const JPEGBlock *current,const JPEGBlock *north,const JPEGBlock *west, const JPEGQuantizationTable *quantization) { int sign=current->c[k]<0; // Calculate sign context, or compress with fixed probability. int predictedsign; if(IsFirstRowOrColumn(k)) { int bdr=BDR(k,current,north,west,quantization); if(bdr==0) { WriteBit(&self->encoder,sign,0x800); return; } predictedsign=(bdr<0); } else if(k==4) { int sign1=Sign(north->c[k]); int sign2=Sign(west->c[k]); if(sign1+sign2==0) { WriteBit(&self->encoder,sign,0x800); return; } predictedsign=(sign1+sign2<0); } else if(IsSecondRow(k)) { if(north->c[k]==0) { WriteBit(&self->encoder,sign,0x800); return; } predictedsign=(north->c[k]<0); } else if(IsSecondColumn(k)) { if(west->c[k]==0) { WriteBit(&self->encoder,sign,0x800); return; } predictedsign=(west->c[k]<0); } else { WriteBit(&self->encoder,sign,0x800); return; } static const int n_for_k[64]={ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 0,11,12, 13,14, 0, 0,15,16, 17,18, 0, 0, 0,19,20, 21,22, 0, 0, 0, 0,23,24, 25, 0, 0, 0, 0, 0,26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; int n=n_for_k[k]; int signcontext1=Min(Category(absvalue)/2,2); WriteDynamicBit(&self->encoder,sign, &self->acsignbins[comp][n][signcontext1][predictedsign], self->acsignshift); }
static int DecodeACComponent(WinZipJPEGDecompressor *self,int comp,unsigned int k,bool canbezero, const WinZipJPEGBlock *current,const WinZipJPEGBlock *north,const WinZipJPEGBlock *west, const WinZipJPEGQuantizationTable *quantization) { if(!north) north=&ZeroBlock; if(!west) west=&ZeroBlock; int val1; if(IsFirstRowOrColumn(k)) val1=Abs(BDR(k,current,north,west,quantization)); else val1=Average(k,north,west,quantization); int val2=Sum(k,current); if(canbezero) { // Decode zero/non-zero bit. (5.6.6.1) int zerocontext1=Min(Category(val1),2); int zerocontext2=Min(Category(val2),5); int nonzero=NextBitFromWinZipJPEGArithmeticDecoder(&self->decoder, &self->zerobins[comp][k-1][zerocontext1][zerocontext2]); // If this component is zero, there is no need to decode further parameters. if(!nonzero) return 0; } // This component is not zero. Proceed with decoding absolute value. int absvalue; // Decode pivot (abs>=2). (5.6.6.2) int pivotcontext1=Min(Category(val1),4); int pivotcontext2=Min(Category(val2),6); int pivot=NextBitFromWinZipJPEGArithmeticDecoder(&self->decoder, &self->pivotbins[comp][k-1][pivotcontext1][pivotcontext2]); if(!pivot) { // The absolute of this component is not >=2. It must therefore be 1, // and there is no need to decode the value. absvalue=1; } else { // The absolute of this component is >=2. Proceed with decoding // the absolute value. (5.6.6.3) int val3,n; if(IsFirstRow(k)) { val3=Column(k)-1; n=0; } else if(IsFirstColumn(k)) { val3=Row(k)-1; n=1; } else { val3=Category(k-4); n=2; } int magnitudecontext1=Min(Category(val1),8); int magnitudecontext2=Min(Category(val2),8); int remaindercontext=val3; // Decode absolute value. absvalue=DecodeBinarization(&self->decoder, self->acmagnitudebins[comp][n][magnitudecontext1][magnitudecontext2], self->acremainderbins[comp][n][remaindercontext], 14,9)+2; } if(DecodeACSign(self,comp,k,absvalue,current,north,west,quantization)) return -absvalue; else return absvalue; }
static void CompressACComponent(JPEGCompressor *self,int comp,unsigned int k,bool canbezero, const JPEGBlock *current,const JPEGBlock *north,const JPEGBlock *west, const JPEGQuantizationTable *quantization) { int value=current->c[k]; if(!north) north=&ZeroBlock; if(!west) west=&ZeroBlock; int val1; if(IsFirstRowOrColumn(k)) val1=Abs(BDR(k,current,north,west,quantization)); else val1=Average(k,north,west,quantization); int val2=Sum(k,current); if(canbezero) { // Compress zero/non-zero bit. int zerocontext1=Min(Category(val1),2); int zerocontext2=Min(Category(val2),5); WriteDynamicBit(&self->encoder,value!=0, &self->zerobins[comp][k-1][zerocontext1][zerocontext2], self->zeroshift); // If this component is zero, there is no need to compress further parameters. if(value==0) return; } // This component is not zero. Proceed with compressing absolute value. int absvalue=Abs(value); // Compress pivot (abs>=2). int pivotcontext1=Min(Category(val1),4); int pivotcontext2=Min(Category(val2),6); WriteDynamicBit(&self->encoder,absvalue>1, &self->pivotbins[comp][k-1][pivotcontext1][pivotcontext2], self->pivotshift); if(absvalue>1) { // The absolute of this component is >=2. Proceed with compressing // the absolute value. int val3,n; if(IsFirstRow(k)) { val3=Column(k)-1; n=0; } else if(IsFirstColumn(k)) { val3=Row(k)-1; n=1; } else { val3=Category(k-4); n=2; } int magnitudecontext1=Min(Category(val1),8); int magnitudecontext2=Min(Category(val2),8); int remaindercontext=val3; // Compress absolute value. WriteUniversalCode(&self->encoder,absvalue-2, self->acmagnitudebins[comp][n][magnitudecontext1][magnitudecontext2], self->acmagnitudeshift, self->acremainderbins[comp][n][remaindercontext], self->acremaindershift); } CompressACSign(self,comp,k,absvalue,current,north,west,quantization); }