private static Matrix Uncompress(CompressedImage image) { var result = new Matrix(image.Height, image.Width, image.RealHeight, image.RealWidth); using (var allQuantizedBytes = new MemoryStream(HuffmanCodec.Decode(image.CompressedBytes, image.DecodeTable, image.BitsCount))) { Parallel.ForEach(Enumerable.Range(0, image.Height / DCTSize).Select(y => y * DCTSize), y => { for (var x = 0; x < image.Width; x += DCTSize) { var _y = new double[DCTSize, DCTSize]; var cb = new double[DCTSize, DCTSize]; var cr = new double[DCTSize, DCTSize]; for (var i = 0; i < 3; i++) { var quantizedBytes = new byte[DCTSize * DCTSize]; allQuantizedBytes.Position = (x * 8 + y * image.Width) * 3 + 64 * i; allQuantizedBytes.ReadAsync(quantizedBytes, 0, quantizedBytes.Length).Wait(); var quantizedFreqs = ZigZagUnScan(quantizedBytes); var channelFreqs = DeQuantize(quantizedFreqs, image.Quality); DCT.IDCT2D(channelFreqs); ShiftMatrixValues(channelFreqs, 128); switch (i) { case 0: _y = channelFreqs; break; case 1: cb = channelFreqs; break; default: cr = channelFreqs; break; } } SetPixels(result, _y, cb, cr, PixelFormat.YCbCr, y, x); } }); } return(result); }
public void araitimer(float[][] testArie, int tasks, int count) { TimeSpan time = TimeSpan.Zero; for (int i = 0; i < count; i++) { Stopwatch sw = new Stopwatch(); sw.Start(); DCT.taskSeperater(testArie, tasks); DCT.DirectDCTTaskSeparator(testArie, tasks); sw.Stop(); time = bestwert(sw.Elapsed, time); } //var time = mittelwertZeit(sw.Elapsed, count); Console.WriteLine($"Matrix Arai Optimized:{ time} Count {tasks}"); Stopwatch sw2 = new Stopwatch(); }
static void Main(string[] args) { //try //{ Console.WriteLine(IntPtr.Size == 8 ? "64-bit version" : "32-bit version"); var sw = Stopwatch.StartNew(); var fileName = @"sample.bmp"; // var fileName = "Big_Black_River_Railroad_Bridge.bmp"; var compressedFileName = fileName + ".compressed." + CompressionQuality; var uncompressedFileName = fileName + ".uncompressed." + CompressionQuality + ".bmp"; DCT.BuildCache(DCTSize); using (var fileStream = File.OpenRead(fileName)) using (var bmp = (Bitmap)Image.FromStream(fileStream, false, false)) { var imageMatrix = (Matrix)bmp; sw.Stop(); Console.WriteLine($"{bmp.Width}x{bmp.Height} - {fileStream.Length / (1024.0 * 1024):F2} MB"); sw.Start(); var compressionResult = Compress(imageMatrix, CompressionQuality); compressionResult.Save(compressedFileName); } sw.Stop(); Console.WriteLine("Compression: " + sw.Elapsed); sw.Restart(); var compressedImage = CompressedImage.Load(compressedFileName); var uncompressedImage = Uncompress(compressedImage); var resultBmp = (Bitmap)uncompressedImage; resultBmp.Save(uncompressedFileName, ImageFormat.Bmp); Console.WriteLine("Decompression: " + sw.Elapsed); Console.WriteLine($"Peak commit size: {MemoryMeter.PeakPrivateBytes() / (1024.0*1024):F2} MB"); Console.WriteLine($"Peak working set: {MemoryMeter.PeakWorkingSet() / (1024.0*1024):F2} MB"); //} //catch(Exception e) //{ // Console.WriteLine(e); //} }
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 }); }
private static CompressedImage Compress(Matrix matrix, int quality = 50) { var tuples = new List <(int, int)>(); for (var y = 0; y < matrix.Height; y += DCTSize) { for (var x = 0; x < matrix.Width; x += DCTSize) { tuples.Add((x, y)); } } var allQuantizedBytes = new List <byte> [tuples.Count]; // MathEx.LoopByTwoVariablesStepped(0, matrix.Height, 0, matrix.Width, DCTSize, (y, x) => Parallel.For(0, tuples.Count, i => { var(x, y) = tuples[i]; allQuantizedBytes[i] = new List <byte>(); foreach (var selector in new Func <Pixel, double>[] { p => p.Y, p => p.Cb, p => p.Cr }) { var subMatrix = GetSubMatrix(matrix, y, DCTSize, x, DCTSize, selector); ShiftMatrixValues(subMatrix, -128); var channelFreqs = DCT.DCT2D(subMatrix); var quantizedFreqs = Quantize(channelFreqs, quality); var quantizedBytes = ZigZagScan(quantizedFreqs); // allQuantizedBytes.Add(quantizedBytes); allQuantizedBytes[i].AddRange(quantizedBytes); } }); var compressedBytes = HuffmanCodec.Encode(allQuantizedBytes.SelectMany(i => i), out var decodeTable, out var bitsCount); return(new CompressedImage { Quality = quality, CompressedBytes = compressedBytes, BitsCount = bitsCount, DecodeTable = decodeTable, Height = matrix.Height, Width = matrix.Width }); }
private Matrix Decompress(CompressedImage image) { if (image.Quality != compressionQuality) { quantizationMatrix = GetQuantizationMatrix(image.Quality); } var matrix = new Matrix(image.Height, image.Width, PixelFormat.YCbCr); var allQuantizedBytes = HuffmanCodec.Decode(image.CompressedBytes, image.DecodeTable, image.BitsCount); var heigth = image.Height / DCTSize; var width = image.Width / DCTSize; var dct = new DCT(DCTSize); Parallel.For(0, heigth, h => { Parallel.For(0, width, w => { var y = new double[DCTSize, DCTSize]; var cb = new double[DCTSize, DCTSize]; var cr = new double[DCTSize, DCTSize]; var channels = new[] { y, cb, cr }; var blockLength = DCTSize * DCTSize * channels.Length; var readPos = h * blockLength * width + w * blockLength; for (var i = 0; i < channels.Length; i++) { var channel = channels[i]; var channelReadPos = readPos + i * DCTSize * DCTSize; var quantizedBytes = allQuantizedBytes.ReadFrom(channelReadPos, DCTSize * DCTSize); var quantizedFreqs = ZigZagUnScan(quantizedBytes); var channelFreqs = DeQuantize(quantizedFreqs); dct.IDCT2D(channelFreqs, channel); channel.ShiftValues(128); } matrix.SetPixels(y, cb, cr, h * DCTSize, w * DCTSize); }); }); return(matrix); }
private CompressedImage Compress(Matrix matrix, int quality = 50) { var heigth = matrix.Height / DCTSize; var width = matrix.Width / DCTSize; var quantinizedMatrix = new List <byte> [heigth, width]; var channelSelectors = new Func <Pixel, double>[] { p => p.Y, p => p.Cb, p => p.Cr }; var dct = new DCT(DCTSize); Parallel.For(0, heigth, h => { Parallel.For(0, width, w => { quantinizedMatrix[h, w] = new List <byte>(); foreach (var selector in channelSelectors) { var subMatrix = matrix.GetSubMatrix(h * DCTSize, DCTSize, w * DCTSize, DCTSize, selector); subMatrix.ShiftValues(-128); var channelFreqs = dct.DCT2D(subMatrix); var quantizedFreqs = Quantize(channelFreqs); var quantizedBytes = ZigZagScan(quantizedFreqs); quantinizedMatrix[h, w].AddRange(quantizedBytes); } }); }); var bytes = quantinizedMatrix.Join(); var compressedBytes = HuffmanCodec.Encode(bytes, out var decodeTable, out var bitsCount); return(new CompressedImage { Quality = quality, CompressedBytes = compressedBytes, BitsCount = bitsCount, DecodeTable = decodeTable, Height = matrix.Height, Width = matrix.Width }); }
public static Matrix Uncompress(CompressedImage image) { var result = new Matrix(image.Height, image.Width); var container = new byte[image.Height * image.Width * 3]; using (var allQuantizedBytes = new MemoryStream(HuffmanCodec.Decode(image.CompressedBytes, image.DecodeTable, image.BitsCount))) allQuantizedBytes.Read(container); var qm = GetQuantizationMatrix(image.Quality); Parallel.For(0, image.Height / 8, i => { var y = i * 8; for (var x = 0; x < image.Width; x += DCTSize) { var channels = new[] { new double[DCTSize, DCTSize], new double[DCTSize, DCTSize], new double[DCTSize, DCTSize] }; for (var index = 0; index < 3; index++) { var channel = channels[index]; var quantizedBytes = new byte[DCTSize * DCTSize]; Array.Copy(container, (index + 3 * i * image.Width / 8 + 3 * x / 8) * 64, quantizedBytes, 0, 64); var quantizedFreqs = ZigZagUnScan(quantizedBytes); var channelFreqs = DeQuantize(quantizedFreqs, qm); DCT.IDCT2D(channelFreqs, channel); ShiftMatrixValues(channel, 128); } SetPixels(result, channels[0], channels[1], channels[2], PixelFormat.YCbCr, y, x); } }); return(result); }
public void PerformanceTest() { //Generate test picture as onedimensional array and fill it with the correct values float[] testValues = new float[65536]; for (int i = 0; i < 65536; i++) { testValues[i] = (i % 256 + (i / 256) * 8) % 256; } Stopwatch watch = new Stopwatch(); Stopwatch recordTime = new Stopwatch(); var recordArai = TimeSpan.Zero; var recordDCT = TimeSpan.Zero; var recordSeparatedDCT = TimeSpan.Zero; //Arai test watch.Start(); while (watch.ElapsedMilliseconds < 10000) { recordTime.Start(); float[][] listOfBlocks = Bilderaufteilen(testValues, 256, 256); //DCT.araiAranger(listOfBlocks);//------------------------------------------- //listOfBlocks = Bilderaufteilen(testValues, 256, 256); //DCT.DirectDCTAranger(listOfBlocks);//--------------------------- listOfBlocks = DCT.taskSeperater(listOfBlocks, 100); float[] outputValues = CombineBlocksToPicture(listOfBlocks, 256, 256); recordTime.Stop(); recordArai = bestwert(recordTime.Elapsed, recordArai); recordTime.Reset(); } watch.Reset(); //DCT test watch.Start(); while (watch.ElapsedMilliseconds < 10000) { recordTime.Start(); float[][] listOfBlocks = Bilderaufteilen(testValues, 256, 256); listOfBlocks = DCT.DirectDCTTaskSeparator(listOfBlocks, 100); float[] outputValues = CombineBlocksToPicture(listOfBlocks, 256, 256); recordTime.Stop(); recordDCT = bestwert(recordTime.Elapsed, recordDCT); recordTime.Reset(); } watch.Reset(); //DCT test watch.Start(); while (watch.ElapsedMilliseconds < 10000) { recordTime.Start(); float[][] listOfBlocks = Bilderaufteilen(testValues, 256, 256); listOfBlocks = DCT.SeparatedDCTTaskSeparator(listOfBlocks, 100); float[] outputValues = CombineBlocksToPicture(listOfBlocks, 256, 256); recordTime.Stop(); recordSeparatedDCT = bestwert(recordTime.Elapsed, recordDCT); recordTime.Reset(); } watch.Reset(); Console.WriteLine($"Arai Record Time: {recordArai}"); Console.WriteLine($"Direct DCT Record Time: {recordDCT}"); Console.WriteLine($"Separated DCT Record Time: {recordSeparatedDCT}"); Console.ReadKey(); }
public void schleifentest() { float[,] testMat81 = new float[8, 8] { { 16, 11, 10, 16, 24, 40, 51, 61 }, { 12, 12, 14, 19, 26, 58, 60, 55 }, { 14, 13, 16, 24, 40, 57, 69, 56 }, { 14, 17, 22, 29, 51, 87, 80, 62 }, { 18, 22, 37, 56, 68, 109, 103, 77 }, { 24, 35, 55, 64, 81, 194, 113, 92 }, { 49, 64, 78, 87, 103, 121, 120, 101 }, { 72, 92, 95, 98, 121, 100, 103, 99 } }; float[,] testMat82 = new float[8, 8] { { 92, 3, -9, -7, 3, -1, 0, 2 }, { -39, -58, 12, 17, -2, 2, 4, 2 }, { -84, 62, 1, -18, 3, 4, -5, 5 }, { -52, -36, -10, 14, -10, 4, -2, 0 }, { -86, -40, 49, -7, 17, -6, -2, 5 }, { -62, 65, -12, -2, 3, -8, -2, 0 }, { -17, 14, -36, 17, -11, 3, 3, -1 }, { -54, 32, -9, -9, 22, 0, 1, 3 } }; float[,] testMat83 = new float[8, 8] { { -76, -73, -67, -62, -58, -67, -64, -55 }, { -65, -69, -73, -38, -19, -43, -59, -56 }, { -66, -69, -60, -15, 16, -24, -62, -55 }, { -65, -70, -57, -6, 26, -22, -58, -59 }, { -61, -67, -60, -24, -2, -40, -60, -58 }, { -49, -63, -68, -58, -51, -60, -70, -53 }, { -43, -57, -64, -69, -73, -67, -63, -45 }, { -41, -49, -59, -60, -63, -52, -50, -34 } }; Stopwatch sw = new Stopwatch(); Stopwatch sw1 = new Stopwatch(); Stopwatch sw2 = new Stopwatch(); sw.Start(); for (int i = 0; i < 5000; i++) { DCT.DCTdirect(testMat83); } sw.Stop(); DCT.IDCTdirect(DCT.DCTdirect(testMat83)); sw1.Start(); for (int i = 0; i < 5000; i++) { DCT.DCTseparated(testMat83); } sw1.Stop(); sw2.Start(); for (int i = 0; i < 5000; i++) { DCT.DCTArai(testMat83); } sw2.Stop(); Console.WriteLine($"/{sw.Elapsed} /{sw1.Elapsed} /{sw2.Elapsed}"); //Console.ReadKey(); }
public void TestDCT() { float[,] testMat81 = new float[8, 8] { { 16, 11, 10, 16, 24, 40, 51, 61 }, { 12, 12, 14, 19, 26, 58, 60, 55 }, { 14, 13, 16, 24, 40, 57, 69, 56 }, { 14, 17, 22, 29, 51, 87, 80, 62 }, { 18, 22, 37, 56, 68, 109, 103, 77 }, { 24, 35, 55, 64, 81, 194, 113, 92 }, { 49, 64, 78, 87, 103, 121, 120, 101 }, { 72, 92, 95, 98, 121, 100, 103, 99 } }; float[,] testMat82 = new float[8, 8] { { 92, 3, -9, -7, 3, -1, 0, 2 }, { -39, -58, 12, 17, -2, 2, 4, 2 }, { -84, 62, 1, -18, 3, 4, -5, 5 }, { -52, -36, -10, 14, -10, 4, -2, 0 }, { -86, -40, 49, -7, 17, -6, -2, 5 }, { -62, 65, -12, -2, 3, -8, -2, 0 }, { -17, 14, -36, 17, -11, 3, 3, -1 }, { -54, 32, -9, -9, 22, 0, 1, 3 } }; float[,] testMat83 = new float[8, 8] { { -76, -73, -67, -62, -58, -67, -64, -55 }, { -65, -69, -73, -38, -19, -43, -59, -56 }, { -66, -69, -60, -15, 16, -24, -62, -55 }, { -65, -70, -57, -6, 26, -22, -58, -59 }, { -61, -67, -60, -24, -2, -40, -60, -58 }, { -49, -63, -68, -58, -51, -60, -70, -53 }, { -43, -57, -64, -69, -73, -67, -63, -45 }, { -41, -49, -59, -60, -63, -52, -50, -34 } }; Stopwatch sw = new Stopwatch(); Stopwatch sw1 = new Stopwatch(); Stopwatch sw2 = new Stopwatch(); Console.WriteLine("Ausgangsmatrix:"); DCT.printMatrix(testMat83); Console.WriteLine("Matrix direct:"); sw.Start(); DCT.printMatrix(DCT.DCTdirect(testMat83)); sw.Stop(); Console.WriteLine("Matrix direct: Elapsed={0} \n", sw.Elapsed); Console.WriteLine("Matrix direct inverse:"); DCT.printMatrix(DCT.IDCTdirect(DCT.DCTdirect(testMat83))); Console.WriteLine("Matrix separated:"); sw1.Start(); DCT.printMatrix(DCT.DCTseparated(testMat83)); sw1.Stop(); Console.WriteLine("Matrix separated: Elapsed={0} \n", sw1.Elapsed); Console.WriteLine("Matrix Arai:"); sw2.Start(); DCT.printMatrix(DCT.DCTArai(testMat83)); sw2.Stop(); Console.WriteLine("Matrix Arai: Elapsed={0} \n", sw2.Elapsed); //Console.ReadKey(); }
public void PPMtoJpg(string imageSrc, string imagedest) { Bitstream bs = new Bitstream(); PlainFormatReader pfr = new PlainFormatReader(imageSrc); Mathloc ml = new Mathloc(); Picture pic = pfr.ReadPicture(); int height = pic.Head.pixelMaxY; int width = pic.Head.pixelMaxX; Color3[,] col3 = new Color3[height, width]; byte[] colors = new byte[3]; //convert RGB to YUV for each pixel for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { col3[y, x] = pic.Data.PictureYX[y, x]; colors[0] = col3[y, x].a; // R colors[1] = col3[y, x].b; // G colors[2] = col3[y, x].c; // B colors = ml.RGBToYUV(colors); col3[y, x].a = colors[0]; // Y col3[y, x].b = colors[1]; // U col3[y, x].c = colors[2]; // V } } //convert float array to byte array float[,] yArray = new float[width, height]; // width and height vertauscht float[,] uArray = new float[width, height]; float[,] vArray = new float[width, height]; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { yArray[i, j] = (float)col3[j, i].a; uArray[i, j] = (float)col3[j, i].b; vArray[i, j] = (float)col3[j, i].c; } } byte[,] yArrayEnde = new byte[width, height]; byte[,] uArrayEnde = new byte[width, height]; byte[,] vArrayEnde = new byte[width, height]; //get float [number of 8x8][8x8] var yarry = aufteilen(yArray); var uarry = aufteilen(uArray); var varry = aufteilen(vArray); //geht beim 40x40 bild 25 for (int y = 0; y < height / 8; y++) { for (int x = 0; x < width / 8; x++) { //DCTDirect for (int i = 0; i < ((height * width) / 64); i++) { yArray = DCT.DCTdirect(yarry[i]); uArray = DCT.DCTdirect(uarry[i]); vArray = DCT.DCTdirect(varry[i]); } //convert float array to byte array byte[,] yArrayB = new byte[width, height]; byte[,] uArrayB = new byte[width, height]; byte[,] vArrayB = new byte[width, height]; for (int i = 0; i < width / 8; i++) { for (int j = 0; j < height / 8; j++) { yArrayB[i, j] = (byte)yArray[i, j]; uArrayB[i, j] = (byte)uArray[i, j]; vArrayB[i, j] = (byte)vArray[i, j]; } } for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { yArrayEnde[i * x, j *y] = yArrayB[i, j]; uArrayEnde[i * x, j *y] = uArrayB[i, j]; vArrayEnde[i * x, j *y] = vArrayB[i, j]; } } byte[] yArrayB2 = new byte[64]; byte[] uArrayB2 = new byte[64]; byte[] vArrayB2 = new byte[64]; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { yArrayB2[ZigZagTable2[i * j]] = yArrayB[i, j]; uArrayB2[ZigZagTable2[i * j]] = uArrayB[i, j]; vArrayB2[ZigZagTable2[i * j]] = vArrayB[i, j]; } } // Create Huffmantables //yArrayEnde = HuffmanCalc(YDCNodes, YDCValues, yArrayB2); //yArrayEnde = HuffmanCalc(YDCNodes, YACValues, yArrayB2); //uArrayEnde = HuffmanCalc(CbDCNodes, CbDCValues, uArrayB2); //uArrayEnde = HuffmanCalc(CbACNodes, CbACValues, uArrayB2); //vArrayEnde = HuffmanCalc(CbDCNodes, CbDCValues, vArrayB2); //vArrayEnde = HuffmanCalc(CbACNodes, CbACValues, vArrayB2); } } //create JPG head PictureHead.CreateJPGHead(bs, (ushort)height, (ushort)width); //TODO: DCT for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { bs.AddByte((byte)yArrayEnde[x, y]); bs.AddByte((byte)uArrayEnde[x, y]); bs.AddByte((byte)vArrayEnde[x, y]); } } bs.AddShort(0xffd9); //End of Picture Marker bs.WriteToFile(imagedest); }
private static Matrix Uncompress(CompressedImage image) { var result = new Matrix(image.Height, image.Width); // using (var allQuantizedBytes = // new MemoryStream(HuffmanCodec.Decode(image.CompressedBytes, image.DecodeTable, image.BitsCount))) // { // for (var y = 0; y < image.Height; y += DCTSize) // for (var x = 0; x < image.Width; x += DCTSize) // { // var _y = new double[DCTSize, DCTSize]; // var cb = new double[DCTSize, DCTSize]; // var cr = new double[DCTSize, DCTSize]; // foreach (var channel in new[] {_y, cb, cr}) // { // var quantizedBytes = new byte[DCTSize * DCTSize]; // allQuantizedBytes.ReadAsync(quantizedBytes, 0, quantizedBytes.Length).Wait(); // var quantizedFreqs = ZigZagUnScan(quantizedBytes); // var channelFreqs = DeQuantize(quantizedFreqs, image.Quality); // DCT.IDCT2D(channelFreqs, channel); // ShiftMatrixValues(channel, 128); // } // // SetPixels(result, _y, cb, cr, PixelFormat.YCbCr, y, x); // } // } var decodedBytesArray = HuffmanCodec.Decode(image.CompressedBytes, image.DecodeTable, image.BitsCount); var tuples = new List <(int, int)>(); for (var y = 0; y < image.Height; y += DCTSize) { for (var x = 0; x < image.Width; x += DCTSize) { tuples.Add((x, y)); } } // var allQuantizedBytes = new List<byte>[tuples.Count]; Parallel.For(0, tuples.Count, i => { var(x, y) = tuples[i]; var _y = new double[DCTSize, DCTSize]; var cb = new double[DCTSize, DCTSize]; var cr = new double[DCTSize, DCTSize]; var offset = 0; foreach (var channel in new[] { _y, cb, cr }) { var quantizedBytes = new byte[DCTSize * DCTSize]; Buffer.BlockCopy(decodedBytesArray, quantizedBytes.Length * (i * 3 + offset), quantizedBytes, 0, quantizedBytes.Length); var quantizedFreqs = ZigZagUnScan(quantizedBytes); var channelFreqs = DeQuantize(quantizedFreqs, image.Quality); DCT.IDCT2D(channelFreqs, channel); ShiftMatrixValues(channel, 128); offset++; } SetPixels(result, _y, cb, cr, PixelFormat.YCbCr, y, x); }); return(result); }