예제 #1
0
        private static CompressedImage Compress(Matrix matrix, int quality = 50)
        {
            var allQuantizedBytes = new List <byte>();

            for (var y = 0; y < matrix.Height; y += DCTSize)
            {
                for (var x = 0; x < matrix.Width; x += DCTSize)
                {
                    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.AddRange(quantizedBytes);
                    }
                }
            }

            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 = matrix.Height, Width = matrix.Width
            });
        }
예제 #2
0
        private static void Encode(Options options)
        {
            var compressionLevel   = CalcCompressionLevel(options);
            var compressedFileName = options.PathToBmp + ".compressed." + options.DCTSize + "." + compressionLevel;

            var bmp = (Bitmap)Image.FromFile(options.PathToBmp);

            CheckCorrectSize(options, bmp);

            var grayscaleMatrix = bmp.ToGrayscaleMatrix();
            var compressedImage = grayscaleMatrix.ParallelCompressWithDCT(options);

            var bytesForHuffman    = compressedImage.ToBytesArray();
            var decodeTable        = null as Dictionary <BitsWithLength, byte>;
            var encodedWithHuffman = HuffmanCodec.Encode(bytesForHuffman, out decodeTable, options);

            using (FileStream fs = File.OpenWrite(compressedFileName))
            {
                var encodedDataLength = BitConverter.GetBytes(encodedWithHuffman.Length);
                fs.Write(encodedDataLength, 0, 4);

                fs.Write(encodedWithHuffman, 0, encodedWithHuffman.Length);

                var serializedTable = SerializeDecodeTable(decodeTable);
                fs.Write(serializedTable, 0, serializedTable.Length);
            }
        }
예제 #3
0
        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);
                    }
                }
            }

            return(result);
        }
예제 #4
0
        public static CompressedImage Compress(Matrix matrix, int quality = 50)
        {
            var allQuantizedBytes = new byte[matrix.Height * matrix.Width * 6];
            var comps             = new[] { Component.y, Component.cb, Component.cr };
            var qm = GetQuantizationMatrix(quality);

            Parallel.For(0, matrix.Height / 8, i =>
            {
                var y = i * 8;
                for (var x = 0; x < matrix.Width; x += DCTSize)
                {
                    for (var index = 0; index < 3; index++)
                    {
                        var subMatrix = GetSubMatrix(matrix, y, DCTSize, x, DCTSize, comps[index]);
                        ShiftMatrixValues(subMatrix, -128);
                        var channelFreqs   = DCT.DCT2D(subMatrix);
                        var quantizedFreqs = Quantize(channelFreqs, qm);
                        var quantizedBytes = ZigZagScan(quantizedFreqs);
                        quantizedBytes.CopyTo(allQuantizedBytes,
                                              ((3 * x / 8 + (y / 8) * 3 * (matrix.Width / 8)) + index) *
                                              quantizedBytes.Length);
                    }
                }
            });

            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 = matrix.Height, Width = matrix.Width
            });
        }
예제 #5
0
        private static CompressedImage Compress(Matrix matrix, int quality = 50)
        {
            var allQuantizedBytes = new byte[matrix.Height * matrix.Width * 3];

            Parallel.ForEach(Enumerable.Range(0, matrix.Height / DCTSize).Select(y => y * DCTSize), y =>
            {
                for (var x = 0; x < matrix.Width; x += DCTSize)
                {
                    var i = 0;
                    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);
                        DCT.DCT2D(subMatrix);
                        var quantizedFreqs = Quantize(subMatrix, quality);
                        var quantizedBytes = ZigZagScan(quantizedFreqs);
                        for (var j = 0; j < quantizedBytes.Length; j++)
                        {
                            allQuantizedBytes[(x * 8 + y * matrix.Width) * 3 + 64 * i + j] = quantizedBytes[j];
                        }
                        i++;
                        i %= 3;
                    }
                }
            });

            var compressedBytes = HuffmanCodec.Encode(allQuantizedBytes, out var decodeTable, out var bitsCount);

            return(new CompressedImage
            {
                Quality = quality, CompressedBytes = compressedBytes, BitsCount = bitsCount, DecodeTable = decodeTable,
                Height = matrix.Height, Width = matrix.Width, RealHeight = matrix.RealHeight, RealWidth = matrix.RealWidth
            });
        }
예제 #6
0
        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);
        }
예제 #7
0
        private static void Decode(Options options)
        {
            var uncompressedFileName = options.PathToEncoded + ".uncompressed." + options.DCTSize + "." +
                                       CalcCompressionLevel(options) + ".bmp";
            var data = File.ReadAllBytes(options.PathToEncoded);
            var encodedDataLength = BitConverter.ToInt32(data, 0);

            var encodedData = new byte[encodedDataLength];

            Buffer.BlockCopy(data, 4, encodedData, 0, encodedDataLength);

            var decodeTable = DeserializeDecodeTable(data, 4 + encodedDataLength);

            var decodedHuffman = HuffmanCodec.Decode(encodedData, decodeTable, options);
            var compressedImg  = CompressedImage.LoadFromBytesArray(decodedHuffman, options.DCTSize);

            compressedImg
            .ParallelUncompressWithDCT(options)
            .GrayscaleMatrixToBitmap()
            .Save(uncompressedFileName);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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
            });
        }
예제 #10
0
        private static CompressedImage Compress(Matrix matrix)
        {
            var allQuantizedBytes = new byte[matrix.Height * matrix.Width * 3];


            Parallel.For(0, matrix.Height / DctSize, h =>
            {
                Parallel.For(0, matrix.Width / DctSize, w =>
                {
                    var counter = 0;
                    foreach (var selector in new Func <Pixel, double>[]
                    {
                        p => 16.0 + (65.738 * p.C1 + 129.057 * p.C2 + 24.064 * p.C3) / 256.0,
                        p => 128.0 + (-37.945 * p.C1 - 74.494 * p.C2 + 112.439 * p.C3) / 256.0,
                        p => 128.0 + (112.439 * p.C1 - 94.154 * p.C2 - 18.285 * p.C3) / 256.0
                    })
                    {
                        var subMatrix = GetSubMatrix(matrix, h * DctSize, DctSize, w * DctSize, DctSize, selector);
                        ShiftMatrixValues(subMatrix, -128);
                        var channelFreqs   = FastDct.Dct(subMatrix);
                        var quantizedFreqs = Quantize(channelFreqs);
                        var quantizedBytes = ZigZagScan(quantizedFreqs);
                        Array.Copy(quantizedBytes, 0, allQuantizedBytes,
                                   h * 8 * matrix.Width * 3 + w * 64 * 3 + 64 * counter++, 64);
                    }
                });
            });

            var compressedBytes = HuffmanCodec.Encode(allQuantizedBytes, out var decodeTable, out var bitsCount);

            return(new CompressedImage
            {
                Quality = CompressionQuality,
                CompressedBytes = compressedBytes,
                BitsCount = bitsCount,
                DecodeTable = decodeTable,
                Height = matrix.Height,
                Width = matrix.Width
            });
        }
예제 #11
0
        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
            });
        }
예제 #12
0
        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);
        }
예제 #13
0
        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
            });
        }
예제 #14
0
        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);
        }
예제 #15
0
        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);
        }