cross-image 0.4.1 → 0.4.3
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/README.md +77 -4
- package/esm/mod.d.ts +1 -1
- package/esm/src/formats/gif.d.ts +1 -0
- package/esm/src/formats/gif.js +19 -2
- package/esm/src/formats/jpeg.d.ts +21 -1
- package/esm/src/formats/jpeg.js +59 -0
- package/esm/src/image.d.ts +39 -1
- package/esm/src/image.js +68 -0
- package/esm/src/types.d.ts +63 -0
- package/esm/src/utils/gif_encoder.d.ts +13 -4
- package/esm/src/utils/gif_encoder.js +100 -97
- package/esm/src/utils/jpeg_decoder.d.ts +25 -2
- package/esm/src/utils/jpeg_decoder.js +101 -10
- package/esm/src/utils/jpeg_encoder.d.ts +19 -0
- package/esm/src/utils/jpeg_encoder.js +267 -0
- package/esm/src/utils/tiff_deflate.d.ts +0 -1
- package/esm/src/utils/tiff_deflate.js +0 -1
- package/package.json +1 -1
- package/script/mod.d.ts +1 -1
- package/script/src/formats/gif.d.ts +1 -0
- package/script/src/formats/gif.js +19 -2
- package/script/src/formats/jpeg.d.ts +21 -1
- package/script/src/formats/jpeg.js +59 -0
- package/script/src/image.d.ts +39 -1
- package/script/src/image.js +68 -0
- package/script/src/types.d.ts +63 -0
- package/script/src/utils/gif_encoder.d.ts +13 -4
- package/script/src/utils/gif_encoder.js +100 -97
- package/script/src/utils/jpeg_decoder.d.ts +25 -2
- package/script/src/utils/jpeg_decoder.js +101 -10
- package/script/src/utils/jpeg_encoder.d.ts +19 -0
- package/script/src/utils/jpeg_encoder.js +267 -0
- package/script/src/utils/tiff_deflate.d.ts +0 -1
- package/script/src/utils/tiff_deflate.js +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @cross/image
|
|
2
2
|
|
|
3
|
-
A pure JavaScript, dependency-free, cross-runtime image processing library for Deno, Node.js,
|
|
4
|
-
|
|
5
|
-
GIF, and more—all without native dependencies.
|
|
3
|
+
A pure JavaScript, dependency-free, cross-runtime image processing library for Deno, Node.js, Bun
|
|
4
|
+
and browsers. Decode, encode, manipulate, and process images in multiple formats including PNG,
|
|
5
|
+
JPEG, WebP, GIF, and more—all without native dependencies.
|
|
6
6
|
|
|
7
7
|
📚 **[Full Documentation](https://cross-image.56k.guru/)**
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ GIF, and more—all without native dependencies.
|
|
|
10
10
|
|
|
11
11
|
- 🚀 **Pure JavaScript** - No native dependencies
|
|
12
12
|
- 🔌 **Pluggable formats** - Easy to extend with custom formats
|
|
13
|
-
- 📦 **Cross-runtime** - Works on Deno, Node.js (18+), and
|
|
13
|
+
- 📦 **Cross-runtime** - Works on Deno, Node.js (18+), Bun and Browsers.
|
|
14
14
|
- 🎨 **Multiple formats** - PNG, APNG, JPEG, WebP, GIF, TIFF, BMP, ICO, DNG, PAM, PPM, PCX, ASCII,
|
|
15
15
|
HEIC, and AVIF support
|
|
16
16
|
- ✂️ **Image manipulation** - Resize, crop, composite, and more
|
|
@@ -284,6 +284,79 @@ const compressed = await image.encode("tiff", {
|
|
|
284
284
|
- **Full compression support**: CMYK works with all TIFF compression methods
|
|
285
285
|
- **Industry standard**: TIFF is the preferred format for CMYK images in print production
|
|
286
286
|
|
|
287
|
+
## JPEG Coefficient Extraction
|
|
288
|
+
|
|
289
|
+
The library provides advanced APIs for extracting and encoding JPEG quantized DCT coefficients,
|
|
290
|
+
enabling coefficient-domain steganography and other frequency-domain processing techniques.
|
|
291
|
+
|
|
292
|
+
### Extracting Coefficients
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
import { Image } from "jsr:@cross/image";
|
|
296
|
+
|
|
297
|
+
const data = await Deno.readFile("photo.jpg");
|
|
298
|
+
|
|
299
|
+
// Extract quantized DCT coefficients
|
|
300
|
+
const coefficients = await Image.extractCoefficients(data, "jpeg");
|
|
301
|
+
|
|
302
|
+
if (coefficients) {
|
|
303
|
+
console.log(`Image: ${coefficients.width}x${coefficients.height}`);
|
|
304
|
+
console.log(`Progressive: ${coefficients.isProgressive}`);
|
|
305
|
+
console.log(`Components: ${coefficients.components.length}`);
|
|
306
|
+
|
|
307
|
+
// Access coefficient blocks (Y, Cb, Cr components)
|
|
308
|
+
for (const comp of coefficients.components) {
|
|
309
|
+
console.log(`Component ${comp.id}: ${comp.blocks.length} block rows`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Modifying and Re-encoding Coefficients
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
import { Image } from "jsr:@cross/image";
|
|
318
|
+
|
|
319
|
+
const data = await Deno.readFile("input.jpg");
|
|
320
|
+
const coefficients = await Image.extractCoefficients(data, "jpeg");
|
|
321
|
+
|
|
322
|
+
if (coefficients) {
|
|
323
|
+
// Modify coefficients (e.g., for steganography)
|
|
324
|
+
for (const comp of coefficients.components) {
|
|
325
|
+
for (const row of comp.blocks) {
|
|
326
|
+
for (const block of row) {
|
|
327
|
+
// Modify AC coefficients (indices 1-63)
|
|
328
|
+
// DC coefficient is at index 0
|
|
329
|
+
// block is an Int32Array of 64 quantized DCT values in zigzag order
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Re-encode to JPEG
|
|
335
|
+
const encoded = await Image.encodeFromCoefficients(coefficients, "jpeg");
|
|
336
|
+
await Deno.writeFile("output.jpg", encoded);
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Coefficient Structure
|
|
341
|
+
|
|
342
|
+
The `JPEGQuantizedCoefficients` type provides:
|
|
343
|
+
|
|
344
|
+
- `width`, `height` - Image dimensions
|
|
345
|
+
- `isProgressive` - Whether the source was progressive JPEG
|
|
346
|
+
- `components` - Array of Y, Cb, Cr (or grayscale) component data
|
|
347
|
+
- `quantizationTables` - The quantization tables used
|
|
348
|
+
- `mcuWidth`, `mcuHeight` - MCU block dimensions
|
|
349
|
+
|
|
350
|
+
Each component contains `blocks[][]` where each block is an `Int32Array` of 64 quantized DCT
|
|
351
|
+
coefficients in zigzag order.
|
|
352
|
+
|
|
353
|
+
**Use Cases:**
|
|
354
|
+
|
|
355
|
+
- DCT-domain steganography (survives JPEG re-compression)
|
|
356
|
+
- Coefficient analysis and visualization
|
|
357
|
+
- Custom frequency-domain filtering
|
|
358
|
+
- Forensic analysis of JPEG compression artifacts
|
|
359
|
+
|
|
287
360
|
## Base64 / Data URLs
|
|
288
361
|
|
|
289
362
|
The library includes small utilities for working with base64 and `data:` URLs.
|
package/esm/mod.d.ts
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
* ```
|
|
44
44
|
*/
|
|
45
45
|
export { Image } from "./src/image.js";
|
|
46
|
-
export type { APNGEncoderOptions, ASCIIEncoderOptions, AVIFEncoderOptions, FrameMetadata, GIFEncoderOptions, HEICEncoderOptions, ImageData, ImageDecoderOptions, ImageFormat, ImageFrame, ImageMetadata, JPEGEncoderOptions, MultiFrameImageData, PNGEncoderOptions, ResizeOptions, TIFFEncoderOptions, WebPEncoderOptions, } from "./src/types.js";
|
|
46
|
+
export type { APNGEncoderOptions, ASCIIEncoderOptions, AVIFEncoderOptions, CoefficientData, FrameMetadata, GIFEncoderOptions, HEICEncoderOptions, ImageData, ImageDecoderOptions, ImageFormat, ImageFrame, ImageMetadata, JPEGComponentCoefficients, JPEGEncoderOptions, JPEGQuantizedCoefficients, MultiFrameImageData, PNGEncoderOptions, ResizeOptions, TIFFEncoderOptions, WebPEncoderOptions, } from "./src/types.js";
|
|
47
47
|
export { PNGFormat } from "./src/formats/png.js";
|
|
48
48
|
export { APNGFormat } from "./src/formats/apng.js";
|
|
49
49
|
export { JPEGFormat } from "./src/formats/jpeg.js";
|
package/esm/src/formats/gif.d.ts
CHANGED
|
@@ -48,6 +48,7 @@ export declare class GIFFormat implements ImageFormat {
|
|
|
48
48
|
* Encode multi-frame image data to animated GIF
|
|
49
49
|
*/
|
|
50
50
|
encodeFrames(imageData: MultiFrameImageData, options?: GIFEncoderOptions): Promise<Uint8Array>;
|
|
51
|
+
private mapDisposalMethodToNumber;
|
|
51
52
|
private mapDisposalMethod;
|
|
52
53
|
private decodeUsingRuntime;
|
|
53
54
|
private readDataSubBlocks;
|
package/esm/src/formats/gif.js
CHANGED
|
@@ -243,12 +243,29 @@ export class GIFFormat {
|
|
|
243
243
|
}
|
|
244
244
|
const encoder = new GIFEncoder(imageData.width, imageData.height);
|
|
245
245
|
for (const frame of imageData.frames) {
|
|
246
|
-
// Get delay from metadata (default to 100ms if not set)
|
|
247
246
|
const delay = frame.frameMetadata?.delay ?? 100;
|
|
248
|
-
encoder.addFrame(frame.data, delay
|
|
247
|
+
encoder.addFrame(frame.data, delay, {
|
|
248
|
+
left: frame.frameMetadata?.left ?? 0,
|
|
249
|
+
top: frame.frameMetadata?.top ?? 0,
|
|
250
|
+
width: frame.width,
|
|
251
|
+
height: frame.height,
|
|
252
|
+
disposal: this.mapDisposalMethodToNumber(frame.frameMetadata?.disposal),
|
|
253
|
+
});
|
|
249
254
|
}
|
|
250
255
|
return Promise.resolve(encoder.encode(options));
|
|
251
256
|
}
|
|
257
|
+
mapDisposalMethodToNumber(disposal) {
|
|
258
|
+
switch (disposal) {
|
|
259
|
+
case "none":
|
|
260
|
+
return 1;
|
|
261
|
+
case "background":
|
|
262
|
+
return 2;
|
|
263
|
+
case "previous":
|
|
264
|
+
return 3;
|
|
265
|
+
default:
|
|
266
|
+
return 0;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
252
269
|
mapDisposalMethod(disposal) {
|
|
253
270
|
switch (disposal) {
|
|
254
271
|
case 0:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ImageData, ImageDecoderOptions, ImageFormat, ImageMetadata, JPEGEncoderOptions } from "../types.js";
|
|
1
|
+
import type { CoefficientData, ImageData, ImageDecoderOptions, ImageFormat, ImageMetadata, JPEGEncoderOptions, JPEGQuantizedCoefficients } from "../types.js";
|
|
2
2
|
/**
|
|
3
3
|
* JPEG format handler
|
|
4
4
|
* Implements a basic JPEG decoder and encoder
|
|
@@ -42,6 +42,26 @@ export declare class JPEGFormat implements ImageFormat {
|
|
|
42
42
|
* Get the list of metadata fields supported by JPEG format
|
|
43
43
|
*/
|
|
44
44
|
getSupportedMetadata(): Array<keyof ImageMetadata>;
|
|
45
|
+
/**
|
|
46
|
+
* Extract quantized DCT coefficients from JPEG data
|
|
47
|
+
* These coefficients can be modified for steganography and re-encoded
|
|
48
|
+
* @param data Raw JPEG data
|
|
49
|
+
* @param options Decoder options
|
|
50
|
+
* @returns JPEGQuantizedCoefficients or undefined if extraction fails
|
|
51
|
+
*/
|
|
52
|
+
extractCoefficients(data: Uint8Array, options?: ImageDecoderOptions): Promise<JPEGQuantizedCoefficients | undefined>;
|
|
53
|
+
/**
|
|
54
|
+
* Type guard to check if coefficient data is JPEG format
|
|
55
|
+
*/
|
|
56
|
+
private isJPEGCoefficients;
|
|
57
|
+
/**
|
|
58
|
+
* Encode JPEG from quantized DCT coefficients
|
|
59
|
+
* Useful for steganography - modify coefficients and re-encode
|
|
60
|
+
* @param coeffs JPEG quantized coefficients
|
|
61
|
+
* @param options Encoding options
|
|
62
|
+
* @returns Encoded JPEG bytes
|
|
63
|
+
*/
|
|
64
|
+
encodeFromCoefficients(coeffs: CoefficientData, options?: JPEGEncoderOptions): Promise<Uint8Array>;
|
|
45
65
|
/**
|
|
46
66
|
* Extract metadata from JPEG data without fully decoding the pixel data
|
|
47
67
|
* This quickly parses JFIF and EXIF markers to extract metadata
|
package/esm/src/formats/jpeg.js
CHANGED
|
@@ -1072,6 +1072,65 @@ export class JPEGFormat {
|
|
|
1072
1072
|
"dpiY",
|
|
1073
1073
|
];
|
|
1074
1074
|
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Extract quantized DCT coefficients from JPEG data
|
|
1077
|
+
* These coefficients can be modified for steganography and re-encoded
|
|
1078
|
+
* @param data Raw JPEG data
|
|
1079
|
+
* @param options Decoder options
|
|
1080
|
+
* @returns JPEGQuantizedCoefficients or undefined if extraction fails
|
|
1081
|
+
*/
|
|
1082
|
+
async extractCoefficients(data, options) {
|
|
1083
|
+
if (!this.canDecode(data)) {
|
|
1084
|
+
return undefined;
|
|
1085
|
+
}
|
|
1086
|
+
try {
|
|
1087
|
+
// Force pure-JS decoding since runtime decoders don't expose coefficients
|
|
1088
|
+
const { JPEGDecoder } = await import("../utils/jpeg_decoder.js");
|
|
1089
|
+
const decoder = new JPEGDecoder(data, {
|
|
1090
|
+
tolerantDecoding: options?.tolerantDecoding ?? true,
|
|
1091
|
+
onWarning: options?.onWarning,
|
|
1092
|
+
extractCoefficients: true,
|
|
1093
|
+
});
|
|
1094
|
+
// Decode to extract coefficients
|
|
1095
|
+
decoder.decode();
|
|
1096
|
+
// Get the quantized coefficients
|
|
1097
|
+
return decoder.getQuantizedCoefficients();
|
|
1098
|
+
}
|
|
1099
|
+
catch (error) {
|
|
1100
|
+
if (options?.onWarning) {
|
|
1101
|
+
options.onWarning(`Failed to extract JPEG coefficients: ${error}`, error);
|
|
1102
|
+
}
|
|
1103
|
+
return undefined;
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Type guard to check if coefficient data is JPEG format
|
|
1108
|
+
*/
|
|
1109
|
+
isJPEGCoefficients(coeffs) {
|
|
1110
|
+
return ("format" in coeffs &&
|
|
1111
|
+
coeffs.format === "jpeg" &&
|
|
1112
|
+
"components" in coeffs &&
|
|
1113
|
+
"quantizationTables" in coeffs &&
|
|
1114
|
+
"isProgressive" in coeffs);
|
|
1115
|
+
}
|
|
1116
|
+
/**
|
|
1117
|
+
* Encode JPEG from quantized DCT coefficients
|
|
1118
|
+
* Useful for steganography - modify coefficients and re-encode
|
|
1119
|
+
* @param coeffs JPEG quantized coefficients
|
|
1120
|
+
* @param options Encoding options
|
|
1121
|
+
* @returns Encoded JPEG bytes
|
|
1122
|
+
*/
|
|
1123
|
+
async encodeFromCoefficients(coeffs, options) {
|
|
1124
|
+
if (!this.isJPEGCoefficients(coeffs)) {
|
|
1125
|
+
throw new Error("Invalid coefficient format for JPEG");
|
|
1126
|
+
}
|
|
1127
|
+
const { JPEGEncoder } = await import("../utils/jpeg_encoder.js");
|
|
1128
|
+
const encoder = new JPEGEncoder({
|
|
1129
|
+
quality: options?.quality,
|
|
1130
|
+
progressive: options?.progressive ?? coeffs.isProgressive,
|
|
1131
|
+
});
|
|
1132
|
+
return encoder.encodeFromCoefficients(coeffs, options);
|
|
1133
|
+
}
|
|
1075
1134
|
/**
|
|
1076
1135
|
* Extract metadata from JPEG data without fully decoding the pixel data
|
|
1077
1136
|
* This quickly parses JFIF and EXIF markers to extract metadata
|
package/esm/src/image.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ImageDecoderOptions, ImageFormat, ImageMetadata, MultiFrameImageData, ResizeOptions } from "./types.js";
|
|
1
|
+
import type { CoefficientData, ImageDecoderOptions, ImageFormat, ImageMetadata, MultiFrameImageData, ResizeOptions } from "./types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Main Image class for reading, manipulating, and saving images
|
|
4
4
|
*/
|
|
@@ -98,6 +98,44 @@ export declare class Image {
|
|
|
98
98
|
* @returns Metadata extracted from the image, or undefined if extraction fails or format is unsupported
|
|
99
99
|
*/
|
|
100
100
|
static extractMetadata(data: Uint8Array, format?: string): Promise<ImageMetadata | undefined>;
|
|
101
|
+
/**
|
|
102
|
+
* Extract coefficients from encoded image data
|
|
103
|
+
* For JPEG, this returns quantized DCT coefficients that can be modified for steganography
|
|
104
|
+
* and re-encoded using encodeFromCoefficients()
|
|
105
|
+
* @param data Raw image data
|
|
106
|
+
* @param format Optional format hint (e.g., "jpeg")
|
|
107
|
+
* @param options Optional decoder options
|
|
108
|
+
* @returns Format-specific coefficient structure or undefined if not supported
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* // Extract JPEG coefficients for steganography
|
|
113
|
+
* const coeffs = await Image.extractCoefficients(jpegData, "jpeg");
|
|
114
|
+
* if (coeffs) {
|
|
115
|
+
* // Modify coefficients for steganography...
|
|
116
|
+
* const modified = await Image.encodeFromCoefficients(coeffs, "jpeg");
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
static extractCoefficients(data: Uint8Array, format?: string, options?: ImageDecoderOptions): Promise<CoefficientData | undefined>;
|
|
121
|
+
/**
|
|
122
|
+
* Encode image from coefficients
|
|
123
|
+
* For JPEG, accepts quantized DCT coefficients and produces a valid JPEG file
|
|
124
|
+
* Useful for steganography where coefficients are extracted, modified, and re-encoded
|
|
125
|
+
* @param coeffs Format-specific coefficient structure
|
|
126
|
+
* @param format Optional format hint (auto-detected from coeffs.format if available)
|
|
127
|
+
* @param options Optional format-specific encoding options
|
|
128
|
+
* @returns Encoded image bytes
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* // Re-encode modified JPEG coefficients
|
|
133
|
+
* const coeffs = await Image.extractCoefficients(jpegData, "jpeg");
|
|
134
|
+
* // Modify coefficients...
|
|
135
|
+
* const encoded = await Image.encodeFromCoefficients(coeffs, "jpeg");
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
static encodeFromCoefficients(coeffs: CoefficientData, format?: string, options?: unknown): Promise<Uint8Array>;
|
|
101
139
|
/**
|
|
102
140
|
* Read an image from bytes
|
|
103
141
|
* @deprecated Use `decode()` instead. This method will be removed in a future version.
|
package/esm/src/image.js
CHANGED
|
@@ -230,6 +230,74 @@ export class Image {
|
|
|
230
230
|
}
|
|
231
231
|
return undefined;
|
|
232
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Extract coefficients from encoded image data
|
|
235
|
+
* For JPEG, this returns quantized DCT coefficients that can be modified for steganography
|
|
236
|
+
* and re-encoded using encodeFromCoefficients()
|
|
237
|
+
* @param data Raw image data
|
|
238
|
+
* @param format Optional format hint (e.g., "jpeg")
|
|
239
|
+
* @param options Optional decoder options
|
|
240
|
+
* @returns Format-specific coefficient structure or undefined if not supported
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```ts
|
|
244
|
+
* // Extract JPEG coefficients for steganography
|
|
245
|
+
* const coeffs = await Image.extractCoefficients(jpegData, "jpeg");
|
|
246
|
+
* if (coeffs) {
|
|
247
|
+
* // Modify coefficients for steganography...
|
|
248
|
+
* const modified = await Image.encodeFromCoefficients(coeffs, "jpeg");
|
|
249
|
+
* }
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
static async extractCoefficients(data, format, options) {
|
|
253
|
+
// Try specified format first
|
|
254
|
+
if (format) {
|
|
255
|
+
const handler = Image.formats.find((f) => f.name === format);
|
|
256
|
+
if (handler && handler.canDecode(data) && handler.extractCoefficients) {
|
|
257
|
+
return await handler.extractCoefficients(data, options);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Auto-detect format
|
|
261
|
+
for (const handler of Image.formats) {
|
|
262
|
+
if (handler.canDecode(data) && handler.extractCoefficients) {
|
|
263
|
+
return await handler.extractCoefficients(data, options);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Encode image from coefficients
|
|
270
|
+
* For JPEG, accepts quantized DCT coefficients and produces a valid JPEG file
|
|
271
|
+
* Useful for steganography where coefficients are extracted, modified, and re-encoded
|
|
272
|
+
* @param coeffs Format-specific coefficient structure
|
|
273
|
+
* @param format Optional format hint (auto-detected from coeffs.format if available)
|
|
274
|
+
* @param options Optional format-specific encoding options
|
|
275
|
+
* @returns Encoded image bytes
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```ts
|
|
279
|
+
* // Re-encode modified JPEG coefficients
|
|
280
|
+
* const coeffs = await Image.extractCoefficients(jpegData, "jpeg");
|
|
281
|
+
* // Modify coefficients...
|
|
282
|
+
* const encoded = await Image.encodeFromCoefficients(coeffs, "jpeg");
|
|
283
|
+
* ```
|
|
284
|
+
*/
|
|
285
|
+
static async encodeFromCoefficients(coeffs, format, options) {
|
|
286
|
+
// Detect format from coefficient structure or use provided format
|
|
287
|
+
const detectedFormat = format ??
|
|
288
|
+
coeffs.format;
|
|
289
|
+
if (!detectedFormat) {
|
|
290
|
+
throw new Error("Format must be specified or present in coefficient data");
|
|
291
|
+
}
|
|
292
|
+
const handler = Image.formats.find((f) => f.name === detectedFormat);
|
|
293
|
+
if (!handler) {
|
|
294
|
+
throw new Error(`Unknown format: ${detectedFormat}`);
|
|
295
|
+
}
|
|
296
|
+
if (!handler.encodeFromCoefficients) {
|
|
297
|
+
throw new Error(`Format ${detectedFormat} does not support encoding from coefficients`);
|
|
298
|
+
}
|
|
299
|
+
return await handler.encodeFromCoefficients(coeffs, options);
|
|
300
|
+
}
|
|
233
301
|
/**
|
|
234
302
|
* Read an image from bytes
|
|
235
303
|
* @deprecated Use `decode()` instead. This method will be removed in a future version.
|
package/esm/src/types.d.ts
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JPEG quantized DCT coefficients for steganography and advanced processing
|
|
3
|
+
* Contains the frequency-domain representation of the image
|
|
4
|
+
*/
|
|
5
|
+
export interface JPEGQuantizedCoefficients {
|
|
6
|
+
/** Format identifier */
|
|
7
|
+
format: "jpeg";
|
|
8
|
+
/** Image width in pixels */
|
|
9
|
+
width: number;
|
|
10
|
+
/** Image height in pixels */
|
|
11
|
+
height: number;
|
|
12
|
+
/** Whether the JPEG is progressive */
|
|
13
|
+
isProgressive: boolean;
|
|
14
|
+
/** Component data (Y, Cb, Cr for color images) */
|
|
15
|
+
components: JPEGComponentCoefficients[];
|
|
16
|
+
/** Quantization tables used (indexed by table ID) */
|
|
17
|
+
quantizationTables: (Uint8Array | number[])[];
|
|
18
|
+
/** MCU width (number of 8x8 blocks horizontally) */
|
|
19
|
+
mcuWidth: number;
|
|
20
|
+
/** MCU height (number of 8x8 blocks vertically) */
|
|
21
|
+
mcuHeight: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Coefficients for a single JPEG component (Y, Cb, or Cr)
|
|
25
|
+
*/
|
|
26
|
+
export interface JPEGComponentCoefficients {
|
|
27
|
+
/** Component ID (1=Y, 2=Cb, 3=Cr typically) */
|
|
28
|
+
id: number;
|
|
29
|
+
/** Horizontal sampling factor */
|
|
30
|
+
h: number;
|
|
31
|
+
/** Vertical sampling factor */
|
|
32
|
+
v: number;
|
|
33
|
+
/** Quantization table index */
|
|
34
|
+
qTable: number;
|
|
35
|
+
/**
|
|
36
|
+
* Quantized DCT coefficient blocks
|
|
37
|
+
* blocks[blockRow][blockCol] contains a 64-element array in zigzag order
|
|
38
|
+
* Coefficients are quantized (divided by quantization table values)
|
|
39
|
+
*/
|
|
40
|
+
blocks: Int32Array[][];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Union type for coefficient data from different formats
|
|
44
|
+
* Currently only JPEG is supported, but this allows for future extension
|
|
45
|
+
*/
|
|
46
|
+
export type CoefficientData = JPEGQuantizedCoefficients;
|
|
1
47
|
/**
|
|
2
48
|
* Image metadata
|
|
3
49
|
*/
|
|
@@ -339,5 +385,22 @@ export interface ImageFormat {
|
|
|
339
385
|
* @returns Metadata extracted from the image, or undefined if extraction fails
|
|
340
386
|
*/
|
|
341
387
|
extractMetadata?(data: Uint8Array): Promise<ImageMetadata | undefined>;
|
|
388
|
+
/**
|
|
389
|
+
* Extract coefficients from encoded image data (optional)
|
|
390
|
+
* For JPEG, this returns quantized DCT coefficients
|
|
391
|
+
* Useful for steganography and advanced image processing
|
|
392
|
+
* @param data Raw image data
|
|
393
|
+
* @param options Decoder options
|
|
394
|
+
* @returns Format-specific coefficient structure or undefined if not supported
|
|
395
|
+
*/
|
|
396
|
+
extractCoefficients?(data: Uint8Array, options?: ImageDecoderOptions): Promise<CoefficientData | undefined>;
|
|
397
|
+
/**
|
|
398
|
+
* Encode image from coefficients (optional)
|
|
399
|
+
* For JPEG, accepts quantized DCT coefficients and produces a valid JPEG
|
|
400
|
+
* @param coeffs Format-specific coefficient structure
|
|
401
|
+
* @param options Format-specific encoding options
|
|
402
|
+
* @returns Encoded image bytes
|
|
403
|
+
*/
|
|
404
|
+
encodeFromCoefficients?(coeffs: CoefficientData, options?: unknown): Promise<Uint8Array>;
|
|
342
405
|
}
|
|
343
406
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -3,11 +3,20 @@
|
|
|
3
3
|
* Supports GIF89a format with LZW compression
|
|
4
4
|
*/
|
|
5
5
|
export declare class GIFEncoder {
|
|
6
|
-
private
|
|
7
|
-
private
|
|
6
|
+
private canvasWidth;
|
|
7
|
+
private canvasHeight;
|
|
8
8
|
private frames;
|
|
9
9
|
constructor(width: number, height: number, data?: Uint8Array);
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Add a frame with optional metadata for partial frame support
|
|
12
|
+
*/
|
|
13
|
+
addFrame(data: Uint8Array, delay?: number, options?: {
|
|
14
|
+
left?: number;
|
|
15
|
+
top?: number;
|
|
16
|
+
width?: number;
|
|
17
|
+
height?: number;
|
|
18
|
+
disposal?: number;
|
|
19
|
+
}): void;
|
|
11
20
|
private writeBytes;
|
|
12
21
|
private writeUint16LE;
|
|
13
22
|
private writeString;
|
|
@@ -20,7 +29,7 @@ export declare class GIFEncoder {
|
|
|
20
29
|
*/
|
|
21
30
|
private quantizeChannel;
|
|
22
31
|
/**
|
|
23
|
-
* Quantize RGBA image to 256 colors
|
|
32
|
+
* Quantize RGBA image to 256 colors with transparency support
|
|
24
33
|
*/
|
|
25
34
|
private quantize;
|
|
26
35
|
private nextPowerOf2;
|