first commit
This commit is contained in:
86
docs/media/image/exif/src/ifd/parse.md
Normal file
86
docs/media/image/exif/src/ifd/parse.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# IFD Parse
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Implements TIFF IFD (Image File Directory) parsing, the core data structure used by EXIF to store metadata. Each IFD entry is a 12-byte record containing a tag number, data type, count, and either an inline value or an offset to data elsewhere in the TIFF stream. This module handles all 12 standard TIFF data types and provides typed accessor helpers for downstream EXIF, GPS, and sub-IFD readers.
|
||||
|
||||
## Features
|
||||
|
||||
- Parses all 12 TIFF primitive types: BYTE, ASCII, SHORT, LONG, RATIONAL, SBYTE, UNDEFINED, SSHORT, SLONG, SRATIONAL, FLOAT, DOUBLE
|
||||
- Inline vs. offset-stored value selection based on total data size
|
||||
- Graceful handling of malformed entries (skips rather than throwing)
|
||||
- Typed accessors: `getTagNumber`, `getTagString`, `getTagRational`, `getTagRationalArray`
|
||||
- Bounds-checked with `ExifError(PARSE_ERROR)` on structural violations
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { ByteReader } from "@suaveplan/exif/binary";
|
||||
import { parseIfd, getTagString } from "@suaveplan/exif";
|
||||
|
||||
const reader = new ByteReader(tiffBuffer, "BE");
|
||||
const ifd0 = parseIfd(reader, 8);
|
||||
|
||||
const make = getTagString(ifd0, 0x010F); // Make tag
|
||||
const model = getTagString(ifd0, 0x0110); // Model tag
|
||||
console.log(`${make} ${model}`);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { ByteReader } from "@suaveplan/exif/binary";
|
||||
import { parseIfd, getTagNumber, getTagRational } from "@suaveplan/exif";
|
||||
|
||||
const reader = new ByteReader(tiffBuffer, "LE");
|
||||
|
||||
// Parse IFD0 then follow ExifIFD pointer
|
||||
const ifd0 = parseIfd(reader, 8);
|
||||
const exifIfdOffset = getTagNumber(ifd0, 0x8769); // ExifIFD pointer
|
||||
|
||||
if (exifIfdOffset !== undefined) {
|
||||
const exifIfd = parseIfd(reader, exifIfdOffset);
|
||||
const exposureTime = getTagRational(exifIfd, 0x829A);
|
||||
const fNumber = getTagRational(exifIfd, 0x829D);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `IfdEntry`
|
||||
|
||||
```ts
|
||||
interface IfdEntry {
|
||||
tag: number;
|
||||
type: number;
|
||||
count: number;
|
||||
value: unknown;
|
||||
}
|
||||
```
|
||||
|
||||
### `parseIfd(reader: ByteReader, ifdOffset: number): Map<number, IfdEntry>`
|
||||
|
||||
Parses the IFD at `ifdOffset` within `reader`. Returns a `Map<tag, IfdEntry>`. Throws `ExifError(PARSE_ERROR)` if the IFD count field extends beyond the buffer. Malformed individual entries are silently skipped.
|
||||
|
||||
### `getTagNumber(entries: Map<number, IfdEntry>, tag: number): number | undefined`
|
||||
|
||||
Extracts a SHORT or LONG tag as a number.
|
||||
|
||||
### `getTagString(entries: Map<number, IfdEntry>, tag: number): string | undefined`
|
||||
|
||||
Extracts an ASCII tag as a string.
|
||||
|
||||
### `getTagRational(entries: Map<number, IfdEntry>, tag: number): Rational | undefined`
|
||||
|
||||
Extracts a single RATIONAL or SRATIONAL tag.
|
||||
|
||||
### `getTagRationalArray(entries: Map<number, IfdEntry>, tag: number): Rational[] | undefined`
|
||||
|
||||
Extracts an array of RATIONAL values (e.g. GPS coordinate triples where each axis is three RATIONALs for degrees/minutes/seconds).
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Inline storage applies when `typeSize * count <= 4`: the value is packed into the 4-byte value/offset field of the IFD entry. For larger values, the field contains a file offset to the actual data. ASCII strings have trailing nulls stripped. The `UNDEFINED` type (7) returns a raw `Uint8Array`. Sign extension for SBYTE uses the left-shift/right-shift trick `<< 24 >> 24`.
|
||||
Reference in New Issue
Block a user