/// <summary> /// Encodes pixel information into a Portable Networks Graphics (PNG) image file. /// </summary> /// <param name="bitmap">A RGB bitmap.</param> /// <returns>A png image file</returns> public IEnumerable <byte> Encode(IRgbBitmap bitmap) { // https://en.wikipedia.org/wiki/Portable_Network_Graphics // https://tools.ietf.org/html/rfc2083 return(GetPngFileHeader() .Concat(GetIHDRChunk(bitmap)) .Concat(GetIDATChunk(bitmap)) .Concat(GetIENDChunk())); }
private IEnumerable <byte> GetIDATChunk(IRgbBitmap bitmap) { var imageData = bitmap.Pixels .Chunk(bitmap.Width) .Select(EncodeScanLine) .Select(FilterImageData) .SelectMany(x => x) .ToList(); var compressedImageData = CompressImageData(imageData).ToList(); return(CreateChunk(ChunkType.IDAT, compressedImageData)); }
private IEnumerable <byte> GetIHDRChunk(IRgbBitmap bitmap) { var chunkData = GetUIntMsb((uint)bitmap.Width) .Concat(GetUIntMsb((uint)bitmap.Height)) .Concat(new[] { (byte)BitDepth.BitsPerSampleIs8, (byte)ColorType.ColorUsed, (byte)CompressionMethod.DeflateInflateCompressionWith32KSlidingWindow, (byte)FilterMethod.AdaptiveFilteringWithFiveBasicFilterTypes, (byte)InterlaceMethod.NoInterlace }) .ToList(); return(CreateChunk(ChunkType.IHDR, chunkData)); }
/// <summary> /// Encodes pixel information into a bitmap image file. /// </summary> /// <param name="bitmap">A RGB bitmap.</param> /// <returns>A bitmap image file</returns> public IEnumerable <byte> Encode(IRgbBitmap bitmap) { // https://en.wikipedia.org/wiki/BMP_file_format const int bitsPerPixel = 24; var pixelArray = GetPixelArray(bitmap, bitsPerPixel); var rawBitmapDataSize = (uint)pixelArray.Length; var dibHeader = GetDibHeader(rawBitmapDataSize, (uint)bitmap.Width, (uint)bitmap.Height, bitsPerPixel).ToList(); const int bitmapHeaderSize = 14; var bmpFileSize = (uint)(rawBitmapDataSize + dibHeader.Count + bitmapHeaderSize); var bmpHeader = GetBmpHeader(bmpFileSize); return(bmpHeader .Concat(dibHeader) .Concat(pixelArray)); }
private static byte[] GetPixelArray(IRgbBitmap bitmap, int bitsPerPixel) { var sourceRowSize = bitmap.Width * 3; var sourcePixelData = bitmap.Pixels.ToRgbEncodedBytes().ToArray(); var destinationRowSize = (bitsPerPixel * bitmap.Width + 31) / 32 * 4; var pixelArraySize = destinationRowSize * bitmap.Height; var pixelArray = new byte[pixelArraySize]; for (var sourceRowIndex = 0; sourceRowIndex < bitmap.Height; sourceRowIndex++) { var sourceOffset = sourceRowIndex * bitmap.Width * 3; var destinationOffset = (bitmap.Height - sourceRowIndex - 1) * destinationRowSize; Buffer.BlockCopy(sourcePixelData, sourceOffset, pixelArray, destinationOffset, sourceRowSize); } return(pixelArray); }