/// <summary> /// Reads the <see cref="BmpInfoHeader"/> from the stream. /// </summary> private void ReadInfoHeader() { byte[] data = new byte[BmpInfoHeader.MaxHeaderSize]; // read header size this.currentStream.Read(data, 0, BmpInfoHeader.HeaderSizeSize); int headerSize = BitConverter.ToInt32(data, 0); if (headerSize < BmpInfoHeader.HeaderSizeSize || headerSize > BmpInfoHeader.MaxHeaderSize) { throw new NotSupportedException($"This kind of bitmap files (header size $headerSize) is not supported."); } // read the rest of the header this.currentStream.Read(data, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize); switch (headerSize) { case BmpInfoHeader.BitmapCoreHeaderSize: this.infoHeader = this.ParseBitmapCoreHeader(data); break; case BmpInfoHeader.BitmapInfoHeaderSize: this.infoHeader = this.ParseBitmapInfoHeader(data); break; default: throw new NotSupportedException($"This kind of bitmap files (header size $headerSize) is not supported."); } }
/// <summary> /// Writes the bitmap information to the binary stream. /// </summary> /// <param name="writer"> /// The <see cref="EndianBinaryWriter"/> containing the stream to write to. /// </param> /// <param name="infoHeader"> /// The <see cref="BmpFileHeader"/> containing the detailed information about the image. /// </param> private void WriteInfo(EndianBinaryWriter writer, BmpInfoHeader infoHeader) { writer.Write(infoHeader.HeaderSize); writer.Write(infoHeader.Width); writer.Write(infoHeader.Height); writer.Write(infoHeader.Planes); writer.Write(infoHeader.BitsPerPixel); writer.Write((int)infoHeader.Compression); writer.Write(infoHeader.ImageSize); writer.Write(infoHeader.XPelsPerMeter); writer.Write(infoHeader.YPelsPerMeter); writer.Write(infoHeader.ClrUsed); writer.Write(infoHeader.ClrImportant); }
/// <summary> /// Reads the <see cref="BmpInfoHeader"/> from the stream. /// </summary> private void ReadInfoHeader() { byte[] data = new byte[BmpInfoHeader.MaxHeaderSize]; // read header size this.currentStream.Read(data, 0, BmpInfoHeader.HeaderSizeSize); int headerSize = BitConverter.ToInt32(data, 0); if (headerSize < BmpInfoHeader.BitmapCoreHeaderSize) { throw new NotSupportedException($"This kind of bitmap files (header size $headerSize) is not supported."); } int skipAmmount = 0; if (headerSize > BmpInfoHeader.MaxHeaderSize) { skipAmmount = headerSize - BmpInfoHeader.MaxHeaderSize; headerSize = BmpInfoHeader.MaxHeaderSize; } // read the rest of the header this.currentStream.Read(data, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize); switch (headerSize) { case BmpInfoHeader.BitmapCoreHeaderSize: this.infoHeader = this.ParseBitmapCoreHeader(data); break; case BmpInfoHeader.BitmapInfoHeaderSize: this.infoHeader = this.ParseBitmapInfoHeader(data); break; default: if (headerSize > BmpInfoHeader.BitmapInfoHeaderSize) { this.infoHeader = this.ParseBitmapInfoHeader(data); break; } else { throw new NotSupportedException($"This kind of bitmap files (header size $headerSize) is not supported."); } } // skip the remaining header because we can't read those parts this.currentStream.Skip(skipAmmount); }
/// <summary> /// Encodes the image to the specified stream from the <see cref="ImageBase{TColor, TPacked}"/>. /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TPacked">The packed format. <example>long, float.</example></typeparam> /// <param name="image">The <see cref="ImageBase{TColor, TPacked}"/> to encode from.</param> /// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param> /// <param name="bitsPerPixel">The <see cref="BmpBitsPerPixel"/></param> public void Encode <TColor, TPacked>(ImageBase <TColor, TPacked> image, Stream stream, BmpBitsPerPixel bitsPerPixel) where TColor : struct, IPackedPixel <TPacked> where TPacked : struct { Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); this.bmpBitsPerPixel = bitsPerPixel; // Cast to int will get the bytes per pixel short bpp = (short)(8 * (int)bitsPerPixel); int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32); this.padding = bytesPerLine - (image.Width * (int)bitsPerPixel); // Do not use IDisposable pattern here as we want to preserve the stream. EndianBinaryWriter writer = new EndianBinaryWriter(EndianBitConverter.Little, stream); BmpInfoHeader infoHeader = new BmpInfoHeader { HeaderSize = BmpInfoHeader.Size, Height = image.Height, Width = image.Width, BitsPerPixel = bpp, Planes = 1, ImageSize = image.Height * bytesPerLine, ClrUsed = 0, ClrImportant = 0 }; BmpFileHeader fileHeader = new BmpFileHeader { Type = 19778, // BM Offset = 54, FileSize = 54 + infoHeader.ImageSize }; WriteHeader(writer, fileHeader); this.WriteInfo(writer, infoHeader); this.WriteImage(writer, image); writer.Flush(); }
/// <summary> /// Reads the <see cref="BmpInfoHeader"/> from the stream. /// </summary> private void ReadInfoHeader() { byte[] data = new byte[BmpInfoHeader.Size]; this.currentStream.Read(data, 0, BmpInfoHeader.Size); this.infoHeader = new BmpInfoHeader { HeaderSize = BitConverter.ToInt32(data, 0), Width = BitConverter.ToInt32(data, 4), Height = BitConverter.ToInt32(data, 8), Planes = BitConverter.ToInt16(data, 12), BitsPerPixel = BitConverter.ToInt16(data, 14), ImageSize = BitConverter.ToInt32(data, 20), XPelsPerMeter = BitConverter.ToInt32(data, 24), YPelsPerMeter = BitConverter.ToInt32(data, 28), ClrUsed = BitConverter.ToInt32(data, 32), ClrImportant = BitConverter.ToInt32(data, 36), Compression = (BmpCompression)BitConverter.ToInt32(data, 16) }; }