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.
Files changed (62) hide show
  1. package/README.md +186 -5
  2. package/esm/mod.d.ts +3 -1
  3. package/esm/mod.js +2 -0
  4. package/esm/src/formats/apng.d.ts +5 -3
  5. package/esm/src/formats/apng.js +11 -4
  6. package/esm/src/formats/avif.d.ts +2 -2
  7. package/esm/src/formats/avif.js +11 -1
  8. package/esm/src/formats/gif.d.ts +3 -3
  9. package/esm/src/formats/gif.js +4 -4
  10. package/esm/src/formats/heic.d.ts +2 -2
  11. package/esm/src/formats/heic.js +11 -1
  12. package/esm/src/formats/jpeg.d.ts +21 -1
  13. package/esm/src/formats/jpeg.js +59 -0
  14. package/esm/src/formats/png.d.ts +3 -2
  15. package/esm/src/formats/png.js +8 -2
  16. package/esm/src/formats/png_base.d.ts +42 -1
  17. package/esm/src/formats/png_base.js +198 -5
  18. package/esm/src/formats/tiff.js +76 -6
  19. package/esm/src/image.d.ts +54 -1
  20. package/esm/src/image.js +97 -1
  21. package/esm/src/types.d.ts +129 -0
  22. package/esm/src/utils/base64.d.ts +32 -0
  23. package/esm/src/utils/base64.js +173 -0
  24. package/esm/src/utils/gif_encoder.d.ts +3 -1
  25. package/esm/src/utils/gif_encoder.js +4 -2
  26. package/esm/src/utils/image_processing.d.ts +31 -0
  27. package/esm/src/utils/image_processing.js +88 -0
  28. package/esm/src/utils/jpeg_decoder.d.ts +25 -2
  29. package/esm/src/utils/jpeg_decoder.js +101 -10
  30. package/esm/src/utils/jpeg_encoder.d.ts +19 -0
  31. package/esm/src/utils/jpeg_encoder.js +267 -0
  32. package/package.json +1 -1
  33. package/script/mod.d.ts +3 -1
  34. package/script/mod.js +11 -1
  35. package/script/src/formats/apng.d.ts +5 -3
  36. package/script/src/formats/apng.js +11 -4
  37. package/script/src/formats/avif.d.ts +2 -2
  38. package/script/src/formats/avif.js +11 -1
  39. package/script/src/formats/gif.d.ts +3 -3
  40. package/script/src/formats/gif.js +4 -4
  41. package/script/src/formats/heic.d.ts +2 -2
  42. package/script/src/formats/heic.js +11 -1
  43. package/script/src/formats/jpeg.d.ts +21 -1
  44. package/script/src/formats/jpeg.js +59 -0
  45. package/script/src/formats/png.d.ts +3 -2
  46. package/script/src/formats/png.js +8 -2
  47. package/script/src/formats/png_base.d.ts +42 -1
  48. package/script/src/formats/png_base.js +198 -5
  49. package/script/src/formats/tiff.js +76 -6
  50. package/script/src/image.d.ts +54 -1
  51. package/script/src/image.js +96 -0
  52. package/script/src/types.d.ts +129 -0
  53. package/script/src/utils/base64.d.ts +32 -0
  54. package/script/src/utils/base64.js +179 -0
  55. package/script/src/utils/gif_encoder.d.ts +3 -1
  56. package/script/src/utils/gif_encoder.js +4 -2
  57. package/script/src/utils/image_processing.d.ts +31 -0
  58. package/script/src/utils/image_processing.js +92 -0
  59. package/script/src/utils/jpeg_decoder.d.ts +25 -2
  60. package/script/src/utils/jpeg_decoder.js +101 -10
  61. package/script/src/utils/jpeg_encoder.d.ts +19 -0
  62. 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
- // Support: 0 = WhiteIsZero, 1 = BlackIsZero, 2 = RGB
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
- // Support: 0 = WhiteIsZero, 1 = BlackIsZero, 2 = RGB
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++) {
@@ -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
@@ -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", {
@@ -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