@crewhaus/tool-media 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/NOTICE +9 -0
- package/README.md +34 -8
- package/dist/index.js +149 -26
- package/dist/lib/color.d.ts +2 -0
- package/dist/lib/color.js +17 -3
- package/dist/lib/jpeg.d.ts +141 -3
- package/dist/lib/jpeg.js +527 -10
- package/dist/lib/subtitle.d.ts +13 -0
- package/dist/lib/subtitle.js +27 -7
- package/dist/paths.d.ts +21 -2
- package/dist/paths.js +72 -13
- package/package.json +10 -6
- package/dist/fixtures.d.ts +0 -81
- package/dist/fixtures.js +0 -385
package/dist/lib/jpeg.d.ts
CHANGED
|
@@ -21,6 +21,59 @@ export declare function readJpegSegments(bytes: Uint8Array): {
|
|
|
21
21
|
segments: JpegSegment[];
|
|
22
22
|
scanStart: number;
|
|
23
23
|
};
|
|
24
|
+
/** One piece of a JPEG, in file order: a marker segment, or a scan's entropy-coded bytes. */
|
|
25
|
+
export type JpegPart = {
|
|
26
|
+
readonly type: "segment";
|
|
27
|
+
readonly segment: JpegSegment;
|
|
28
|
+
} | {
|
|
29
|
+
readonly type: "scan";
|
|
30
|
+
readonly start: number;
|
|
31
|
+
readonly end: number;
|
|
32
|
+
};
|
|
33
|
+
export type JpegWalk = {
|
|
34
|
+
/** Every piece after SOI, in order, up to and including EOI. */
|
|
35
|
+
readonly parts: ReadonlyArray<JpegPart>;
|
|
36
|
+
/** The marker segments alone, in order. */
|
|
37
|
+
readonly segments: ReadonlyArray<JpegSegment>;
|
|
38
|
+
/** Offset just past EOI, or null when the file ends without one. */
|
|
39
|
+
readonly eoiEnd: number | null;
|
|
40
|
+
/** Bytes after EOI: where an appended image or video lives. 0 when EOI is missing. */
|
|
41
|
+
readonly trailing: number;
|
|
42
|
+
/**
|
|
43
|
+
* Where the walk stopped short of EOI after the first scan, and why: a
|
|
44
|
+
* segment the end of the file cuts off, or bytes where a marker should
|
|
45
|
+
* be. Null when it reached EOI or the file's end in scan data. The bytes
|
|
46
|
+
* from here on were not walked.
|
|
47
|
+
*/
|
|
48
|
+
readonly stopped: {
|
|
49
|
+
readonly offset: number;
|
|
50
|
+
readonly reason: string;
|
|
51
|
+
} | null;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Walk the WHOLE codestream: every marker segment, including those between
|
|
55
|
+
* the scans of a progressive or multi-scan file, to EOI.
|
|
56
|
+
*
|
|
57
|
+
* `readJpegSegments` stops at the first start-of-scan, which is all a header
|
|
58
|
+
* reader needs, and 0.7.0's ExifStrip copied everything after that point
|
|
59
|
+
* verbatim. But an APPn or COM segment may sit between scans, and a camera
|
|
60
|
+
* appends whole images after EOI (MPF previews, HDR gain maps, stereo pairs)
|
|
61
|
+
* and phones append motion-photo video; each can carry its own EXIF and GPS.
|
|
62
|
+
*
|
|
63
|
+
* Inside a scan, `0xFF` followed by `0x00` (stuffing), `0xD0`–`0xD7` (restart
|
|
64
|
+
* markers) or another `0xFF` (fill) belongs to the scan; any other `0xFF xx`
|
|
65
|
+
* is the next marker. The walk is linear: the scan search is a native
|
|
66
|
+
* `indexOf` from where the last one stopped.
|
|
67
|
+
*
|
|
68
|
+
* A broken header (before the first scan) is refused. Past the first scan
|
|
69
|
+
* the picture is already there, and a file cut short there — a partial
|
|
70
|
+
* download, a truncated progressive JPEG — is still a photo: the walk stops
|
|
71
|
+
* at the break and says where (`stopped`), rather than refusing a file
|
|
72
|
+
* 0.7.0 read, which only ever looked as far as the first scan.
|
|
73
|
+
*/
|
|
74
|
+
export declare function walkJpeg(bytes: Uint8Array): JpegWalk;
|
|
75
|
+
/** A hint at what the bytes after EOI are, for a person reading the result. */
|
|
76
|
+
export declare function describeTrailer(trailer: Uint8Array): string;
|
|
24
77
|
export type GpsFix = {
|
|
25
78
|
readonly latitude: number;
|
|
26
79
|
readonly longitude: number;
|
|
@@ -72,10 +125,95 @@ export type StripResult = {
|
|
|
72
125
|
bytes: number;
|
|
73
126
|
}>;
|
|
74
127
|
readonly bytesRemoved: number;
|
|
128
|
+
/** Bytes after EOI that were dropped: an appended image or video, and its metadata. */
|
|
129
|
+
readonly trailingBytesRemoved: number;
|
|
130
|
+
/** What those bytes looked like, when there were any. */
|
|
131
|
+
readonly trailingKind?: string;
|
|
132
|
+
/** The file ends without EOI; everything up to its end was walked and kept. */
|
|
133
|
+
readonly eoiMissing: boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Where the file breaks off after the first scan, when it does: the walk
|
|
136
|
+
* stopped there, and the bytes after it were kept verbatim (or, when they
|
|
137
|
+
* begin a metadata segment, dropped).
|
|
138
|
+
*/
|
|
139
|
+
readonly breaksOffAt?: {
|
|
140
|
+
readonly offset: number;
|
|
141
|
+
readonly reason: string;
|
|
142
|
+
};
|
|
75
143
|
};
|
|
76
144
|
/**
|
|
77
|
-
* A JPEG with its metadata
|
|
78
|
-
*
|
|
79
|
-
*
|
|
145
|
+
* A JPEG with its metadata dropped: every APPn and COM segment the options
|
|
146
|
+
* do not keep, wherever it sits (before the first scan or between scans),
|
|
147
|
+
* and everything after EOI. The scans' entropy-coded bytes are copied
|
|
148
|
+
* verbatim — nothing is re-encoded, so the primary image is bit-for-bit the
|
|
149
|
+
* same picture, without the record of who took it and where.
|
|
150
|
+
*
|
|
151
|
+
* Dropping the trailer loses an appended preview, gain map or motion-photo
|
|
152
|
+
* video, and the metadata inside each. Nothing in the stripped file points
|
|
153
|
+
* at them any more: the MPF index (APP2) and the XMP (APP1) that did are
|
|
154
|
+
* metadata segments and are removed.
|
|
80
155
|
*/
|
|
81
156
|
export declare function stripJpegMetadata(bytes: Uint8Array, options?: StripOptions): StripResult;
|
|
157
|
+
/** One EXIF block found anywhere in a file, with where it was. */
|
|
158
|
+
export type ExifLocation = {
|
|
159
|
+
readonly where: "before the first scan" | "between scans" | "in an appended image" | "in bytes no walk accounts for";
|
|
160
|
+
readonly offset: number;
|
|
161
|
+
readonly exif: ExifData | null;
|
|
162
|
+
/** Why `exif` is null: the block is there but could not be parsed. */
|
|
163
|
+
readonly unreadable?: string;
|
|
164
|
+
};
|
|
165
|
+
export type JpegMetadataReport = {
|
|
166
|
+
/** Every EXIF block in the file, the primary one first. */
|
|
167
|
+
readonly exifBlocks: ReadonlyArray<ExifLocation>;
|
|
168
|
+
/** APPn and COM segments that sit between or after the scans of the main image. */
|
|
169
|
+
readonly interScanMetadataSegments: ReadonlyArray<string>;
|
|
170
|
+
/** APPn segments before the first scan, by name. */
|
|
171
|
+
readonly metadataSegments: ReadonlyArray<string>;
|
|
172
|
+
readonly trailingBytes: number;
|
|
173
|
+
readonly trailingKind?: string;
|
|
174
|
+
/** JPEGs found in the trailer and walked for EXIF. */
|
|
175
|
+
readonly embeddedImages: number;
|
|
176
|
+
/** JPEG starts in the trailer beyond the ones walked; their metadata is unknown. */
|
|
177
|
+
readonly embeddedImagesNotInspected: number;
|
|
178
|
+
readonly eoiMissing: boolean;
|
|
179
|
+
/** Where the main image breaks off after its first scan, when it does. */
|
|
180
|
+
readonly breaksOffAt?: {
|
|
181
|
+
readonly offset: number;
|
|
182
|
+
readonly reason: string;
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Bytes no walk accounts for and that are not padding: after a break,
|
|
186
|
+
* after EOI outside every appended image walked (a video, data this does
|
|
187
|
+
* not recognise, an image that would not walk), or past the end of what
|
|
188
|
+
* was read. They were searched for EXIF blocks, not parsed, so they may
|
|
189
|
+
* hold a location this report does not see.
|
|
190
|
+
*/
|
|
191
|
+
readonly unaccountedBytes: number;
|
|
192
|
+
/** EXIF signatures in those bytes beyond the ones parsed. */
|
|
193
|
+
readonly exifSignaturesNotParsed: number;
|
|
194
|
+
/** Every APPn segment other than EXIF, in the main image and the appended ones walked. */
|
|
195
|
+
readonly otherMetadata: ReadonlyArray<OtherMetadata>;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* A metadata segment other than EXIF, and whether it names a location.
|
|
199
|
+
* `location` is true when it does, false when it was read (or its format
|
|
200
|
+
* has no place for one) and it does not, and null when this reader does
|
|
201
|
+
* not parse it, so it may.
|
|
202
|
+
*/
|
|
203
|
+
export type OtherMetadata = {
|
|
204
|
+
/** `"APP1 XMP"`, `"APP13 Photoshop"`, or the marker and its identifier. */
|
|
205
|
+
readonly segment: string;
|
|
206
|
+
readonly where: ExifLocation["where"];
|
|
207
|
+
readonly offset: number;
|
|
208
|
+
readonly location: boolean | null;
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* Every place in a JPEG that can carry metadata: EXIF before and between
|
|
212
|
+
* scans, other APPn/COM segments, and the JPEGs appended after EOI (walked
|
|
213
|
+
* once each, not their own trailers again). Bytes no walk accounts for —
|
|
214
|
+
* after a break, a video, unrecognised data, an appended image that would
|
|
215
|
+
* not walk — are counted and searched for EXIF blocks, which are parsed
|
|
216
|
+
* where found. What this reports is what ExifRead answers from, so it
|
|
217
|
+
* cannot call a file clean on the strength of bytes it never read.
|
|
218
|
+
*/
|
|
219
|
+
export declare function inspectJpegMetadata(bytes: Uint8Array): JpegMetadataReport;
|