/// <summary> /// Generate BitmapFileHeader from first 14 bytes /// </summary> /// <param name="headerBytes"></param> /// <returns>BitmapFileHeader or throws exception</returns> public static BitmapFileHeader GetHeaderFromBytes(byte[] headerBytes) { if (headerBytes == null) { throw new ArgumentNullException(nameof(headerBytes)); } if (headerBytes.Length != BitmapFileHeader.BitmapFileHeaderSizeInBytes) { throw new ArgumentOutOfRangeException($"{nameof( headerBytes )} should be {BitmapFileHeader.BitmapFileHeaderSizeInBytes} bytes in headerSize"); } if (!System.BitConverter.IsLittleEndian) { Array.Reverse(headerBytes, 2, 4); Array.Reverse(headerBytes, 10, 4); } var sizeBytes = BitConverter.ToUInt32(headerBytes, 2); var offset = BitConverter.ToUInt32(headerBytes, 10); var header = new BitmapFileHeader() { PixelDataOffset = offset, FileSize = sizeBytes }; return(header); }
public static Bitmap ReadFileAsBitmap(string fileName, bool flipRows = false) { if (string.IsNullOrWhiteSpace(fileName)) { throw new ArgumentNullException(nameof(fileName)); } if (!File.Exists(fileName)) { throw new Exception($"File {fileName} not found"); } var fileInfo = new FileInfo(fileName); if (fileInfo.Length <= BitmapFileHeader.BitmapFileHeaderSizeInBytes) { throw new Exception($"Invalid file format. Size is too small."); } using (var fileStream = File.OpenRead(fileName)) { using (var bReader = new SafeBinaryReader(fileStream)) { var headerBytes = bReader.ReadBytes(BitmapFileHeader.BitmapFileHeaderSizeInBytes); var fileHeader = BitmapFileHeader.GetHeaderFromBytes(headerBytes); if (fileInfo.Length != fileHeader.FileSize) { throw new Exception($"File size is different than in header."); } var dibHeaderSize = bReader.ReadInt32(); fileStream.Seek(-4, SeekOrigin.Current); var infoHeader = BitmapInfoHeader.GetHeaderFromBytes(bReader.ReadBytes(dibHeaderSize)); var width = infoHeader.Width; var height = infoHeader.Height; var bytesPerRow = Bitmap.RequiredBytesPerRow(infoHeader.Width, infoHeader.BitsPerPixel); var bytesPerPixel = (int)infoHeader.BitsPerPixel / 8; var paddingRequired = Bitmap.IsPaddingRequired(infoHeader.Width, infoHeader.BitsPerPixel, bytesPerRow); var pixelData = new byte[width * height * bytesPerPixel]; // seek to location where pixel data is fileStream.Seek(fileHeader.PixelDataOffset, SeekOrigin.Begin); if (paddingRequired) { var bytesToCopy = width * bytesPerPixel; for (var counter = 0; counter < height; counter++) { var rowBuffer = bReader.ReadBytes(bytesPerRow); Buffer.BlockCopy(src: rowBuffer, srcOffset: 0, dst: pixelData, dstOffset: counter * bytesToCopy, count: bytesToCopy); } } else { var rowBuffer = bReader.ReadBytes(pixelData.Length); rowBuffer.CopyTo(pixelData, 0); } var bitmap = new Bitmap( width, height, pixelData: pixelData, bitsPerPixel: infoHeader.BitsPerPixel ); return(bitmap); } } }