3.3 KiB
ByteWriter
(no submodules)
Purpose
Provides a dynamic binary writer for building TIFF/EXIF byte streams from scratch. It maintains an auto-growing Uint8Array buffer and exposes typed write methods for all TIFF primitive types. This is the write-side counterpart to ByteReader, sharing the same byte-order model and error infrastructure.
Features
- Auto-growing buffer (doubles capacity on overflow, no pre-allocation required)
- Big-endian and little-endian support with runtime
setByteOrder()switching - Full TIFF primitive coverage: uint8/16/32, int16, rational, raw bytes, strings
- Fluent API — all write methods return
thisfor chaining toUint8Array()snapshot of the written bytes at any pointExifErrorwithEXIF.WRITE_ERRORon non-Latin-1 string characters
Usage: Basic Example
import { ByteWriter } from "@suaveplan/exif/binary";
const writer = new ByteWriter(64, "BE");
writer.writeUint16(0x4D4D); // big-endian BOM
writer.writeUint16(0x002A); // TIFF magic
writer.writeUint32(8); // IFD0 offset
const bytes = writer.toUint8Array();
// Uint8Array [ 0x4D, 0x4D, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x08 ]
Usage: Advanced Example
import { ByteWriter } from "@suaveplan/exif/binary";
// Fluent chaining
const exifHeader = new ByteWriter()
.setByteOrder("LE")
.writeBytes(new Uint8Array([0x45, 0x78, 0x69, 0x66, 0x00, 0x00])) // "Exif\0\0"
.writeUint16(0x4949) // LE BOM
.writeUint16(0x002A)
.writeUint32(8)
.toUint8Array();
// Writing a RATIONAL (e.g. exposure time 1/100)
const writer = new ByteWriter();
writer.writeRational({ numerator: 1, denominator: 100 });
API Reference
constructor(initialSize?: number, byteOrder?: ByteOrder): ByteWriter
Creates a new writer. initialSize defaults to 256 bytes. byteOrder defaults to "BE".
get position: number
Returns the current write cursor position (total bytes written so far).
setByteOrder(order: ByteOrder): this
Switches the active byte order. Returns this for chaining.
writeUint8(value: number): this
Writes one unsigned byte.
writeUint16(value: number): this
Writes a 2-byte unsigned integer using the active byte order.
writeUint32(value: number): this
Writes a 4-byte unsigned integer using the active byte order.
writeInt16(value: number): this
Writes a 2-byte signed integer using the active byte order.
writeBytes(bytes: Uint8Array): this
Appends a raw byte array.
writeString(str: string): this
Writes a Latin-1 string without null termination. Throws ExifError(WRITE_ERROR) if any character is outside the Latin-1 range (> U+00FF).
writeRational(r: Rational): this
Writes an 8-byte TIFF RATIONAL (two unsigned 32-bit integers: numerator then denominator).
toUint8Array(): Uint8Array
Returns a copy of all bytes written so far (from position 0 to the current cursor).
Implementation Notes
The buffer starts at initialSize and doubles whenever the next write would overflow. This amortizes allocation cost to O(log n) reallocations for n total bytes written. The view is recreated after each reallocation since DataView binds to a specific ArrayBuffer instance. toUint8Array() always returns a fresh slice to prevent the caller from holding a reference to the internal buffer.