cross-image 0.1.2
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 +21 -0
- package/README.md +606 -0
- package/esm/mod.d.ts +33 -0
- package/esm/mod.d.ts.map +1 -0
- package/esm/mod.js +31 -0
- package/esm/package.json +3 -0
- package/esm/src/formats/ascii.d.ts +27 -0
- package/esm/src/formats/ascii.d.ts.map +1 -0
- package/esm/src/formats/ascii.js +172 -0
- package/esm/src/formats/bmp.d.ts +19 -0
- package/esm/src/formats/bmp.d.ts.map +1 -0
- package/esm/src/formats/bmp.js +174 -0
- package/esm/src/formats/gif.d.ts +40 -0
- package/esm/src/formats/gif.d.ts.map +1 -0
- package/esm/src/formats/gif.js +385 -0
- package/esm/src/formats/jpeg.d.ts +18 -0
- package/esm/src/formats/jpeg.d.ts.map +1 -0
- package/esm/src/formats/jpeg.js +414 -0
- package/esm/src/formats/png.d.ts +33 -0
- package/esm/src/formats/png.d.ts.map +1 -0
- package/esm/src/formats/png.js +544 -0
- package/esm/src/formats/raw.d.ts +23 -0
- package/esm/src/formats/raw.d.ts.map +1 -0
- package/esm/src/formats/raw.js +98 -0
- package/esm/src/formats/tiff.d.ts +58 -0
- package/esm/src/formats/tiff.d.ts.map +1 -0
- package/esm/src/formats/tiff.js +791 -0
- package/esm/src/formats/webp.d.ts +22 -0
- package/esm/src/formats/webp.d.ts.map +1 -0
- package/esm/src/formats/webp.js +403 -0
- package/esm/src/image.d.ts +124 -0
- package/esm/src/image.d.ts.map +1 -0
- package/esm/src/image.js +320 -0
- package/esm/src/types.d.ts +167 -0
- package/esm/src/types.d.ts.map +1 -0
- package/esm/src/types.js +1 -0
- package/esm/src/utils/gif_decoder.d.ts +42 -0
- package/esm/src/utils/gif_decoder.d.ts.map +1 -0
- package/esm/src/utils/gif_decoder.js +374 -0
- package/esm/src/utils/gif_encoder.d.ts +29 -0
- package/esm/src/utils/gif_encoder.d.ts.map +1 -0
- package/esm/src/utils/gif_encoder.js +226 -0
- package/esm/src/utils/jpeg_decoder.d.ts +39 -0
- package/esm/src/utils/jpeg_decoder.d.ts.map +1 -0
- package/esm/src/utils/jpeg_decoder.js +580 -0
- package/esm/src/utils/jpeg_encoder.d.ts +33 -0
- package/esm/src/utils/jpeg_encoder.d.ts.map +1 -0
- package/esm/src/utils/jpeg_encoder.js +1017 -0
- package/esm/src/utils/lzw.d.ts +43 -0
- package/esm/src/utils/lzw.d.ts.map +1 -0
- package/esm/src/utils/lzw.js +309 -0
- package/esm/src/utils/resize.d.ts +9 -0
- package/esm/src/utils/resize.d.ts.map +1 -0
- package/esm/src/utils/resize.js +52 -0
- package/esm/src/utils/tiff_lzw.d.ts +44 -0
- package/esm/src/utils/tiff_lzw.d.ts.map +1 -0
- package/esm/src/utils/tiff_lzw.js +306 -0
- package/esm/src/utils/webp_decoder.d.ts +39 -0
- package/esm/src/utils/webp_decoder.d.ts.map +1 -0
- package/esm/src/utils/webp_decoder.js +493 -0
- package/esm/src/utils/webp_encoder.d.ts +72 -0
- package/esm/src/utils/webp_encoder.d.ts.map +1 -0
- package/esm/src/utils/webp_encoder.js +627 -0
- package/package.json +41 -0
- package/script/mod.d.ts +33 -0
- package/script/mod.d.ts.map +1 -0
- package/script/mod.js +43 -0
- package/script/package.json +3 -0
- package/script/src/formats/ascii.d.ts +27 -0
- package/script/src/formats/ascii.d.ts.map +1 -0
- package/script/src/formats/ascii.js +176 -0
- package/script/src/formats/bmp.d.ts +19 -0
- package/script/src/formats/bmp.d.ts.map +1 -0
- package/script/src/formats/bmp.js +178 -0
- package/script/src/formats/gif.d.ts +40 -0
- package/script/src/formats/gif.d.ts.map +1 -0
- package/script/src/formats/gif.js +389 -0
- package/script/src/formats/jpeg.d.ts +18 -0
- package/script/src/formats/jpeg.d.ts.map +1 -0
- package/script/src/formats/jpeg.js +451 -0
- package/script/src/formats/png.d.ts +33 -0
- package/script/src/formats/png.d.ts.map +1 -0
- package/script/src/formats/png.js +548 -0
- package/script/src/formats/raw.d.ts +23 -0
- package/script/src/formats/raw.d.ts.map +1 -0
- package/script/src/formats/raw.js +102 -0
- package/script/src/formats/tiff.d.ts +58 -0
- package/script/src/formats/tiff.d.ts.map +1 -0
- package/script/src/formats/tiff.js +795 -0
- package/script/src/formats/webp.d.ts +22 -0
- package/script/src/formats/webp.d.ts.map +1 -0
- package/script/src/formats/webp.js +440 -0
- package/script/src/image.d.ts +124 -0
- package/script/src/image.d.ts.map +1 -0
- package/script/src/image.js +324 -0
- package/script/src/types.d.ts +167 -0
- package/script/src/types.d.ts.map +1 -0
- package/script/src/types.js +2 -0
- package/script/src/utils/gif_decoder.d.ts +42 -0
- package/script/src/utils/gif_decoder.d.ts.map +1 -0
- package/script/src/utils/gif_decoder.js +378 -0
- package/script/src/utils/gif_encoder.d.ts +29 -0
- package/script/src/utils/gif_encoder.d.ts.map +1 -0
- package/script/src/utils/gif_encoder.js +230 -0
- package/script/src/utils/jpeg_decoder.d.ts +39 -0
- package/script/src/utils/jpeg_decoder.d.ts.map +1 -0
- package/script/src/utils/jpeg_decoder.js +584 -0
- package/script/src/utils/jpeg_encoder.d.ts +33 -0
- package/script/src/utils/jpeg_encoder.d.ts.map +1 -0
- package/script/src/utils/jpeg_encoder.js +1021 -0
- package/script/src/utils/lzw.d.ts +43 -0
- package/script/src/utils/lzw.d.ts.map +1 -0
- package/script/src/utils/lzw.js +314 -0
- package/script/src/utils/resize.d.ts +9 -0
- package/script/src/utils/resize.d.ts.map +1 -0
- package/script/src/utils/resize.js +56 -0
- package/script/src/utils/tiff_lzw.d.ts +44 -0
- package/script/src/utils/tiff_lzw.d.ts.map +1 -0
- package/script/src/utils/tiff_lzw.js +311 -0
- package/script/src/utils/webp_decoder.d.ts +39 -0
- package/script/src/utils/webp_decoder.d.ts.map +1 -0
- package/script/src/utils/webp_decoder.js +497 -0
- package/script/src/utils/webp_encoder.d.ts +72 -0
- package/script/src/utils/webp_encoder.d.ts.map +1 -0
- package/script/src/utils/webp_encoder.js +631 -0
package/esm/src/image.js
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { resizeBilinear, resizeNearest } from "./utils/resize.js";
|
|
2
|
+
import { PNGFormat } from "./formats/png.js";
|
|
3
|
+
import { JPEGFormat } from "./formats/jpeg.js";
|
|
4
|
+
import { WebPFormat } from "./formats/webp.js";
|
|
5
|
+
import { GIFFormat } from "./formats/gif.js";
|
|
6
|
+
import { TIFFFormat } from "./formats/tiff.js";
|
|
7
|
+
import { BMPFormat } from "./formats/bmp.js";
|
|
8
|
+
import { RAWFormat } from "./formats/raw.js";
|
|
9
|
+
import { ASCIIFormat } from "./formats/ascii.js";
|
|
10
|
+
/**
|
|
11
|
+
* Main Image class for reading, manipulating, and saving images
|
|
12
|
+
*/
|
|
13
|
+
export class Image {
|
|
14
|
+
constructor() {
|
|
15
|
+
Object.defineProperty(this, "imageData", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true,
|
|
18
|
+
writable: true,
|
|
19
|
+
value: null
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get the current image width
|
|
24
|
+
*/
|
|
25
|
+
get width() {
|
|
26
|
+
if (!this.imageData)
|
|
27
|
+
throw new Error("No image loaded");
|
|
28
|
+
return this.imageData.width;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get the current image height
|
|
32
|
+
*/
|
|
33
|
+
get height() {
|
|
34
|
+
if (!this.imageData)
|
|
35
|
+
throw new Error("No image loaded");
|
|
36
|
+
return this.imageData.height;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get the current image data
|
|
40
|
+
*/
|
|
41
|
+
get data() {
|
|
42
|
+
if (!this.imageData)
|
|
43
|
+
throw new Error("No image loaded");
|
|
44
|
+
return this.imageData.data;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get the current image metadata
|
|
48
|
+
*/
|
|
49
|
+
get metadata() {
|
|
50
|
+
if (!this.imageData)
|
|
51
|
+
throw new Error("No image loaded");
|
|
52
|
+
return this.imageData.metadata;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Set or update image metadata
|
|
56
|
+
* @param metadata Metadata to set or merge
|
|
57
|
+
* @param merge If true, merges with existing metadata. If false, replaces it. Default: true
|
|
58
|
+
*/
|
|
59
|
+
setMetadata(metadata, merge = true) {
|
|
60
|
+
if (!this.imageData)
|
|
61
|
+
throw new Error("No image loaded");
|
|
62
|
+
if (merge && this.imageData.metadata) {
|
|
63
|
+
this.imageData.metadata = {
|
|
64
|
+
...this.imageData.metadata,
|
|
65
|
+
...metadata,
|
|
66
|
+
custom: {
|
|
67
|
+
...(this.imageData.metadata.custom || {}),
|
|
68
|
+
...(metadata.custom || {}),
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.imageData.metadata = { ...metadata };
|
|
74
|
+
}
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get a specific metadata field
|
|
79
|
+
* @param key The metadata field to retrieve
|
|
80
|
+
* @returns The metadata value or undefined
|
|
81
|
+
*/
|
|
82
|
+
getMetadataField(key) {
|
|
83
|
+
if (!this.imageData)
|
|
84
|
+
throw new Error("No image loaded");
|
|
85
|
+
return this.imageData.metadata?.[key];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get position (latitude, longitude) from metadata
|
|
89
|
+
* @returns Object with latitude and longitude, or undefined if not available
|
|
90
|
+
*/
|
|
91
|
+
getPosition() {
|
|
92
|
+
const latitude = this.getMetadataField("latitude");
|
|
93
|
+
const longitude = this.getMetadataField("longitude");
|
|
94
|
+
if (latitude !== undefined && longitude !== undefined) {
|
|
95
|
+
return { latitude, longitude };
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Set position (latitude, longitude) in metadata
|
|
101
|
+
* @param latitude GPS latitude
|
|
102
|
+
* @param longitude GPS longitude
|
|
103
|
+
*/
|
|
104
|
+
setPosition(latitude, longitude) {
|
|
105
|
+
return this.setMetadata({ latitude, longitude });
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get physical dimensions from metadata
|
|
109
|
+
* @returns Object with DPI and physical dimensions, or undefined if not available
|
|
110
|
+
*/
|
|
111
|
+
getDimensions() {
|
|
112
|
+
const dpiX = this.getMetadataField("dpiX");
|
|
113
|
+
const dpiY = this.getMetadataField("dpiY");
|
|
114
|
+
const physicalWidth = this.getMetadataField("physicalWidth");
|
|
115
|
+
const physicalHeight = this.getMetadataField("physicalHeight");
|
|
116
|
+
if (dpiX !== undefined || dpiY !== undefined || physicalWidth !== undefined ||
|
|
117
|
+
physicalHeight !== undefined) {
|
|
118
|
+
return { dpiX, dpiY, physicalWidth, physicalHeight };
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Set physical dimensions in metadata
|
|
124
|
+
* @param dpiX Dots per inch (horizontal)
|
|
125
|
+
* @param dpiY Dots per inch (vertical), defaults to dpiX if not provided
|
|
126
|
+
*/
|
|
127
|
+
setDPI(dpiX, dpiY) {
|
|
128
|
+
const actualDpiY = dpiY ?? dpiX;
|
|
129
|
+
// Calculate physical dimensions based on pixel dimensions and DPI
|
|
130
|
+
const physicalWidth = this.width / dpiX;
|
|
131
|
+
const physicalHeight = this.height / actualDpiY;
|
|
132
|
+
return this.setMetadata({
|
|
133
|
+
dpiX,
|
|
134
|
+
dpiY: actualDpiY,
|
|
135
|
+
physicalWidth,
|
|
136
|
+
physicalHeight,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Register a custom image format
|
|
141
|
+
* @param format Custom format implementation
|
|
142
|
+
*/
|
|
143
|
+
static registerFormat(format) {
|
|
144
|
+
Image.formats.push(format);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get all registered formats
|
|
148
|
+
*/
|
|
149
|
+
static getFormats() {
|
|
150
|
+
return Image.formats;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Read an image from bytes
|
|
154
|
+
* @param data Raw image data
|
|
155
|
+
* @param format Optional format hint (e.g., "png", "jpeg", "webp")
|
|
156
|
+
* @returns Image instance
|
|
157
|
+
*/
|
|
158
|
+
static async read(data, format) {
|
|
159
|
+
const image = new Image();
|
|
160
|
+
// Try specified format first
|
|
161
|
+
if (format) {
|
|
162
|
+
const handler = Image.formats.find((f) => f.name === format);
|
|
163
|
+
if (handler && handler.canDecode(data)) {
|
|
164
|
+
image.imageData = await handler.decode(data);
|
|
165
|
+
return image;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Auto-detect format
|
|
169
|
+
for (const handler of Image.formats) {
|
|
170
|
+
if (handler.canDecode(data)) {
|
|
171
|
+
image.imageData = await handler.decode(data);
|
|
172
|
+
return image;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
throw new Error("Unsupported or unrecognized image format");
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Read all frames from a multi-frame image (GIF animation, multi-page TIFF)
|
|
179
|
+
* @param data Raw image data
|
|
180
|
+
* @param format Optional format hint (e.g., "gif", "tiff")
|
|
181
|
+
* @returns MultiFrameImageData with all frames
|
|
182
|
+
*/
|
|
183
|
+
static async readFrames(data, format) {
|
|
184
|
+
// Try specified format first
|
|
185
|
+
if (format) {
|
|
186
|
+
const handler = Image.formats.find((f) => f.name === format);
|
|
187
|
+
if (handler && handler.canDecode(data) && handler.decodeFrames) {
|
|
188
|
+
return await handler.decodeFrames(data);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Auto-detect format
|
|
192
|
+
for (const handler of Image.formats) {
|
|
193
|
+
if (handler.canDecode(data) && handler.decodeFrames) {
|
|
194
|
+
return await handler.decodeFrames(data);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
throw new Error("Unsupported or unrecognized multi-frame image format");
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Save multi-frame image data to bytes in the specified format
|
|
201
|
+
* @param format Format name (e.g., "gif", "tiff")
|
|
202
|
+
* @param imageData Multi-frame image data to save
|
|
203
|
+
* @param options Optional format-specific encoding options
|
|
204
|
+
* @returns Encoded image bytes
|
|
205
|
+
*/
|
|
206
|
+
static async saveFrames(format, imageData, options) {
|
|
207
|
+
const handler = Image.formats.find((f) => f.name === format);
|
|
208
|
+
if (!handler) {
|
|
209
|
+
throw new Error(`Unsupported format: ${format}`);
|
|
210
|
+
}
|
|
211
|
+
if (!handler.encodeFrames) {
|
|
212
|
+
throw new Error(`Format ${format} does not support multi-frame encoding`);
|
|
213
|
+
}
|
|
214
|
+
return await handler.encodeFrames(imageData, options);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Create an image from raw RGBA data
|
|
218
|
+
* @param width Image width
|
|
219
|
+
* @param height Image height
|
|
220
|
+
* @param data Raw RGBA pixel data (4 bytes per pixel)
|
|
221
|
+
* @returns Image instance
|
|
222
|
+
*/
|
|
223
|
+
static fromRGBA(width, height, data) {
|
|
224
|
+
if (data.length !== width * height * 4) {
|
|
225
|
+
throw new Error(`Data length mismatch: expected ${width * height * 4}, got ${data.length}`);
|
|
226
|
+
}
|
|
227
|
+
const image = new Image();
|
|
228
|
+
image.imageData = { width, height, data: new Uint8Array(data) };
|
|
229
|
+
return image;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Resize the image
|
|
233
|
+
* @param options Resize options
|
|
234
|
+
* @returns This image instance for chaining
|
|
235
|
+
*/
|
|
236
|
+
resize(options) {
|
|
237
|
+
if (!this.imageData)
|
|
238
|
+
throw new Error("No image loaded");
|
|
239
|
+
const { width, height, method = "bilinear" } = options;
|
|
240
|
+
const { data: srcData, width: srcWidth, height: srcHeight } = this.imageData;
|
|
241
|
+
let resizedData;
|
|
242
|
+
if (method === "nearest") {
|
|
243
|
+
resizedData = resizeNearest(srcData, srcWidth, srcHeight, width, height);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
resizedData = resizeBilinear(srcData, srcWidth, srcHeight, width, height);
|
|
247
|
+
}
|
|
248
|
+
// Preserve metadata when resizing
|
|
249
|
+
const metadata = this.imageData.metadata;
|
|
250
|
+
this.imageData = {
|
|
251
|
+
width,
|
|
252
|
+
height,
|
|
253
|
+
data: resizedData,
|
|
254
|
+
metadata: metadata ? { ...metadata } : undefined,
|
|
255
|
+
};
|
|
256
|
+
// Update physical dimensions if DPI is set
|
|
257
|
+
if (this.imageData.metadata) {
|
|
258
|
+
if (metadata?.dpiX) {
|
|
259
|
+
this.imageData.metadata.physicalWidth = width / metadata.dpiX;
|
|
260
|
+
}
|
|
261
|
+
if (metadata?.dpiY) {
|
|
262
|
+
this.imageData.metadata.physicalHeight = height / metadata.dpiY;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return this;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Save the image to bytes in the specified format
|
|
269
|
+
* @param format Format name (e.g., "png", "jpeg", "webp", "ascii")
|
|
270
|
+
* @param options Optional format-specific encoding options
|
|
271
|
+
* @returns Encoded image bytes
|
|
272
|
+
*/
|
|
273
|
+
async save(format, options) {
|
|
274
|
+
if (!this.imageData)
|
|
275
|
+
throw new Error("No image loaded");
|
|
276
|
+
const handler = Image.formats.find((f) => f.name === format);
|
|
277
|
+
if (!handler) {
|
|
278
|
+
throw new Error(`Unsupported format: ${format}`);
|
|
279
|
+
}
|
|
280
|
+
return await handler.encode(this.imageData, options);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Clone this image
|
|
284
|
+
* @returns New image instance with copied data and metadata
|
|
285
|
+
*/
|
|
286
|
+
clone() {
|
|
287
|
+
if (!this.imageData)
|
|
288
|
+
throw new Error("No image loaded");
|
|
289
|
+
const image = new Image();
|
|
290
|
+
image.imageData = {
|
|
291
|
+
width: this.imageData.width,
|
|
292
|
+
height: this.imageData.height,
|
|
293
|
+
data: new Uint8Array(this.imageData.data),
|
|
294
|
+
metadata: this.imageData.metadata
|
|
295
|
+
? {
|
|
296
|
+
...this.imageData.metadata,
|
|
297
|
+
custom: this.imageData.metadata.custom
|
|
298
|
+
? { ...this.imageData.metadata.custom }
|
|
299
|
+
: undefined,
|
|
300
|
+
}
|
|
301
|
+
: undefined,
|
|
302
|
+
};
|
|
303
|
+
return image;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
Object.defineProperty(Image, "formats", {
|
|
307
|
+
enumerable: true,
|
|
308
|
+
configurable: true,
|
|
309
|
+
writable: true,
|
|
310
|
+
value: [
|
|
311
|
+
new PNGFormat(),
|
|
312
|
+
new JPEGFormat(),
|
|
313
|
+
new WebPFormat(),
|
|
314
|
+
new GIFFormat(),
|
|
315
|
+
new TIFFFormat(),
|
|
316
|
+
new BMPFormat(),
|
|
317
|
+
new RAWFormat(),
|
|
318
|
+
new ASCIIFormat(),
|
|
319
|
+
]
|
|
320
|
+
});
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image metadata
|
|
3
|
+
*/
|
|
4
|
+
export interface ImageMetadata {
|
|
5
|
+
/** Physical width in inches (derived from DPI if available) */
|
|
6
|
+
physicalWidth?: number;
|
|
7
|
+
/** Physical height in inches (derived from DPI if available) */
|
|
8
|
+
physicalHeight?: number;
|
|
9
|
+
/** Dots per inch (horizontal) */
|
|
10
|
+
dpiX?: number;
|
|
11
|
+
/** Dots per inch (vertical) */
|
|
12
|
+
dpiY?: number;
|
|
13
|
+
/** GPS latitude */
|
|
14
|
+
latitude?: number;
|
|
15
|
+
/** GPS longitude */
|
|
16
|
+
longitude?: number;
|
|
17
|
+
/** Image title */
|
|
18
|
+
title?: string;
|
|
19
|
+
/** Image description */
|
|
20
|
+
description?: string;
|
|
21
|
+
/** Image author */
|
|
22
|
+
author?: string;
|
|
23
|
+
/** Copyright information */
|
|
24
|
+
copyright?: string;
|
|
25
|
+
/** Creation date */
|
|
26
|
+
creationDate?: Date;
|
|
27
|
+
/** Custom metadata fields */
|
|
28
|
+
custom?: Record<string, string | number | boolean>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Frame-specific metadata for multi-frame images
|
|
32
|
+
*/
|
|
33
|
+
export interface FrameMetadata {
|
|
34
|
+
/** Frame delay in milliseconds (for animations) */
|
|
35
|
+
delay?: number;
|
|
36
|
+
/** Frame disposal method: how to treat the frame before rendering the next one */
|
|
37
|
+
disposal?: "none" | "background" | "previous";
|
|
38
|
+
/** X offset of frame within the canvas */
|
|
39
|
+
left?: number;
|
|
40
|
+
/** Y offset of frame within the canvas */
|
|
41
|
+
top?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Image data representation
|
|
45
|
+
*/
|
|
46
|
+
export interface ImageData {
|
|
47
|
+
/** Image width in pixels */
|
|
48
|
+
width: number;
|
|
49
|
+
/** Image height in pixels */
|
|
50
|
+
height: number;
|
|
51
|
+
/** Raw pixel data as RGBA (4 bytes per pixel) */
|
|
52
|
+
data: Uint8Array;
|
|
53
|
+
/** Optional metadata */
|
|
54
|
+
metadata?: ImageMetadata;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Single frame in a multi-frame image
|
|
58
|
+
*/
|
|
59
|
+
export interface ImageFrame {
|
|
60
|
+
/** Frame width in pixels */
|
|
61
|
+
width: number;
|
|
62
|
+
/** Frame height in pixels */
|
|
63
|
+
height: number;
|
|
64
|
+
/** Raw pixel data as RGBA (4 bytes per pixel) */
|
|
65
|
+
data: Uint8Array;
|
|
66
|
+
/** Optional frame-specific metadata */
|
|
67
|
+
frameMetadata?: FrameMetadata;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Multi-frame image data representation
|
|
71
|
+
*/
|
|
72
|
+
export interface MultiFrameImageData {
|
|
73
|
+
/** Canvas width in pixels (for GIF logical screen) */
|
|
74
|
+
width: number;
|
|
75
|
+
/** Canvas height in pixels (for GIF logical screen) */
|
|
76
|
+
height: number;
|
|
77
|
+
/** Array of frames */
|
|
78
|
+
frames: ImageFrame[];
|
|
79
|
+
/** Optional global metadata */
|
|
80
|
+
metadata?: ImageMetadata;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Options for resizing images
|
|
84
|
+
*/
|
|
85
|
+
export interface ResizeOptions {
|
|
86
|
+
/** Target width in pixels */
|
|
87
|
+
width: number;
|
|
88
|
+
/** Target height in pixels */
|
|
89
|
+
height: number;
|
|
90
|
+
/** Resize method (default: "bilinear") */
|
|
91
|
+
method?: "nearest" | "bilinear";
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Options for ASCII art encoding
|
|
95
|
+
*/
|
|
96
|
+
export interface ASCIIOptions {
|
|
97
|
+
/** Target width in characters (default: 80) */
|
|
98
|
+
width?: number;
|
|
99
|
+
/** Character set to use (default: "simple") */
|
|
100
|
+
charset?: "simple" | "extended" | "blocks" | "detailed";
|
|
101
|
+
/** Aspect ratio correction factor for terminal display (default: 0.5) */
|
|
102
|
+
aspectRatio?: number;
|
|
103
|
+
/** Whether to invert brightness (default: false) */
|
|
104
|
+
invert?: boolean;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Options for WebP encoding
|
|
108
|
+
*/
|
|
109
|
+
export interface WebPEncodeOptions {
|
|
110
|
+
/**
|
|
111
|
+
* Encoding quality (1-100, default: 90)
|
|
112
|
+
* - 100 = lossless (VP8L)
|
|
113
|
+
* - 1-99 = lossy (VP8 if OffscreenCanvas available, otherwise quantized VP8L)
|
|
114
|
+
*/
|
|
115
|
+
quality?: number;
|
|
116
|
+
/**
|
|
117
|
+
* Force lossless encoding even with quality < 100
|
|
118
|
+
* Uses VP8L format with optional color quantization based on quality
|
|
119
|
+
*/
|
|
120
|
+
lossless?: boolean;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Image format handler interface
|
|
124
|
+
*/
|
|
125
|
+
export interface ImageFormat {
|
|
126
|
+
/** Format name (e.g., "png", "jpeg", "webp") */
|
|
127
|
+
readonly name: string;
|
|
128
|
+
/** MIME type (e.g., "image/png") */
|
|
129
|
+
readonly mimeType: string;
|
|
130
|
+
/**
|
|
131
|
+
* Decode image data from bytes
|
|
132
|
+
* @param data Raw image data
|
|
133
|
+
* @returns Decoded image data
|
|
134
|
+
*/
|
|
135
|
+
decode(data: Uint8Array): Promise<ImageData>;
|
|
136
|
+
/**
|
|
137
|
+
* Encode image data to bytes
|
|
138
|
+
* @param imageData Image data to encode
|
|
139
|
+
* @param options Optional format-specific encoding options
|
|
140
|
+
* @returns Encoded image bytes
|
|
141
|
+
*/
|
|
142
|
+
encode(imageData: ImageData, options?: unknown): Promise<Uint8Array>;
|
|
143
|
+
/**
|
|
144
|
+
* Check if the given data is in this format
|
|
145
|
+
* @param data Raw data to check
|
|
146
|
+
* @returns true if the data matches this format
|
|
147
|
+
*/
|
|
148
|
+
canDecode(data: Uint8Array): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Decode all frames from multi-frame image (optional)
|
|
151
|
+
* @param data Raw image data
|
|
152
|
+
* @returns Decoded multi-frame image data
|
|
153
|
+
*/
|
|
154
|
+
decodeFrames?(data: Uint8Array): Promise<MultiFrameImageData>;
|
|
155
|
+
/**
|
|
156
|
+
* Encode multi-frame image data to bytes (optional)
|
|
157
|
+
* @param imageData Multi-frame image data to encode
|
|
158
|
+
* @param options Optional format-specific encoding options
|
|
159
|
+
* @returns Encoded image bytes
|
|
160
|
+
*/
|
|
161
|
+
encodeFrames?(imageData: MultiFrameImageData, options?: unknown): Promise<Uint8Array>;
|
|
162
|
+
/**
|
|
163
|
+
* Check if the format supports multiple frames
|
|
164
|
+
*/
|
|
165
|
+
supportsMultipleFrames?(): boolean;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/src/types.ts"],"names":[],"mappings":"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"}
|
package/esm/src/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure JavaScript GIF decoder implementation
|
|
3
|
+
* Supports GIF87a and GIF89a formats with LZW decompression
|
|
4
|
+
*/
|
|
5
|
+
interface GIFImage {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
data: Uint8Array;
|
|
9
|
+
}
|
|
10
|
+
interface GIFFrame {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
left: number;
|
|
14
|
+
top: number;
|
|
15
|
+
data: Uint8Array;
|
|
16
|
+
delay: number;
|
|
17
|
+
disposal: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class GIFDecoder {
|
|
20
|
+
private data;
|
|
21
|
+
private pos;
|
|
22
|
+
constructor(data: Uint8Array);
|
|
23
|
+
private readByte;
|
|
24
|
+
private readUint16LE;
|
|
25
|
+
private readBytes;
|
|
26
|
+
private readColorTable;
|
|
27
|
+
private readDataSubBlocks;
|
|
28
|
+
decode(): GIFImage;
|
|
29
|
+
/**
|
|
30
|
+
* Decode all frames from an animated GIF
|
|
31
|
+
* @returns Object with canvas dimensions and array of frames
|
|
32
|
+
*/
|
|
33
|
+
decodeAllFrames(): {
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
frames: GIFFrame[];
|
|
37
|
+
};
|
|
38
|
+
private indexedToRGBA;
|
|
39
|
+
private deinterlace;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=gif_decoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gif_decoder.d.ts","sourceRoot":"","sources":["../../../src/src/utils/gif_decoder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,GAAG,CAAS;gBAER,IAAI,EAAE,UAAU;IAK5B,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,iBAAiB;IAWzB,MAAM,IAAI,QAAQ;IAwHlB;;;OAGG;IACH,eAAe,IAAI;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,QAAQ,EAAE,CAAC;KACpB;IA0KD,OAAO,CAAC,aAAa;IAwErB,OAAO,CAAC,WAAW;CA0BpB"}
|