diff --git a/src/ImageProcessorCore/IO/EndianBinaryWriter.cs b/src/ImageProcessorCore/IO/EndianBinaryWriter.cs
new file mode 100644
index 000000000..0f37b9a13
--- /dev/null
+++ b/src/ImageProcessorCore/IO/EndianBinaryWriter.cs
@@ -0,0 +1,385 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore.IO
+{
+ using System;
+ using System.IO;
+ using System.Text;
+
+ ///
+ /// Equivalent of , but with either endianness, depending on
+ /// the it is constructed with.
+ ///
+ internal class EndianBinaryWriter : IDisposable
+ {
+ ///
+ /// Buffer used for temporary storage during conversion from primitives
+ ///
+ private readonly byte[] buffer = new byte[16];
+
+ ///
+ /// Buffer used for Write(char)
+ ///
+ private readonly char[] charBuffer = new char[1];
+
+ ///
+ /// Whether or not this writer has been disposed yet.
+ ///
+ private bool disposed;
+
+ ///
+ /// Initializes a new instance of the class
+ /// with the given bit converter, writing to the given stream, using UTF-8 encoding.
+ ///
+ /// Converter to use when writing data
+ /// Stream to write data to
+ public EndianBinaryWriter(EndianBitConverter bitConverter, Stream stream)
+ : this(bitConverter, stream, Encoding.UTF8)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with the given bit converter, writing to the given stream, using the given encoding.
+ ///
+ /// Converter to use when writing data
+ /// Stream to write data to
+ ///
+ /// Encoding to use when writing character data
+ ///
+ public EndianBinaryWriter(EndianBitConverter bitConverter, Stream stream, Encoding encoding)
+ {
+ // TODO: Use Guard
+ if (bitConverter == null)
+ {
+ throw new ArgumentNullException("bitConverter");
+ }
+
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+
+ if (encoding == null)
+ {
+ throw new ArgumentNullException("encoding");
+ }
+
+ if (!stream.CanWrite)
+ {
+ throw new ArgumentException("Stream isn't writable", "stream");
+ }
+
+ this.BaseStream = stream;
+ this.BitConverter = bitConverter;
+ this.Encoding = encoding;
+ }
+
+ ///
+ /// Gets the bit converter used to write values to the stream
+ ///
+ public EndianBitConverter BitConverter { get; }
+
+ ///
+ /// Gets the encoding used to write strings
+ ///
+ public Encoding Encoding { get; }
+
+ ///
+ /// Gets the underlying stream of the EndianBinaryWriter.
+ ///
+ public Stream BaseStream { get; }
+
+ ///
+ /// Closes the writer, including the underlying stream.
+ ///
+ public void Close()
+ {
+ this.Dispose();
+ }
+
+ ///
+ /// Flushes the underlying stream.
+ ///
+ public void Flush()
+ {
+ this.CheckDisposed();
+ this.BaseStream.Flush();
+ }
+
+ ///
+ /// Seeks within the stream.
+ ///
+ /// Offset to seek to.
+ /// Origin of seek operation.
+ public void Seek(int offset, SeekOrigin origin)
+ {
+ this.CheckDisposed();
+ this.BaseStream.Seek(offset, origin);
+ }
+
+ ///
+ /// Writes a boolean value to the stream. 1 byte is written.
+ ///
+ /// The value to write
+ public void Write(bool value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 1);
+ }
+
+ ///
+ /// Writes a 16-bit signed integer to the stream, using the bit converter
+ /// for this writer. 2 bytes are written.
+ ///
+ /// The value to write
+ public void Write(short value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 2);
+ }
+
+ ///
+ /// Writes a 32-bit signed integer to the stream, using the bit converter
+ /// for this writer. 4 bytes are written.
+ ///
+ /// The value to write
+ public void Write(int value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 4);
+ }
+
+ ///
+ /// Writes a 64-bit signed integer to the stream, using the bit converter
+ /// for this writer. 8 bytes are written.
+ ///
+ /// The value to write
+ public void Write(long value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 8);
+ }
+
+ ///
+ /// Writes a 16-bit unsigned integer to the stream, using the bit converter
+ /// for this writer. 2 bytes are written.
+ ///
+ /// The value to write
+ public void Write(ushort value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 2);
+ }
+
+ ///
+ /// Writes a 32-bit unsigned integer to the stream, using the bit converter
+ /// for this writer. 4 bytes are written.
+ ///
+ /// The value to write
+ public void Write(uint value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 4);
+ }
+
+ ///
+ /// Writes a 64-bit unsigned integer to the stream, using the bit converter
+ /// for this writer. 8 bytes are written.
+ ///
+ /// The value to write
+ public void Write(ulong value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 8);
+ }
+
+ ///
+ /// Writes a single-precision floating-point value to the stream, using the bit converter
+ /// for this writer. 4 bytes are written.
+ ///
+ /// The value to write
+ public void Write(float value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 4);
+ }
+
+ ///
+ /// Writes a double-precision floating-point value to the stream, using the bit converter
+ /// for this writer. 8 bytes are written.
+ ///
+ /// The value to write
+ public void Write(double value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 8);
+ }
+
+ ///
+ /// Writes a decimal value to the stream, using the bit converter for this writer.
+ /// 16 bytes are written.
+ ///
+ /// The value to write
+ public void Write(decimal value)
+ {
+ this.BitConverter.CopyBytes(value, this.buffer, 0);
+ this.WriteInternal(this.buffer, 16);
+ }
+
+ ///
+ /// Writes a signed byte to the stream.
+ ///
+ /// The value to write
+ public void Write(byte value)
+ {
+ this.buffer[0] = value;
+ this.WriteInternal(this.buffer, 1);
+ }
+
+ ///
+ /// Writes an unsigned byte to the stream.
+ ///
+ /// The value to write
+ public void Write(sbyte value)
+ {
+ this.buffer[0] = unchecked((byte)value);
+ this.WriteInternal(this.buffer, 1);
+ }
+
+ ///
+ /// Writes an array of bytes to the stream.
+ ///
+ /// The values to write
+ public void Write(byte[] value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ this.WriteInternal(value, value.Length);
+ }
+
+ ///
+ /// Writes a portion of an array of bytes to the stream.
+ ///
+ /// An array containing the bytes to write
+ /// The index of the first byte to write within the array
+ /// The number of bytes to write
+ public void Write(byte[] value, int offset, int count)
+ {
+ this.CheckDisposed();
+ this.BaseStream.Write(value, offset, count);
+ }
+
+ ///
+ /// Writes a single character to the stream, using the encoding for this writer.
+ ///
+ /// The value to write
+ public void Write(char value)
+ {
+ this.charBuffer[0] = value;
+ this.Write(this.charBuffer);
+ }
+
+ ///
+ /// Writes an array of characters to the stream, using the encoding for this writer.
+ ///
+ /// An array containing the characters to write
+ public void Write(char[] value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ this.CheckDisposed();
+ byte[] data = this.Encoding.GetBytes(value, 0, value.Length);
+ this.WriteInternal(data, data.Length);
+ }
+
+ ///
+ /// Writes a string to the stream, using the encoding for this writer.
+ ///
+ /// The value to write. Must not be null.
+ /// value is null
+ public void Write(string value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ this.CheckDisposed();
+ byte[] data = this.Encoding.GetBytes(value);
+ this.Write7BitEncodedInt(data.Length);
+ this.WriteInternal(data, data.Length);
+ }
+
+ ///
+ /// Writes a 7-bit encoded integer from the stream. This is stored with the least significant
+ /// information first, with 7 bits of information per byte of value, and the top
+ /// bit as a continuation flag.
+ ///
+ /// The 7-bit encoded integer to write to the stream
+ public void Write7BitEncodedInt(int value)
+ {
+ this.CheckDisposed();
+ if (value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), "Value must be greater than or equal to 0.");
+ }
+
+ int index = 0;
+ while (value >= 128)
+ {
+ this.buffer[index++] = (byte)((value & 0x7f) | 0x80);
+ value = value >> 7;
+ index++;
+ }
+
+ this.buffer[index++] = (byte)value;
+ this.BaseStream.Write(this.buffer, 0, index);
+ }
+
+ ///
+ /// Checks whether or not the writer has been disposed, throwing an exception if so.
+ ///
+ private void CheckDisposed()
+ {
+ if (this.disposed)
+ {
+ throw new ObjectDisposedException("EndianBinaryWriter");
+ }
+ }
+
+ ///
+ /// Writes the specified number of bytes from the start of the given byte array,
+ /// after checking whether or not the writer has been disposed.
+ ///
+ /// The array of bytes to write from
+ /// The number of bytes to write
+ private void WriteInternal(byte[] bytes, int length)
+ {
+ this.CheckDisposed();
+ this.BaseStream.Write(bytes, 0, length);
+ }
+
+ ///
+ /// Disposes of the underlying stream.
+ ///
+ public void Dispose()
+ {
+ if (!this.disposed)
+ {
+ this.Flush();
+ this.disposed = true;
+ ((IDisposable)this.BaseStream).Dispose();
+ }
+ }
+ }
+}
\ No newline at end of file