Browse Source

Create specialized BigEndianBinaryWriter & LittleEndianBinaryWriter classes

af/merge-core
Jason Nelson 8 years ago
parent
commit
5dacf84c5b
  1. 26
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  2. 18
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  3. 87
      src/ImageSharp/IO/BigEndianBinaryWriter.cs
  4. 130
      src/ImageSharp/IO/EndianBinaryWriter.cs
  5. 87
      src/ImageSharp/IO/LittleEndianBinaryWriter.cs
  6. 6
      tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs

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

@ -55,9 +55,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
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. // Do not use IDisposable pattern here as we want to preserve the stream.
EndianBinaryWriter writer = new EndianBinaryWriter(Endianness.LittleEndian, stream); var writer = new LittleEndianBinaryWriter(stream);
BmpInfoHeader infoHeader = new BmpInfoHeader var infoHeader = new BmpInfoHeader
{ {
HeaderSize = BmpInfoHeader.BitmapInfoHeaderSize, HeaderSize = BmpInfoHeader.BitmapInfoHeaderSize,
Height = image.Height, Height = image.Height,
@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
ClrImportant = 0 ClrImportant = 0
}; };
BmpFileHeader fileHeader = new BmpFileHeader var fileHeader = new BmpFileHeader
{ {
Type = 19778, // BM Type = 19778, // BM
Offset = 54, Offset = 54,
@ -87,12 +87,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Writes the bitmap header data to the binary stream. /// Writes the bitmap header data to the binary stream.
/// </summary> /// </summary>
/// <param name="writer"> /// <param name="writer">
/// The <see cref="EndianBinaryWriter"/> containing the stream to write to. /// The <see cref="BigEndianBinaryWriter"/> containing the stream to write to.
/// </param> /// </param>
/// <param name="fileHeader"> /// <param name="fileHeader">
/// The <see cref="BmpFileHeader"/> containing the header data. /// The <see cref="BmpFileHeader"/> containing the header data.
/// </param> /// </param>
private static void WriteHeader(EndianBinaryWriter writer, BmpFileHeader fileHeader) private static void WriteHeader(LittleEndianBinaryWriter writer, BmpFileHeader fileHeader)
{ {
writer.Write(fileHeader.Type); writer.Write(fileHeader.Type);
writer.Write(fileHeader.FileSize); writer.Write(fileHeader.FileSize);
@ -104,12 +104,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Writes the bitmap information to the binary stream. /// Writes the bitmap information to the binary stream.
/// </summary> /// </summary>
/// <param name="writer"> /// <param name="writer">
/// The <see cref="EndianBinaryWriter"/> containing the stream to write to. /// The <see cref="BigEndianBinaryWriter"/> containing the stream to write to.
/// </param> /// </param>
/// <param name="infoHeader"> /// <param name="infoHeader">
/// The <see cref="BmpFileHeader"/> containing the detailed information about the image. /// The <see cref="BmpFileHeader"/> containing the detailed information about the image.
/// </param> /// </param>
private void WriteInfo(EndianBinaryWriter writer, BmpInfoHeader infoHeader) private void WriteInfo(LittleEndianBinaryWriter writer, BmpInfoHeader infoHeader)
{ {
writer.Write(infoHeader.HeaderSize); writer.Write(infoHeader.HeaderSize);
writer.Write(infoHeader.Width); writer.Write(infoHeader.Width);
@ -128,11 +128,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// 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="writer">The <see cref="BigEndianBinaryWriter"/> containing the 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>(LittleEndianBinaryWriter writer, 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())
@ -159,9 +159,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="writer">The <see cref="BigEndianBinaryWriter"/> containing the 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>(LittleEndianBinaryWriter writer, 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))
@ -179,9 +179,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="writer">The <see cref="BigEndianBinaryWriter"/> containing the 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>(LittleEndianBinaryWriter writer, 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))

18
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
// Do not use IDisposable pattern here as we want to preserve the stream. // Do not use IDisposable pattern here as we want to preserve the stream.
var writer = new EndianBinaryWriter(Endianness.LittleEndian, stream); var writer = new LittleEndianBinaryWriter(stream);
this.hasFrames = image.Frames.Count > 1; this.hasFrames = image.Frames.Count > 1;
@ -155,7 +155,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// Writes the file header signature and version to the stream. /// Writes the file header signature and version to the stream.
/// </summary> /// </summary>
/// <param name="writer">The writer to write to the stream with.</param> /// <param name="writer">The writer to write to the stream with.</param>
private void WriteHeader(EndianBinaryWriter writer) private void WriteHeader(LittleEndianBinaryWriter writer)
{ {
writer.Write(GifConstants.MagicNumber, 0, GifConstants.MagicNumber.Length); writer.Write(GifConstants.MagicNumber, 0, GifConstants.MagicNumber.Length);
} }
@ -167,7 +167,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <param name="image">The image to encode.</param> /// <param name="image">The image to encode.</param>
/// <param name="writer">The writer to write to the stream with.</param> /// <param name="writer">The writer to write to the stream with.</param>
/// <param name="transparencyIndex">The transparency index to set the default background index to.</param> /// <param name="transparencyIndex">The transparency index to set the default background index to.</param>
private void WriteLogicalScreenDescriptor<TPixel>(Image<TPixel> image, EndianBinaryWriter writer, int transparencyIndex) private void WriteLogicalScreenDescriptor<TPixel>(Image<TPixel> image, LittleEndianBinaryWriter writer, int transparencyIndex)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
var descriptor = new GifLogicalScreenDescriptor var descriptor = new GifLogicalScreenDescriptor
@ -202,7 +202,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <param name="writer">The writer to write to the stream with.</param> /// <param name="writer">The writer to write to the stream with.</param>
/// <param name="repeatCount">The animated image repeat count.</param> /// <param name="repeatCount">The animated image repeat count.</param>
/// <param name="frames">The number of image frames.</param> /// <param name="frames">The number of image frames.</param>
private void WriteApplicationExtension(EndianBinaryWriter writer, ushort repeatCount, int frames) private void WriteApplicationExtension(LittleEndianBinaryWriter writer, ushort repeatCount, int frames)
{ {
// Application Extension Header // Application Extension Header
if (repeatCount != 1 && frames > 0) if (repeatCount != 1 && frames > 0)
@ -231,7 +231,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageFrame{TPixel}"/> to be encoded.</param> /// <param name="image">The <see cref="ImageFrame{TPixel}"/> to be encoded.</param>
/// <param name="writer">The stream to write to.</param> /// <param name="writer">The stream to write to.</param>
private void WriteComments<TPixel>(Image<TPixel> image, EndianBinaryWriter writer) private void WriteComments<TPixel>(Image<TPixel> image, LittleEndianBinaryWriter writer)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
if (this.ignoreMetadata) if (this.ignoreMetadata)
@ -264,7 +264,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <param name="metaData">The metadata of the image or frame.</param> /// <param name="metaData">The metadata of the image or frame.</param>
/// <param name="writer">The stream to write to.</param> /// <param name="writer">The stream to write to.</param>
/// <param name="transparencyIndex">The index of the color in the color palette to make transparent.</param> /// <param name="transparencyIndex">The index of the color in the color palette to make transparent.</param>
private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, EndianBinaryWriter writer, int transparencyIndex) private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, LittleEndianBinaryWriter writer, int transparencyIndex)
{ {
var extension = new GifGraphicsControlExtension var extension = new GifGraphicsControlExtension
{ {
@ -299,7 +299,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageFrame{TPixel}"/> to be encoded.</param> /// <param name="image">The <see cref="ImageFrame{TPixel}"/> to be encoded.</param>
/// <param name="writer">The stream to write to.</param> /// <param name="writer">The stream to write to.</param>
private void WriteImageDescriptor<TPixel>(ImageFrame<TPixel> image, EndianBinaryWriter writer) private void WriteImageDescriptor<TPixel>(ImageFrame<TPixel> image, LittleEndianBinaryWriter writer)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
writer.Write(GifConstants.ImageDescriptorLabel); // 2c writer.Write(GifConstants.ImageDescriptorLabel); // 2c
@ -325,7 +325,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageFrame{TPixel}"/> to encode.</param> /// <param name="image">The <see cref="ImageFrame{TPixel}"/> to encode.</param>
/// <param name="writer">The writer to write to the stream with.</param> /// <param name="writer">The writer to write to the stream with.</param>
private void WriteColorTable<TPixel>(QuantizedFrame<TPixel> image, EndianBinaryWriter writer) private void WriteColorTable<TPixel>(QuantizedFrame<TPixel> image, LittleEndianBinaryWriter writer)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
// Grab the palette and write it to the stream. // Grab the palette and write it to the stream.
@ -357,7 +357,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="QuantizedFrame{TPixel}"/> containing indexed pixels.</param> /// <param name="image">The <see cref="QuantizedFrame{TPixel}"/> containing indexed pixels.</param>
/// <param name="writer">The stream to write to.</param> /// <param name="writer">The stream to write to.</param>
private void WriteImageData<TPixel>(QuantizedFrame<TPixel> image, EndianBinaryWriter writer) private void WriteImageData<TPixel>(QuantizedFrame<TPixel> image, LittleEndianBinaryWriter writer)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
using (var encoder = new LzwEncoder(this.memoryManager, image.Pixels, (byte)this.bitDepth)) using (var encoder = new LzwEncoder(this.memoryManager, image.Pixels, (byte)this.bitDepth))

87
src/ImageSharp/IO/BigEndianBinaryWriter.cs

@ -0,0 +1,87 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers.Binary;
using System.IO;
namespace SixLabors.ImageSharp.IO
{
/// <summary>
/// A BigEndian variant of <see cref="BinaryWriter"/>
/// </summary>
internal sealed class BigEndianBinaryWriter : EndianBinaryWriter
{
/// <summary>
/// Initializes a new instance of the <see cref="BigEndianBinaryWriter"/> class
/// </summary>
/// <param name="stream">Stream to write data to</param>
public BigEndianBinaryWriter(Stream stream)
: base(stream)
{
}
/// <inheritdoc />
public override Endianness Endianness => Endianness.BigEndian;
/// <inheritdoc />
public override void Write(short value)
{
BinaryPrimitives.WriteInt16BigEndian(this.buffer, value);
this.WriteInternal(this.buffer, 2);
}
/// <inheritdoc />
public override void Write(int value)
{
BinaryPrimitives.WriteInt32BigEndian(this.buffer, value);
this.WriteInternal(this.buffer, 4);
}
/// <inheritdoc />
public override void Write(long value)
{
BinaryPrimitives.WriteInt64BigEndian(this.buffer, value);
this.WriteInternal(this.buffer, 8);
}
/// <inheritdoc />
public override void Write(ushort value)
{
BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value);
this.WriteInternal(this.buffer, 2);
}
/// <inheritdoc />
public override void Write(uint value)
{
BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value);
this.WriteInternal(this.buffer, 4);
}
/// <inheritdoc />
public override void Write(ulong value)
{
BinaryPrimitives.WriteUInt64BigEndian(this.buffer, value);
this.WriteInternal(this.buffer, 8);
}
/// <inheritdoc />
public override unsafe void Write(float value)
{
this.Write(*((int*)&value));
}
/// <inheritdoc />
public override unsafe void Write(double value)
{
this.Write(*((long*)&value));
}
}
}

130
src/ImageSharp/IO/EndianBinaryWriter.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Buffers.Binary;
using System.IO; using System.IO;
namespace SixLabors.ImageSharp.IO namespace SixLabors.ImageSharp.IO
@ -10,17 +9,12 @@ namespace SixLabors.ImageSharp.IO
/// <summary> /// <summary>
/// Equivalent of <see cref="BinaryWriter"/>, but with either endianness /// Equivalent of <see cref="BinaryWriter"/>, but with either endianness
/// </summary> /// </summary>
internal class EndianBinaryWriter : IDisposable internal abstract class EndianBinaryWriter : IDisposable
{ {
/// <summary> /// <summary>
/// Buffer used for temporary storage during conversion from primitives /// Buffer used for temporary storage during conversion from primitives
/// </summary> /// </summary>
private readonly byte[] buffer = new byte[16]; protected readonly byte[] buffer = new byte[16];
/// <summary>
/// The endianness used to write the data
/// </summary>
private readonly Endianness endianness;
/// <summary> /// <summary>
/// Whether or not this writer has been disposed yet. /// Whether or not this writer has been disposed yet.
@ -29,17 +23,14 @@ namespace SixLabors.ImageSharp.IO
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="EndianBinaryWriter"/> class /// Initializes a new instance of the <see cref="EndianBinaryWriter"/> class
/// with the given bit converter, writing to the given stream, using the given encoding.
/// </summary> /// </summary>
/// <param name="endianness">Endianness to use when writing data</param>
/// <param name="stream">Stream to write data to</param> /// <param name="stream">Stream to write data to</param>
public EndianBinaryWriter(Endianness endianness, Stream stream) public EndianBinaryWriter(Stream stream)
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
Guard.IsTrue(stream.CanWrite, nameof(stream), "Stream isn't writable"); Guard.IsTrue(stream.CanWrite, nameof(stream), "Stream isn't writable");
this.BaseStream = stream; this.BaseStream = stream;
this.endianness = endianness;
} }
/// <summary> /// <summary>
@ -47,6 +38,11 @@ namespace SixLabors.ImageSharp.IO
/// </summary> /// </summary>
public Stream BaseStream { get; } public Stream BaseStream { get; }
/// <summary>
/// Gets the endianness of the BinaryWriter
/// </summary>
public abstract Endianness Endianness { get; }
/// <summary> /// <summary>
/// Closes the writer, including the underlying stream. /// Closes the writer, including the underlying stream.
/// </summary> /// </summary>
@ -91,134 +87,56 @@ namespace SixLabors.ImageSharp.IO
/// for this writer. 2 bytes are written. /// for this writer. 2 bytes are written.
/// </summary> /// </summary>
/// <param name="value">The value to write</param> /// <param name="value">The value to write</param>
public void Write(short value) public abstract void Write(short value);
{
if (this.endianness == Endianness.BigEndian)
{
BinaryPrimitives.WriteInt16BigEndian(this.buffer, value);
}
else
{
BinaryPrimitives.WriteInt16LittleEndian(this.buffer, value);
}
this.WriteInternal(this.buffer, 2);
}
/// <summary> /// <summary>
/// Writes a 32-bit signed integer to the stream, using the bit converter /// Writes a 32-bit signed integer to the stream, using the bit converter
/// for this writer. 4 bytes are written. /// for this writer. 4 bytes are written.
/// </summary> /// </summary>
/// <param name="value">The value to write</param> /// <param name="value">The value to write</param>
public void Write(int value) public abstract void Write(int value);
{
if (this.endianness == Endianness.BigEndian)
{
BinaryPrimitives.WriteInt32BigEndian(this.buffer, value);
}
else
{
BinaryPrimitives.WriteInt32LittleEndian(this.buffer, value);
}
this.WriteInternal(this.buffer, 4);
}
/// <summary> /// <summary>
/// Writes a 64-bit signed integer to the stream, using the bit converter /// Writes a 64-bit signed integer to the stream, using the bit converter
/// for this writer. 8 bytes are written. /// for this writer. 8 bytes are written.
/// </summary> /// </summary>
/// <param name="value">The value to write</param> /// <param name="value">The value to write</param>
public void Write(long value) public abstract void Write(long value);
{
if (this.endianness == Endianness.BigEndian)
{
BinaryPrimitives.WriteInt64BigEndian(this.buffer, value);
}
else
{
BinaryPrimitives.WriteInt64LittleEndian(this.buffer, value);
}
this.WriteInternal(this.buffer, 8);
}
/// <summary> /// <summary>
/// Writes a 16-bit unsigned integer to the stream, using the bit converter /// Writes a 16-bit unsigned integer to the stream, using the bit converter
/// for this writer. 2 bytes are written. /// for this writer. 2 bytes are written.
/// </summary> /// </summary>
/// <param name="value">The value to write</param> /// <param name="value">The value to write</param>
public void Write(ushort value) public abstract void Write(ushort value);
{
if (this.endianness == Endianness.BigEndian)
{
BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value);
}
else
{
BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value);
}
this.WriteInternal(this.buffer, 2);
}
/// <summary> /// <summary>
/// Writes a 32-bit unsigned integer to the stream, using the bit converter /// Writes a 32-bit unsigned integer to the stream, using the bit converter
/// for this writer. 4 bytes are written. /// for this writer. 4 bytes are written.
/// </summary> /// </summary>
/// <param name="value">The value to write</param> /// <param name="value">The value to write</param>
public void Write(uint value) public abstract void Write(uint value);
{
if (this.endianness == Endianness.BigEndian)
{
BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value);
}
else
{
BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value);
}
this.WriteInternal(this.buffer, 4);
}
/// <summary> /// <summary>
/// Writes a 64-bit unsigned integer to the stream, using the bit converter /// Writes a 64-bit unsigned integer to the stream, using the bit converter
/// for this writer. 8 bytes are written. /// for this writer. 8 bytes are written.
/// </summary> /// </summary>
/// <param name="value">The value to write</param> /// <param name="value">The value to write</param>
public void Write(ulong value) public abstract void Write(ulong value);
{
if (this.endianness == Endianness.BigEndian)
{
BinaryPrimitives.WriteUInt64BigEndian(this.buffer, value);
}
else
{
BinaryPrimitives.WriteUInt64LittleEndian(this.buffer, value);
}
this.WriteInternal(this.buffer, 8);
}
/// <summary> /// <summary>
/// Writes a single-precision floating-point value to the stream, using the bit converter /// Writes a single-precision floating-point value to the stream, using the bit converter
/// for this writer. 4 bytes are written. /// for this writer. 4 bytes are written.
/// </summary> /// </summary>
/// <param name="value">The value to write</param> /// <param name="value">The value to write</param>
public unsafe void Write(float value) public abstract void Write(float value);
{
this.Write(*((int*)&value));
}
/// <summary> /// <summary>
/// Writes a double-precision floating-point value to the stream, using the bit converter /// Writes a double-precision floating-point value to the stream, using the bit converter
/// for this writer. 8 bytes are written. /// for this writer. 8 bytes are written.
/// </summary> /// </summary>
/// <param name="value">The value to write</param> /// <param name="value">The value to write</param>
public unsafe void Write(double value) public abstract void Write(double value);
{
this.Write(*((long*)&value));
}
/// <summary> /// <summary>
/// Writes a signed byte to the stream. /// Writes a signed byte to the stream.
@ -284,7 +202,7 @@ namespace SixLabors.ImageSharp.IO
{ {
if (this.disposed) if (this.disposed)
{ {
throw new ObjectDisposedException(nameof(EndianBinaryWriter)); throw new ObjectDisposedException(nameof(BigEndianBinaryWriter));
} }
} }
@ -294,10 +212,22 @@ namespace SixLabors.ImageSharp.IO
/// </summary> /// </summary>
/// <param name="bytes">The array of bytes to write from</param> /// <param name="bytes">The array of bytes to write from</param>
/// <param name="length">The number of bytes to write</param> /// <param name="length">The number of bytes to write</param>
private void WriteInternal(byte[] bytes, int length) protected void WriteInternal(byte[] bytes, int length)
{ {
this.CheckDisposed(); this.CheckDisposed();
this.BaseStream.Write(bytes, 0, length); this.BaseStream.Write(bytes, 0, length);
} }
public static EndianBinaryWriter Create(Endianness endianness, Stream stream)
{
if (endianness == Endianness.BigEndian)
{
return new BigEndianBinaryWriter(stream);
}
else
{
return new LittleEndianBinaryWriter(stream);
}
}
} }
} }

87
src/ImageSharp/IO/LittleEndianBinaryWriter.cs

@ -0,0 +1,87 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers.Binary;
using System.IO;
namespace SixLabors.ImageSharp.IO
{
/// <summary>
/// A Little Endian variant of <see cref="BinaryWriter"/>
/// </summary>
internal sealed class LittleEndianBinaryWriter : EndianBinaryWriter
{
/// <summary>
/// Initializes a new instance of the <see cref="LittleEndianBinaryWriter"/> class
/// </summary>
/// <param name="stream">Stream to write data to</param>
public LittleEndianBinaryWriter(Stream stream)
: base(stream)
{
}
/// <inhertdoc />
public override Endianness Endianness => Endianness.LittleEndian;
/// <inheritdoc />
public override void Write(short value)
{
BinaryPrimitives.WriteInt16LittleEndian(this.buffer, value);
this.WriteInternal(this.buffer, 2);
}
/// <inheritdoc />
public override void Write(int value)
{
BinaryPrimitives.WriteInt32LittleEndian(this.buffer, value);
this.WriteInternal(this.buffer, 4);
}
/// <inheritdoc />
public override void Write(long value)
{
BinaryPrimitives.WriteInt64LittleEndian(this.buffer, value);
this.WriteInternal(this.buffer, 8);
}
/// <inheritdoc />
public override void Write(ushort value)
{
BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value);
this.WriteInternal(this.buffer, 2);
}
/// <inheritdoc />
public override void Write(uint value)
{
BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value);
this.WriteInternal(this.buffer, 4);
}
/// <inheritdoc />
public override void Write(ulong value)
{
BinaryPrimitives.WriteUInt64LittleEndian(this.buffer, value);
this.WriteInternal(this.buffer, 8);
}
/// <inheritdoc />
public override unsafe void Write(float value)
{
this.Write(*((int*)&value));
}
/// <inheritdoc />
public override unsafe void Write(double value)
{
this.Write(*((long*)&value));
}
}
}

6
tests/ImageSharp.Tests/IO/EndianBinaryReaderWriterTests.cs

@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.IO
{ {
var stream = new MemoryStream(); var stream = new MemoryStream();
using (var writer = new EndianBinaryWriter(endianness, stream)) using (var writer = EndianBinaryWriter.Create(endianness, stream))
{ {
writer.Write((float)Math.PI); writer.Write((float)Math.PI);
@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.IO
{ {
var stream = new MemoryStream(); var stream = new MemoryStream();
using (var writer = new EndianBinaryWriter(endianness, stream)) using (var writer = EndianBinaryWriter.Create(endianness, stream))
{ {
writer.Write(Math.PI); writer.Write(Math.PI);
@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Tests.IO
{ {
var stream = new MemoryStream(); var stream = new MemoryStream();
var writer = new EndianBinaryWriter(endianness, stream); var writer = EndianBinaryWriter.Create(endianness, stream);
writer.Write(true); // Bool writer.Write(true); // Bool
writer.Write((byte)1); // Byte writer.Write((byte)1); // Byte

Loading…
Cancel
Save