public CompressedImage Compress(Bitmap bmp) { if (bmp.PixelFormat != PixelFormat.Format24bppRgb) { throw new Exception($"{bmp.PixelFormat} pixel format is not supported, supported rgb24"); } var pixelsMatrix = _pixelsExtractor.Extract(bmp); var converterPixelsMatrix = MatrixRgbToYCbCrConveter.Convert(pixelsMatrix); var residueYPiece = bmp.Height % (_thinIndex * _dctSize); var residueXPiece = bmp.Width % (_thinIndex * _dctSize); var countAddYPiece = residueYPiece == 0 ? 0 : _thinIndex * _dctSize - residueYPiece; var countAddXPiece = residueXPiece == 0 ? 0 : _thinIndex * _dctSize - residueXPiece; var extendedPixelsMatrix = _matrixExtender.Extend(converterPixelsMatrix, countAddYPiece, countAddXPiece); var yCbCrchannels = _channelExtractor.Extract(extendedPixelsMatrix); var thinnedCbChannel = _matrixThinner.Thin(yCbCrchannels.CbChannel, _thinIndex); var thinnedCrChannel = _matrixThinner.Thin(yCbCrchannels.CrChannel, _thinIndex); var dctYPieces = _dctCompressor.Compress(yCbCrchannels.YChannel, _dctSize, _compressionLevel, _lumiaMatrixProvider.GetMatrix()); var dctCbPieces = _dctCompressor.Compress(thinnedCbChannel, _dctSize, _compressionLevel, _colorMatrixProvider.GetMatrix()); var dctCrPieces = _dctCompressor.Compress(thinnedCrChannel, _dctSize, _compressionLevel, _colorMatrixProvider.GetMatrix()); var result = new List <byte>(); var countYBlocksPerColorBlock = _thinIndex * _thinIndex; for (int i = 0, thinI = 0; i < dctYPieces.Length; thinI++) { for (var j = 0; j < countYBlocksPerColorBlock; j++) { result.AddRange(dctYPieces[i++]); } result.AddRange(dctCbPieces[thinI]); result.AddRange(dctCrPieces[thinI]); } var rle = Rle <byte> .Encode(result).ToArray(); Dictionary <BitsWithLength, byte> decodeTable; long bitsCount; var huf = HuffmanCodec.Encode(rle, out decodeTable, out bitsCount); var compressedImage = new CompressedImage { ThinIndex = _thinIndex, CompressionLevel = _compressionLevel, DataBytes = huf, Height = extendedPixelsMatrix.GetLength(0), Width = extendedPixelsMatrix.GetLength(1), DecodeTable = decodeTable, BitsCount = bitsCount }; return(compressedImage); }
public void Test() { var bmp1 = (Bitmap)Image.FromFile(@"C:\Users\FessEmpty\Downloads\parallelprogramming-shpora2016-56f562c98bbf\parallelprogramming-shpora2016-56f562c98bbf\JPEG\sample.bmp"); var bitmapData1 = bmp1.LockBits(new Rectangle(0, 0, bmp1.Width, bmp1.Height), ImageLockMode.ReadOnly, bmp1.PixelFormat); const int rgpPixelSize = 3; var additional = bitmapData1.Stride - bitmapData1.Width * rgpPixelSize; var result = new RgbPixel[bmp1.Height, bmp1.Width]; unsafe { var imagePointer = (byte *)bitmapData1.Scan0; for (var j = 0; j < bitmapData1.Height; j++, imagePointer += additional) { for (var i = 0; i < bitmapData1.Width; i++, imagePointer += rgpPixelSize) { result[j, i] = new RgbPixel(imagePointer[0], imagePointer[1], imagePointer[2]); } } } bmp1.UnlockBits(bitmapData1); var convert = MatrixRgbToYCbCrConveter.Convert(result); var back = MatrixYCbCrToRgbConverter.Convert(convert); var bmp2 = new Bitmap(bmp1.Width, bmp1.Height, bmp1.PixelFormat); var bitmapData2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), ImageLockMode.ReadOnly, bmp2.PixelFormat); unsafe { var imagePointer = (byte *)bitmapData2.Scan0; for (var j = 0; j < bitmapData2.Height; j++, imagePointer += additional) { for (var i = 0; i < bitmapData2.Width; i++, imagePointer += rgpPixelSize) { imagePointer[0] = back[j, i].R; imagePointer[1] = back[j, i].G; imagePointer[2] = back[j, i].B; } } } bmp2.UnlockBits(bitmapData2); bmp2.Save(@"C:\Users\FessEmpty\Downloads\parallelprogramming-shpora2016-56f562c98bbf\parallelprogramming-shpora2016-56f562c98bbf\JPEG\sampleTest.bmp", ImageFormat.Bmp); }