cross-image 0.4.0 → 0.4.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/README.md +186 -5
- package/esm/mod.d.ts +3 -1
- package/esm/mod.js +2 -0
- package/esm/src/formats/apng.d.ts +5 -3
- package/esm/src/formats/apng.js +11 -4
- package/esm/src/formats/avif.d.ts +2 -2
- package/esm/src/formats/avif.js +11 -1
- package/esm/src/formats/gif.d.ts +3 -3
- package/esm/src/formats/gif.js +4 -4
- package/esm/src/formats/heic.d.ts +2 -2
- package/esm/src/formats/heic.js +11 -1
- package/esm/src/formats/jpeg.d.ts +21 -1
- package/esm/src/formats/jpeg.js +59 -0
- package/esm/src/formats/png.d.ts +3 -2
- package/esm/src/formats/png.js +8 -2
- package/esm/src/formats/png_base.d.ts +42 -1
- package/esm/src/formats/png_base.js +198 -5
- package/esm/src/formats/tiff.js +76 -6
- package/esm/src/image.d.ts +54 -1
- package/esm/src/image.js +97 -1
- package/esm/src/types.d.ts +129 -0
- package/esm/src/utils/base64.d.ts +32 -0
- package/esm/src/utils/base64.js +173 -0
- package/esm/src/utils/gif_encoder.d.ts +3 -1
- package/esm/src/utils/gif_encoder.js +4 -2
- package/esm/src/utils/image_processing.d.ts +31 -0
- package/esm/src/utils/image_processing.js +88 -0
- 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/package.json +1 -1
- package/script/mod.d.ts +3 -1
- package/script/mod.js +11 -1
- package/script/src/formats/apng.d.ts +5 -3
- package/script/src/formats/apng.js +11 -4
- package/script/src/formats/avif.d.ts +2 -2
- package/script/src/formats/avif.js +11 -1
- package/script/src/formats/gif.d.ts +3 -3
- package/script/src/formats/gif.js +4 -4
- package/script/src/formats/heic.d.ts +2 -2
- package/script/src/formats/heic.js +11 -1
- package/script/src/formats/jpeg.d.ts +21 -1
- package/script/src/formats/jpeg.js +59 -0
- package/script/src/formats/png.d.ts +3 -2
- package/script/src/formats/png.js +8 -2
- package/script/src/formats/png_base.d.ts +42 -1
- package/script/src/formats/png_base.js +198 -5
- package/script/src/formats/tiff.js +76 -6
- package/script/src/image.d.ts +54 -1
- package/script/src/image.js +96 -0
- package/script/src/types.d.ts +129 -0
- package/script/src/utils/base64.d.ts +32 -0
- package/script/src/utils/base64.js +179 -0
- package/script/src/utils/gif_encoder.d.ts +3 -1
- package/script/src/utils/gif_encoder.js +4 -2
- package/script/src/utils/image_processing.d.ts +31 -0
- package/script/src/utils/image_processing.js +92 -0
- 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
|
@@ -5,6 +5,7 @@ const tiff_lzw_js_1 = require("../utils/tiff_lzw.js");
|
|
|
5
5
|
const tiff_packbits_js_1 = require("../utils/tiff_packbits.js");
|
|
6
6
|
const tiff_deflate_js_1 = require("../utils/tiff_deflate.js");
|
|
7
7
|
const security_js_1 = require("../utils/security.js");
|
|
8
|
+
const image_processing_js_1 = require("../utils/image_processing.js");
|
|
8
9
|
// Constants for unit conversions
|
|
9
10
|
const DEFAULT_DPI = 72;
|
|
10
11
|
/**
|
|
@@ -139,6 +140,7 @@ class TIFFFormat {
|
|
|
139
140
|
const compression = opts?.compression ?? "none";
|
|
140
141
|
const grayscale = opts?.grayscale ?? false;
|
|
141
142
|
const rgb = opts?.rgb ?? false;
|
|
143
|
+
const cmyk = opts?.cmyk ?? false;
|
|
142
144
|
// Convert RGBA to grayscale if requested
|
|
143
145
|
let sourceData;
|
|
144
146
|
let samplesPerPixel;
|
|
@@ -153,6 +155,16 @@ class TIFFFormat {
|
|
|
153
155
|
sourceData[i] = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
|
|
154
156
|
}
|
|
155
157
|
}
|
|
158
|
+
else if (cmyk) {
|
|
159
|
+
// Convert RGBA to CMYK
|
|
160
|
+
const cmykData = (0, image_processing_js_1.rgbaToCmyk)(data);
|
|
161
|
+
sourceData = new Uint8Array(width * height * 4);
|
|
162
|
+
samplesPerPixel = 4;
|
|
163
|
+
// Convert Float32Array CMYK (0-1) to Uint8Array (0-255)
|
|
164
|
+
for (let i = 0; i < cmykData.length; i++) {
|
|
165
|
+
sourceData[i] = Math.round(cmykData[i] * 255);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
156
168
|
else if (rgb) {
|
|
157
169
|
// Convert RGBA to RGB (strip alpha channel)
|
|
158
170
|
sourceData = new Uint8Array(width * height * 3);
|
|
@@ -244,8 +256,8 @@ class TIFFFormat {
|
|
|
244
256
|
}
|
|
245
257
|
// Compression (0x0103) - 1 = uncompressed, 5 = LZW
|
|
246
258
|
this.writeIFDEntry(result, 0x0103, 3, 1, compressionCode);
|
|
247
|
-
// PhotometricInterpretation (0x0106) - 1 = BlackIsZero (grayscale), 2 = RGB
|
|
248
|
-
this.writeIFDEntry(result, 0x0106, 3, 1, grayscale ? 1 : 2);
|
|
259
|
+
// PhotometricInterpretation (0x0106) - 1 = BlackIsZero (grayscale), 2 = RGB, 5 = CMYK
|
|
260
|
+
this.writeIFDEntry(result, 0x0106, 3, 1, grayscale ? 1 : (cmyk ? 5 : 2));
|
|
249
261
|
// StripOffsets (0x0111)
|
|
250
262
|
this.writeIFDEntry(result, 0x0111, 4, 1, 8);
|
|
251
263
|
// SamplesPerPixel (0x0115) - 1 for grayscale, 3 for RGB, 4 for RGBA
|
|
@@ -795,14 +807,16 @@ class TIFFFormat {
|
|
|
795
807
|
}
|
|
796
808
|
// Check photometric interpretation
|
|
797
809
|
const photometric = this.getIFDValue(data, ifdOffset, 0x0106, isLittleEndian);
|
|
798
|
-
if (photometric !== 0 && photometric !== 1 && photometric !== 2
|
|
799
|
-
|
|
810
|
+
if (photometric !== 0 && photometric !== 1 && photometric !== 2 &&
|
|
811
|
+
photometric !== 5) {
|
|
812
|
+
// Support: 0 = WhiteIsZero, 1 = BlackIsZero, 2 = RGB, 5 = CMYK
|
|
800
813
|
return null;
|
|
801
814
|
}
|
|
802
815
|
// Get samples per pixel
|
|
803
816
|
const samplesPerPixel = this.getIFDValue(data, ifdOffset, 0x0115, isLittleEndian);
|
|
804
817
|
// For grayscale (photometric 0 or 1), expect 1 sample per pixel
|
|
805
818
|
// For RGB, expect 3 or 4 samples per pixel
|
|
819
|
+
// For CMYK, expect 4 samples per pixel
|
|
806
820
|
if (!samplesPerPixel) {
|
|
807
821
|
return null;
|
|
808
822
|
}
|
|
@@ -814,6 +828,10 @@ class TIFFFormat {
|
|
|
814
828
|
// RGB requires 3 or 4 samples per pixel
|
|
815
829
|
return null;
|
|
816
830
|
}
|
|
831
|
+
if (photometric === 5 && samplesPerPixel !== 4) {
|
|
832
|
+
// CMYK requires 4 samples per pixel
|
|
833
|
+
return null;
|
|
834
|
+
}
|
|
817
835
|
// Get strip offset
|
|
818
836
|
const stripOffset = this.getIFDValue(data, ifdOffset, 0x0111, isLittleEndian);
|
|
819
837
|
if (!stripOffset || stripOffset >= data.length) {
|
|
@@ -871,6 +889,29 @@ class TIFFFormat {
|
|
|
871
889
|
}
|
|
872
890
|
}
|
|
873
891
|
}
|
|
892
|
+
else if (photometric === 5) {
|
|
893
|
+
// CMYK image - convert to RGB
|
|
894
|
+
for (let y = 0; y < height; y++) {
|
|
895
|
+
for (let x = 0; x < width; x++) {
|
|
896
|
+
const dstIdx = (y * width + x) * 4;
|
|
897
|
+
if (srcPos + 4 > pixelData.length) {
|
|
898
|
+
return null; // Not enough data
|
|
899
|
+
}
|
|
900
|
+
// TIFF stores CMYK in order, values are 0-255
|
|
901
|
+
// Convert to 0-1 range for conversion
|
|
902
|
+
const c = pixelData[srcPos++] / 255;
|
|
903
|
+
const m = pixelData[srcPos++] / 255;
|
|
904
|
+
const yVal = pixelData[srcPos++] / 255;
|
|
905
|
+
const k = pixelData[srcPos++] / 255;
|
|
906
|
+
// Convert CMYK to RGB
|
|
907
|
+
const [r, g, b] = (0, image_processing_js_1.cmykToRgb)(c, m, yVal, k);
|
|
908
|
+
rgba[dstIdx] = r; // R
|
|
909
|
+
rgba[dstIdx + 1] = g; // G
|
|
910
|
+
rgba[dstIdx + 2] = b; // B
|
|
911
|
+
rgba[dstIdx + 3] = 255; // A (opaque)
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
874
915
|
else {
|
|
875
916
|
// RGB/RGBA image
|
|
876
917
|
for (let y = 0; y < height; y++) {
|
|
@@ -903,14 +944,16 @@ class TIFFFormat {
|
|
|
903
944
|
}
|
|
904
945
|
// Check photometric interpretation
|
|
905
946
|
const photometric = this.getIFDValue(data, ifdOffset, 0x0106, isLittleEndian);
|
|
906
|
-
if (photometric !== 0 && photometric !== 1 && photometric !== 2
|
|
907
|
-
|
|
947
|
+
if (photometric !== 0 && photometric !== 1 && photometric !== 2 &&
|
|
948
|
+
photometric !== 5) {
|
|
949
|
+
// Support: 0 = WhiteIsZero, 1 = BlackIsZero, 2 = RGB, 5 = CMYK
|
|
908
950
|
return null;
|
|
909
951
|
}
|
|
910
952
|
// Get samples per pixel
|
|
911
953
|
const samplesPerPixel = this.getIFDValue(data, ifdOffset, 0x0115, isLittleEndian);
|
|
912
954
|
// For grayscale (photometric 0 or 1), expect 1 sample per pixel
|
|
913
955
|
// For RGB, expect 3 or 4 samples per pixel
|
|
956
|
+
// For CMYK, expect 4 samples per pixel
|
|
914
957
|
if (!samplesPerPixel) {
|
|
915
958
|
return null;
|
|
916
959
|
}
|
|
@@ -922,6 +965,10 @@ class TIFFFormat {
|
|
|
922
965
|
// RGB requires 3 or 4 samples per pixel
|
|
923
966
|
return null;
|
|
924
967
|
}
|
|
968
|
+
if (photometric === 5 && samplesPerPixel !== 4) {
|
|
969
|
+
// CMYK requires 4 samples per pixel
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
925
972
|
// Get strip offset
|
|
926
973
|
const stripOffset = this.getIFDValue(data, ifdOffset, 0x0111, isLittleEndian);
|
|
927
974
|
if (!stripOffset || stripOffset >= data.length) {
|
|
@@ -979,6 +1026,29 @@ class TIFFFormat {
|
|
|
979
1026
|
}
|
|
980
1027
|
}
|
|
981
1028
|
}
|
|
1029
|
+
else if (photometric === 5) {
|
|
1030
|
+
// CMYK image - convert to RGB
|
|
1031
|
+
for (let y = 0; y < height; y++) {
|
|
1032
|
+
for (let x = 0; x < width; x++) {
|
|
1033
|
+
const dstIdx = (y * width + x) * 4;
|
|
1034
|
+
if (srcPos + 4 > pixelData.length) {
|
|
1035
|
+
return null; // Not enough data
|
|
1036
|
+
}
|
|
1037
|
+
// TIFF stores CMYK in order, values are 0-255
|
|
1038
|
+
// Convert to 0-1 range for conversion
|
|
1039
|
+
const c = pixelData[srcPos++] / 255;
|
|
1040
|
+
const m = pixelData[srcPos++] / 255;
|
|
1041
|
+
const yVal = pixelData[srcPos++] / 255;
|
|
1042
|
+
const k = pixelData[srcPos++] / 255;
|
|
1043
|
+
// Convert CMYK to RGB
|
|
1044
|
+
const [r, g, b] = (0, image_processing_js_1.cmykToRgb)(c, m, yVal, k);
|
|
1045
|
+
rgba[dstIdx] = r; // R
|
|
1046
|
+
rgba[dstIdx + 1] = g; // G
|
|
1047
|
+
rgba[dstIdx + 2] = b; // B
|
|
1048
|
+
rgba[dstIdx + 3] = 255; // A (opaque)
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
982
1052
|
else {
|
|
983
1053
|
// RGB/RGBA image
|
|
984
1054
|
for (let y = 0; y < height; y++) {
|
package/script/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.
|
|
@@ -350,5 +388,20 @@ export declare class Image {
|
|
|
350
388
|
* @returns This image instance for chaining
|
|
351
389
|
*/
|
|
352
390
|
flipVertical(): this;
|
|
391
|
+
/**
|
|
392
|
+
* Convert the image to CMYK color space
|
|
393
|
+
* Returns a Float32Array with 4 values per pixel (C, M, Y, K) in 0-1 range
|
|
394
|
+
* @returns CMYK image data as Float32Array
|
|
395
|
+
*/
|
|
396
|
+
toCMYK(): Float32Array;
|
|
397
|
+
/**
|
|
398
|
+
* Create an Image from CMYK data
|
|
399
|
+
* @param cmykData CMYK image data (4 values per pixel in 0-1 range)
|
|
400
|
+
* @param width Image width
|
|
401
|
+
* @param height Image height
|
|
402
|
+
* @param alpha Optional alpha value for all pixels (0-255, default: 255)
|
|
403
|
+
* @returns New Image instance
|
|
404
|
+
*/
|
|
405
|
+
static fromCMYK(cmykData: Float32Array, width: number, height: number, alpha?: number): Image;
|
|
353
406
|
}
|
|
354
407
|
//# sourceMappingURL=image.d.ts.map
|
package/script/src/image.js
CHANGED
|
@@ -233,6 +233,74 @@ class Image {
|
|
|
233
233
|
}
|
|
234
234
|
return undefined;
|
|
235
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Extract coefficients from encoded image data
|
|
238
|
+
* For JPEG, this returns quantized DCT coefficients that can be modified for steganography
|
|
239
|
+
* and re-encoded using encodeFromCoefficients()
|
|
240
|
+
* @param data Raw image data
|
|
241
|
+
* @param format Optional format hint (e.g., "jpeg")
|
|
242
|
+
* @param options Optional decoder options
|
|
243
|
+
* @returns Format-specific coefficient structure or undefined if not supported
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```ts
|
|
247
|
+
* // Extract JPEG coefficients for steganography
|
|
248
|
+
* const coeffs = await Image.extractCoefficients(jpegData, "jpeg");
|
|
249
|
+
* if (coeffs) {
|
|
250
|
+
* // Modify coefficients for steganography...
|
|
251
|
+
* const modified = await Image.encodeFromCoefficients(coeffs, "jpeg");
|
|
252
|
+
* }
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
static async extractCoefficients(data, format, options) {
|
|
256
|
+
// Try specified format first
|
|
257
|
+
if (format) {
|
|
258
|
+
const handler = Image.formats.find((f) => f.name === format);
|
|
259
|
+
if (handler && handler.canDecode(data) && handler.extractCoefficients) {
|
|
260
|
+
return await handler.extractCoefficients(data, options);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Auto-detect format
|
|
264
|
+
for (const handler of Image.formats) {
|
|
265
|
+
if (handler.canDecode(data) && handler.extractCoefficients) {
|
|
266
|
+
return await handler.extractCoefficients(data, options);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Encode image from coefficients
|
|
273
|
+
* For JPEG, accepts quantized DCT coefficients and produces a valid JPEG file
|
|
274
|
+
* Useful for steganography where coefficients are extracted, modified, and re-encoded
|
|
275
|
+
* @param coeffs Format-specific coefficient structure
|
|
276
|
+
* @param format Optional format hint (auto-detected from coeffs.format if available)
|
|
277
|
+
* @param options Optional format-specific encoding options
|
|
278
|
+
* @returns Encoded image bytes
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```ts
|
|
282
|
+
* // Re-encode modified JPEG coefficients
|
|
283
|
+
* const coeffs = await Image.extractCoefficients(jpegData, "jpeg");
|
|
284
|
+
* // Modify coefficients...
|
|
285
|
+
* const encoded = await Image.encodeFromCoefficients(coeffs, "jpeg");
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
288
|
+
static async encodeFromCoefficients(coeffs, format, options) {
|
|
289
|
+
// Detect format from coefficient structure or use provided format
|
|
290
|
+
const detectedFormat = format ??
|
|
291
|
+
coeffs.format;
|
|
292
|
+
if (!detectedFormat) {
|
|
293
|
+
throw new Error("Format must be specified or present in coefficient data");
|
|
294
|
+
}
|
|
295
|
+
const handler = Image.formats.find((f) => f.name === detectedFormat);
|
|
296
|
+
if (!handler) {
|
|
297
|
+
throw new Error(`Unknown format: ${detectedFormat}`);
|
|
298
|
+
}
|
|
299
|
+
if (!handler.encodeFromCoefficients) {
|
|
300
|
+
throw new Error(`Format ${detectedFormat} does not support encoding from coefficients`);
|
|
301
|
+
}
|
|
302
|
+
return await handler.encodeFromCoefficients(coeffs, options);
|
|
303
|
+
}
|
|
236
304
|
/**
|
|
237
305
|
* Read an image from bytes
|
|
238
306
|
* @deprecated Use `decode()` instead. This method will be removed in a future version.
|
|
@@ -867,6 +935,34 @@ class Image {
|
|
|
867
935
|
this.imageData.data = (0, image_processing_js_1.flipVertical)(this.imageData.data, this.imageData.width, this.imageData.height);
|
|
868
936
|
return this;
|
|
869
937
|
}
|
|
938
|
+
/**
|
|
939
|
+
* Convert the image to CMYK color space
|
|
940
|
+
* Returns a Float32Array with 4 values per pixel (C, M, Y, K) in 0-1 range
|
|
941
|
+
* @returns CMYK image data as Float32Array
|
|
942
|
+
*/
|
|
943
|
+
toCMYK() {
|
|
944
|
+
if (!this.imageData)
|
|
945
|
+
throw new Error("No image loaded");
|
|
946
|
+
return (0, image_processing_js_1.rgbaToCmyk)(this.imageData.data);
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Create an Image from CMYK data
|
|
950
|
+
* @param cmykData CMYK image data (4 values per pixel in 0-1 range)
|
|
951
|
+
* @param width Image width
|
|
952
|
+
* @param height Image height
|
|
953
|
+
* @param alpha Optional alpha value for all pixels (0-255, default: 255)
|
|
954
|
+
* @returns New Image instance
|
|
955
|
+
*/
|
|
956
|
+
static fromCMYK(cmykData, width, height, alpha = 255) {
|
|
957
|
+
const rgbaData = (0, image_processing_js_1.cmykToRgba)(cmykData, alpha);
|
|
958
|
+
const image = new Image();
|
|
959
|
+
image.imageData = {
|
|
960
|
+
width,
|
|
961
|
+
height,
|
|
962
|
+
data: rgbaData,
|
|
963
|
+
};
|
|
964
|
+
return image;
|
|
965
|
+
}
|
|
870
966
|
}
|
|
871
967
|
exports.Image = Image;
|
|
872
968
|
Object.defineProperty(Image, "formats", {
|
package/script/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
|
*/
|
|
@@ -135,6 +181,42 @@ export interface ResizeOptions {
|
|
|
135
181
|
*/
|
|
136
182
|
fit?: "stretch" | "fit" | "fill" | "cover" | "contain";
|
|
137
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Options for PNG encoding.
|
|
186
|
+
*/
|
|
187
|
+
export interface PNGEncoderOptions {
|
|
188
|
+
/**
|
|
189
|
+
* Compression level (0-9)
|
|
190
|
+
* - 0-2: No filtering (fastest)
|
|
191
|
+
* - 3-6: Sub filter (balanced, default is 6)
|
|
192
|
+
* - 7-9: Adaptive filtering per scanline (best compression)
|
|
193
|
+
*
|
|
194
|
+
* Default: 6 (balanced)
|
|
195
|
+
*
|
|
196
|
+
* Note: Affects PNG filter selection. The native deflate compression
|
|
197
|
+
* is used regardless of level.
|
|
198
|
+
*/
|
|
199
|
+
compressionLevel?: number;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Options for APNG (Animated PNG) encoding.
|
|
203
|
+
*
|
|
204
|
+
* APNG uses PNG encoding for each frame.
|
|
205
|
+
*/
|
|
206
|
+
export interface APNGEncoderOptions extends PNGEncoderOptions {
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Options for GIF encoding.
|
|
210
|
+
*/
|
|
211
|
+
export interface GIFEncoderOptions {
|
|
212
|
+
/**
|
|
213
|
+
* Loop count for animated GIFs.
|
|
214
|
+
* - 0 (default): Loop infinitely
|
|
215
|
+
* - 1+: Loop a specific number of times
|
|
216
|
+
* - undefined or not set: Loop infinitely (same as 0)
|
|
217
|
+
*/
|
|
218
|
+
loop?: number;
|
|
219
|
+
}
|
|
138
220
|
/**
|
|
139
221
|
* Options for ASCII art encoding
|
|
140
222
|
*/
|
|
@@ -158,6 +240,8 @@ export interface TIFFEncoderOptions {
|
|
|
158
240
|
grayscale?: boolean;
|
|
159
241
|
/** Encode as RGB without alpha channel (default: false, ignored if grayscale is true) */
|
|
160
242
|
rgb?: boolean;
|
|
243
|
+
/** Encode as CMYK color space (default: false, ignored if grayscale is true) */
|
|
244
|
+
cmyk?: boolean;
|
|
161
245
|
}
|
|
162
246
|
/**
|
|
163
247
|
* Options for WebP encoding
|
|
@@ -189,6 +273,34 @@ export interface JPEGEncoderOptions {
|
|
|
189
273
|
*/
|
|
190
274
|
progressive?: boolean;
|
|
191
275
|
}
|
|
276
|
+
/**
|
|
277
|
+
* Options for AVIF encoding.
|
|
278
|
+
*
|
|
279
|
+
* Note: AVIF encoding is currently delegated to runtime APIs (OffscreenCanvas).
|
|
280
|
+
* Many runtimes ignore `quality` for AVIF, or may not support AVIF encoding at all.
|
|
281
|
+
*/
|
|
282
|
+
export interface AVIFEncoderOptions {
|
|
283
|
+
/**
|
|
284
|
+
* Best-effort encoding quality.
|
|
285
|
+
*
|
|
286
|
+
* Accepts either 0-1 (canvas-style) or 1-100 (library-style).
|
|
287
|
+
*/
|
|
288
|
+
quality?: number;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Options for HEIC encoding.
|
|
292
|
+
*
|
|
293
|
+
* Note: HEIC encoding is currently delegated to runtime APIs (OffscreenCanvas).
|
|
294
|
+
* Many runtimes do not support HEIC encoding.
|
|
295
|
+
*/
|
|
296
|
+
export interface HEICEncoderOptions {
|
|
297
|
+
/**
|
|
298
|
+
* Best-effort encoding quality.
|
|
299
|
+
*
|
|
300
|
+
* Accepts either 0-1 (canvas-style) or 1-100 (library-style).
|
|
301
|
+
*/
|
|
302
|
+
quality?: number;
|
|
303
|
+
}
|
|
192
304
|
/**
|
|
193
305
|
* Common options for decode APIs.
|
|
194
306
|
*
|
|
@@ -273,5 +385,22 @@ export interface ImageFormat {
|
|
|
273
385
|
* @returns Metadata extracted from the image, or undefined if extraction fails
|
|
274
386
|
*/
|
|
275
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>;
|
|
276
405
|
}
|
|
277
406
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base64 utilities.
|
|
3
|
+
*
|
|
4
|
+
* Designed to work across Deno, Node.js, and Bun without external dependencies.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Encode bytes into a standard Base64 string.
|
|
8
|
+
*/
|
|
9
|
+
export declare function encodeBase64(bytes: Uint8Array): string;
|
|
10
|
+
/**
|
|
11
|
+
* Decode a Base64 (or Base64URL) string into bytes.
|
|
12
|
+
*
|
|
13
|
+
* - Whitespace is ignored.
|
|
14
|
+
* - Missing padding is tolerated.
|
|
15
|
+
* - `-`/`_` are accepted as URL-safe variants.
|
|
16
|
+
*/
|
|
17
|
+
export declare function decodeBase64(base64: string): Uint8Array;
|
|
18
|
+
export interface ParsedDataUrl {
|
|
19
|
+
mime: string;
|
|
20
|
+
bytes: Uint8Array;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create a base64 data URL.
|
|
24
|
+
*/
|
|
25
|
+
export declare function toDataUrl(mime: string, bytes: Uint8Array): string;
|
|
26
|
+
/**
|
|
27
|
+
* Parse a base64 data URL.
|
|
28
|
+
*
|
|
29
|
+
* Supports `data:<mime>;base64,<payload>`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseDataUrl(url: string): ParsedDataUrl;
|
|
32
|
+
//# sourceMappingURL=base64.d.ts.map
|