/// <summary> /// Dequantize, perform the inverse DCT and store decodedBlock.Block to the into the corresponding <see cref="JpegPixelArea"/> instance. /// </summary> /// <param name="decoder">The <see cref="JpegDecoderCore"/></param> /// <param name="decodedBlock">The <see cref="DecodedBlock"/></param> private void ProcessBlockColors(JpegDecoderCore decoder, ref DecodedBlock decodedBlock) { this.data.Block = decodedBlock.Block; int qtIndex = decoder.ComponentArray[this.componentIndex].Selector; this.data.QuantiazationTable = decoder.QuantizationTables[qtIndex]; Block8x8F *b = this.pointers.Block; Block8x8F.UnZig(b, this.pointers.QuantiazationTable, this.pointers.Unzig); DCT.TransformIDCT(ref *b, ref *this.pointers.Temp1, ref *this.pointers.Temp2); JpegPixelArea destChannel = decoder.GetDestinationChannel(this.componentIndex); JpegPixelArea destArea = destChannel.GetOffsetedSubAreaForBlock(decodedBlock.Bx, decodedBlock.By); destArea.LoadColorsFrom(this.pointers.Temp1, this.pointers.Temp2); }
/// <summary> /// Process the current block at (<see cref="bx"/>, <see cref="by"/>) /// </summary> /// <param name="decoder">The decoder</param> /// <param name="i">The index of the scan</param> /// <param name="compIndex">The component index</param> /// <param name="hi">Horizontal sampling factor at the given component index</param> private void ProcessBlockImpl(JpegDecoderCore decoder, int i, int compIndex, int hi) { var b = this.pointers.Block; int huffmannIdx = (AcTableIndex * HuffmanTree.ThRowSize) + this.pointers.Scan[i].AcTableSelector; if (this.ah != 0) { this.Refine(decoder, ref decoder.HuffmanTrees[huffmannIdx], 1 << this.al); } else { int zig = this.zigStart; if (zig == 0) { zig++; // Decode the DC coefficient, as specified in section F.2.2.1. byte value = decoder.DecodeHuffman( ref decoder.HuffmanTrees[(DcTableIndex * HuffmanTree.ThRowSize) + this.pointers.Scan[i].DcTableSelector]); if (value > 16) { throw new ImageFormatException("Excessive DC component"); } int deltaDC = decoder.Bits.ReceiveExtend(value, decoder); this.pointers.Dc[compIndex] += deltaDC; // b[0] = dc[compIndex] << al; Block8x8F.SetScalarAt(b, 0, this.pointers.Dc[compIndex] << this.al); } if (zig <= this.zigEnd && this.eobRun > 0) { this.eobRun--; } else { // Decode the AC coefficients, as specified in section F.2.2.2. for (; zig <= this.zigEnd; zig++) { byte value = decoder.DecodeHuffman(ref decoder.HuffmanTrees[huffmannIdx]); byte val0 = (byte)(value >> 4); byte val1 = (byte)(value & 0x0f); if (val1 != 0) { zig += val0; if (zig > this.zigEnd) { break; } int ac = decoder.Bits.ReceiveExtend(val1, decoder); // b[Unzig[zig]] = ac << al; Block8x8F.SetScalarAt(b, this.pointers.Unzig[zig], ac << this.al); } else { if (val0 != 0x0f) { this.eobRun = (ushort)(1 << val0); if (val0 != 0) { this.eobRun |= (ushort)decoder.DecodeBits(val0); } this.eobRun--; break; } zig += 0x0f; } } } } if (decoder.IsProgressive) { if (this.zigEnd != Block8x8F.ScalarCount - 1 || this.al != 0) { // We haven't completely decoded this 8x8 block. Save the coefficients. // this.ProgCoeffs[compIndex][((@by * XNumberOfMCUs) * hi) + bx] = b.Clone(); decoder.ProgCoeffs[compIndex][((this.by * this.XNumberOfMCUs) * hi) + this.bx] = *b; // At this point, we could execute the rest of the loop body to dequantize and // perform the inverse DCT, to save early stages of a progressive image to the // *image.YCbCr buffers (the whole point of progressive encoding), but in Go, // the jpeg.Decode function does not return until the entire image is decoded, // so we "continue" here to avoid wasted computation. return; } } // Dequantize, perform the inverse DCT and store the block to the image. Block8x8F.UnZig(b, this.pointers.QuantiazationTable, this.pointers.Unzig); DCT.TransformIDCT(ref *b, ref *this.pointers.Temp1, ref *this.pointers.Temp2); var destChannel = decoder.GetDestinationChannel(compIndex); var destArea = destChannel.GetOffsetedSubAreaForBlock(this.bx, this.by); destArea.LoadColorsFrom(this.pointers.Temp1, this.pointers.Temp2); }