first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
# JPEG Segments
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Parses the segment structure of a JPEG file and identifies metadata segments (EXIF, XMP, IPTC). JPEG is a container format: each segment is introduced by a 2-byte marker (`0xFF` + type), followed by a 2-byte big-endian length and payload. This module provides the structural parser that upstream readers (EXIF, IPTC, XMP) rely on to locate their data.
## Features
- `parseJpegSegments` — iterates all APP/marker segments up to and including SOS
- Handles padding bytes (multiple consecutive `0xFF`) between segments
- `isExifSegment` — identifies APP1 segments with the `Exif\0\0` header
- `isXmpSegment` — identifies APP1 segments with the XMP namespace header
- `isIptcSegment` — identifies APP13 segments with the `Photoshop 3.0\0` header
- Bounds-checking with `ExifError(PARSE_ERROR)` on malformed input
## Usage: Basic Example
```ts
import { parseJpegSegments, isExifSegment } from "@suaveplan/exif";
const segments = parseJpegSegments(jpegBuffer);
const exifSeg = segments.find(isExifSegment);
if (exifSeg) {
console.log("EXIF data found, length:", exifSeg.data.length);
}
```
## Usage: Advanced Example
```ts
import { parseJpegSegments, isExifSegment, isXmpSegment, isIptcSegment } from "@suaveplan/exif";
const segments = parseJpegSegments(jpegBuffer);
for (const seg of segments) {
if (isExifSegment(seg)) {
console.log(`EXIF APP1 at offset ${seg.offset}, ${seg.data.length} bytes`);
} else if (isXmpSegment(seg)) {
console.log(`XMP APP1 at offset ${seg.offset}`);
} else if (isIptcSegment(seg)) {
console.log(`IPTC APP13 at offset ${seg.offset}`);
}
}
```
## API Reference
### `JpegSegment`
```ts
interface JpegSegment {
marker: number; // e.g. 0xFFE1 for APP1
data: Uint8Array; // payload (length field excluded)
offset: number; // byte offset of marker in original buffer
}
```
### `parseJpegSegments(buffer: Uint8Array): JpegSegment[]`
Parses all JPEG segments from `buffer`. Returns segments from SOI through SOS (inclusive). Throws `ExifError(PARSE_ERROR)` if:
- The buffer does not start with `FF D8` (SOI)
- A segment's length field is less than 2
- A segment's data extends beyond the buffer
### `isExifSegment(seg: JpegSegment): boolean`
Returns `true` if `seg` is an APP1 segment (`0xFFE1`) whose payload begins with `Exif\0\0`.
### `isXmpSegment(seg: JpegSegment): boolean`
Returns `true` if `seg` is an APP1 segment whose payload begins with `http://ns.adobe.com/xap/1.0/\0`.
### `isIptcSegment(seg: JpegSegment): boolean`
Returns `true` if `seg` is an APP13 segment (`0xFFED`) whose payload begins with `Photoshop 3.0\0`.
## Implementation Notes
The parser skips padding `0xFF` bytes between markers as permitted by the JFIF specification. Standalone markers (SOI, EOI, RST0–RST7) have no length field and are handled as zero-data segments. Parsing stops at the SOS marker to avoid processing compressed image data as segments. The `data` field of each segment excludes the 2-byte length field, so `data.length === segmentLength - 2`.