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 bool IsFirstRowOrColumn(unsigned int k) { return IsFirstRow(k)||IsFirstColumn(k); }
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); }