Files
skills/docs/media/image/exif/src/binary/writer/byte-writer.md
2026-05-29 08:20:56 +01:00

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 this for chaining
  • toUint8Array() snapshot of the written bytes at any point
  • ExifError with EXIF.WRITE_ERROR on 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.