Browse Source

Remove EndianBinaryWriter from BmpEncoderCore

pull/530/head
Jason Nelson 8 years ago
parent
commit
602c359fc2
  1. 2
      src/ImageSharp/Formats/Bmp/BmpCompression.cs
  2. 66
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  3. 17
      src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
  4. 20
      src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs

2
src/ImageSharp/Formats/Bmp/BmpCompression.cs

@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Defines how the compression type of the image data /// Defines how the compression type of the image data
/// in the bitmap file. /// in the bitmap file.
/// </summary> /// </summary>
internal enum BmpCompression internal enum BmpCompression : int
{ {
/// <summary> /// <summary>
/// Each image row has a multiple of four elements. If the /// Each image row has a multiple of four elements. If the

66
src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

@ -3,7 +3,6 @@
using System; using System;
using System.IO; using System.IO;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -14,11 +13,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// </summary> /// </summary>
internal sealed class BmpEncoderCore internal sealed class BmpEncoderCore
{ {
/// <summary>
/// A general use buffer for reading and writing data.
/// </summary>
private byte[] buffer = new byte[16];
/// <summary> /// <summary>
/// The amount to pad each row by. /// The amount to pad each row by.
/// </summary> /// </summary>
@ -59,9 +53,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32); int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32);
this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel); this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel);
// Do not use IDisposable pattern here as we want to preserve the stream.
var writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);
var infoHeader = new BmpInfoHeader var infoHeader = new BmpInfoHeader
{ {
HeaderSize = BmpInfoHeader.BitmapInfoHeaderSize, HeaderSize = BmpInfoHeader.BitmapInfoHeaderSize,
@ -80,49 +71,30 @@ namespace SixLabors.ImageSharp.Formats.Bmp
reserved: 0, reserved: 0,
fileSize: 54 + infoHeader.ImageSize); fileSize: 54 + infoHeader.ImageSize);
fileHeader.WriteTo(this.buffer); byte[] buffer = new byte[40]; // TODO: stackalloc
stream.Write(this.buffer, 0, BmpFileHeader.Size); fileHeader.WriteTo(buffer);
this.WriteInfo(writer, infoHeader); stream.Write(buffer, 0, BmpFileHeader.Size);
this.WriteImage(writer, image.Frames.RootFrame);
writer.Flush(); infoHeader.WriteTo(buffer);
}
/// <summary> stream.Write(buffer, 0, 40);
/// Writes the bitmap information to the binary stream.
/// </summary> this.WriteImage(stream, image.Frames.RootFrame);
/// <param name="writer">
/// The <see cref="EndianBinaryWriter"/> containing the stream to write to. stream.Flush();
/// </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> /// <summary>
/// Writes the pixel data to the binary stream. /// Writes the pixel data to the binary stream.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param> /// <param name="stream">The <see cref="Stream"/> to write to.</param>
/// <param name="image"> /// <param name="image">
/// The <see cref="ImageFrame{TPixel}"/> containing pixel data. /// The <see cref="ImageFrame{TPixel}"/> containing pixel data.
/// </param> /// </param>
private void WriteImage<TPixel>(EndianBinaryWriter writer, ImageFrame<TPixel> image) private void WriteImage<TPixel>(Stream stream, ImageFrame<TPixel> image)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
using (PixelAccessor<TPixel> pixels = image.Lock()) using (PixelAccessor<TPixel> pixels = image.Lock())
@ -130,11 +102,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
switch (this.bitsPerPixel) switch (this.bitsPerPixel)
{ {
case BmpBitsPerPixel.Pixel32: case BmpBitsPerPixel.Pixel32:
this.Write32Bit(writer, pixels); this.Write32Bit(stream, pixels);
break; break;
case BmpBitsPerPixel.Pixel24: case BmpBitsPerPixel.Pixel24:
this.Write24Bit(writer, pixels); this.Write24Bit(stream, pixels);
break; break;
} }
} }
@ -149,9 +121,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Writes the 32bit color palette to the stream. /// Writes the 32bit color palette to the stream.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param> /// <param name="stream">The <see cref="Stream"/> to write to.</param>
/// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> containing pixel data.</param> /// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> containing pixel data.</param>
private void Write32Bit<TPixel>(EndianBinaryWriter writer, PixelAccessor<TPixel> pixels) private void Write32Bit<TPixel>(Stream stream, PixelAccessor<TPixel> pixels)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 4)) using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 4))
@ -160,7 +132,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{ {
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.ToBgra32Bytes(pixelSpan, row.Span, pixelSpan.Length); PixelOperations<TPixel>.Instance.ToBgra32Bytes(pixelSpan, row.Span, pixelSpan.Length);
writer.Write(row.Array, 0, row.Length()); stream.Write(row.Array, 0, row.Length());
} }
} }
} }
@ -169,9 +141,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Writes the 24bit color palette to the stream. /// Writes the 24bit color palette to the stream.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param> /// <param name="stream">The <see cref="Stream"/> to write to.</param>
/// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> containing pixel data.</param> /// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> containing pixel data.</param>
private void Write24Bit<TPixel>(EndianBinaryWriter writer, PixelAccessor<TPixel> pixels) private void Write24Bit<TPixel>(Stream stream, PixelAccessor<TPixel> pixels)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 3)) using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 3))
@ -180,7 +152,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{ {
Span<TPixel> pixelSpan = pixels.GetRowSpan(y); Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.ToBgr24Bytes(pixelSpan, row.Span, pixelSpan.Length); PixelOperations<TPixel>.Instance.ToBgr24Bytes(pixelSpan, row.Span, pixelSpan.Length);
writer.Write(row.Array, 0, row.Length()); stream.Write(row.Array, 0, row.Length());
} }
} }
} }

17
src/ImageSharp/Formats/Bmp/BmpFileHeader.cs

@ -59,21 +59,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp
public unsafe void WriteTo(Span<byte> buffer) public unsafe void WriteTo(Span<byte> buffer)
{ {
if (BitConverter.IsLittleEndian) fixed (BmpFileHeader* pointer = &this)
{ {
fixed (BmpFileHeader* pointer = &this) MemoryMarshal.AsBytes(new ReadOnlySpan<BmpFileHeader>(pointer, 1)).CopyTo(buffer);
{
MemoryMarshal.AsBytes(new ReadOnlySpan<BmpFileHeader>(pointer, 1)).CopyTo(buffer);
}
}
else
{
// Big Endian Platform
BinaryPrimitives.WriteInt16LittleEndian(buffer.Slice(0, 2), this.Type);
BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(2, 4), this.FileSize);
BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(6, 4), this.Reserved);
BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(10, 4), this.Offset);
} }
// TODO: Big Endian Platforms
} }
} }
} }

20
src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs

@ -1,5 +1,8 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Bmp namespace SixLabors.ImageSharp.Formats.Bmp
{ {
/// <summary> /// <summary>
@ -8,8 +11,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// the screen. /// the screen.
/// <see href="https://en.wikipedia.org/wiki/BMP_file_format"/> /// <see href="https://en.wikipedia.org/wiki/BMP_file_format"/>
/// </summary> /// </summary>
internal sealed class BmpInfoHeader [StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct BmpInfoHeader
{ {
// TODO: Make readonly
/// <summary> /// <summary>
/// Defines the size of the BITMAPINFOHEADER data structure in the bitmap file. /// Defines the size of the BITMAPINFOHEADER data structure in the bitmap file.
/// </summary> /// </summary>
@ -91,5 +97,15 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// or 0 when every color is important{ get; set; } generally ignored. /// or 0 when every color is important{ get; set; } generally ignored.
/// </summary> /// </summary>
public int ClrImportant { get; set; } public int ClrImportant { get; set; }
public unsafe void WriteTo(Span<byte> buffer)
{
fixed (BmpInfoHeader* pointer = &this)
{
MemoryMarshal.AsBytes(new ReadOnlySpan<BmpInfoHeader>(pointer, 1)).CopyTo(buffer);
}
// TODO: Big Endian Platforms
}
} }
} }
Loading…
Cancel
Save