/// <summary> /// Writes a block of pixel data using the given quantization table, /// returning the post-quantized DC value of the DCT-transformed block. /// The block is in natural (not zig-zag) order. /// </summary> /// <param name="block">The block to write.</param> /// <param name="index">The quantization table index.</param> /// <param name="prevDC">The previous DC value.</param> /// <returns></returns> private int WriteBlock(Block block, QuantIndex index, int prevDC) { FDCT.Transform(block); // Emit the DC delta. int dc = Round(block[0], 8 * this.quant[(int)index][0]); this.EmitHuffRLE((HuffIndex)(2 * (int)index + 0), 0, dc - prevDC); // Emit the AC components. var h = (HuffIndex)(2 * (int)index + 1); int runLength = 0; for (int zig = 1; zig < Block.BlockSize; zig++) { int ac = Round(block[Unzig[zig]], 8 * this.quant[(int)index][zig]); if (ac == 0) { runLength++; } else { while (runLength > 15) { this.EmitHuff(h, 0xf0); runLength -= 16; } this.EmitHuffRLE(h, runLength, ac); runLength = 0; } } if (runLength > 0) { this.EmitHuff(h, 0x00); } return(dc); }
/// <summary> /// Writes the descrete quantization tables. /// </summary> /// <param name="writer">The writer to write to the stream.</param> private void WriteDescreteQuantizationTables(EndianBinaryWriter writer) { byte[] dqt = new byte[134]; // Write the define quantization table marker. Markers are always prefixed with with 0xff. dqt[0] = JpegConstants.Markers.XFF; dqt[1] = JpegConstants.Markers.DQT; dqt[2] = 0x00; dqt[3] = 0x84; // Length 132 this.fdct = new FDCT(this.quality); int offset = 4; for (int i = 0; i < 2; i++) { dqt[offset++] = (byte)i; // TODO: Perf. Split and avoid allocation. int[] tempArray = this.fdct.Quantum[i]; for (int j = 0; j < 64; j++) { dqt[offset++] = (byte)tempArray[ZigZag.ZigZagMap[j]]; } } writer.Write(dqt); }