private static CbCrImage Uncompress(CompressedImage image) { var result = new CbCrImage(image.Height, image.Width); var DCTcoefficients = DCT.GetCoefficientsMatrix(DCTSize, DCTSize); var transponseDCTcoefficients = DCT.Transpose(DCTcoefficients); var quantizationMatrix = GetQuantizationMatrix(image.Quality); using (var allQuantizedBytes = new MemoryStream(HuffmanCodec.Decode(image.CompressedBytes, image.DecodeTable, image.BitsCount))) { Parallel.For(0, image.Height / DCTSize, ky => { var y = ky; Parallel.For(0, image.Width / DCTSize, _x => { var x = _x; var _y = new double[DCTSize, DCTSize]; var cb = new double[DCTSize, DCTSize]; var cr = new double[DCTSize, DCTSize]; var c = 0; foreach (var channel in new[] { _y, cb, cr }) { var quantizedBytes = new byte[DCTSize * DCTSize]; lock (allQuantizedBytes) { allQuantizedBytes.Seek((y * (image.Width / 8) + x) * 8 * 8 * 3 + 8 * 8 * c, SeekOrigin.Begin); allQuantizedBytes.ReadAsync(quantizedBytes, 0, quantizedBytes.Length).Wait(); } c++; var quantizedFreqs = ZigZagUnScan(quantizedBytes); var channelFreqs = DeQuantize(quantizedFreqs, quantizationMatrix); DCT.IDCT2D(channelFreqs, channel, DCTcoefficients, transponseDCTcoefficients); } SetPixels(result, _y, cb, cr, y * DCTSize, x * DCTSize, 128); }); }); } return(result); }
private static CompressedImage Compress(CbCrImage cbCrImage, int quality = 50) { var allQuantizedBytes = new byte[(cbCrImage.Height - cbCrImage.Height % 8) * (cbCrImage.Width - cbCrImage.Width % 8) * 3]; var shiftFunc = new Func <double, double>(x => x - 128); var DCTcoefficients = DCT.GetCoefficientsMatrix(DCTSize, DCTSize); var transponseDCTcoefficients = DCT.Transpose(DCTcoefficients); var quantizationMatrix = GetQuantizationMatrix(quality); var channels = new List <double[, ]> { cbCrImage.y, cbCrImage.Cb, cbCrImage.Cr }; Parallel.For(0, cbCrImage.Height / DCTSize, y => { var y1 = y; Parallel.For(0, cbCrImage.Width / DCTSize, _x => { var x = _x; Parallel.For(0, channels.Count, _k => { var k = _k; var subMatrix = GetSubMatrix(channels[k], y1 * DCTSize, DCTSize, x * DCTSize, DCTSize, shiftFunc); var channelFreqs = DCT.DCT2D(subMatrix, DCTcoefficients, transponseDCTcoefficients); var quantizedFreqs = Quantize(channelFreqs, quantizationMatrix); var quantizedBytes = ZigZagScan(quantizedFreqs); var index = (y1 * (cbCrImage.Width / DCTSize) + x) * DCTSize * DCTSize * 3 + DCTSize * DCTSize * k; for (var i = 0; i < quantizedBytes.Count; i++) { allQuantizedBytes[index + i] = quantizedBytes[i]; } }); }); }); long bitsCount; Dictionary <BitsWithLength, byte> decodeTable; var compressedBytes = HuffmanCodec.Encode(allQuantizedBytes, out decodeTable, out bitsCount); return(new CompressedImage { Quality = quality, CompressedBytes = compressedBytes, BitsCount = bitsCount, DecodeTable = decodeTable, Height = cbCrImage.Height, Width = cbCrImage.Width }); }