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
@@ -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
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Base64 utilities.
3
+ *
4
+ * Designed to work across Deno, Node.js, and Bun without external dependencies.
5
+ */
6
+ const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7
+ const DECODE_TABLE = (() => {
8
+ const table = new Uint8Array(256);
9
+ table.fill(0xff);
10
+ for (let i = 0; i < BASE64_ALPHABET.length; i++) {
11
+ table[BASE64_ALPHABET.charCodeAt(i)] = i;
12
+ }
13
+ return table;
14
+ })();
15
+ function stripWhitespace(input) {
16
+ // Avoid regex to keep this fast and allocation-light.
17
+ let out = "";
18
+ for (let i = 0; i < input.length; i++) {
19
+ const code = input.charCodeAt(i);
20
+ // Space, tab, CR, LF
21
+ if (code === 0x20 || code === 0x09 || code === 0x0d || code === 0x0a)
22
+ continue;
23
+ out += input[i];
24
+ }
25
+ return out;
26
+ }
27
+ function normalizeBase64(input) {
28
+ // Accept URL-safe alphabet in decode paths.
29
+ let s = stripWhitespace(input.trim());
30
+ if (s.length === 0)
31
+ return s;
32
+ // Map base64url to base64.
33
+ if (s.includes("-") || s.includes("_")) {
34
+ s = s.replaceAll("-", "+").replaceAll("_", "/");
35
+ }
36
+ const remainder = s.length % 4;
37
+ if (remainder === 1) {
38
+ throw new Error("Invalid base64: length must not be 1 (mod 4)");
39
+ }
40
+ if (remainder === 2)
41
+ s += "==";
42
+ if (remainder === 3)
43
+ s += "=";
44
+ return s;
45
+ }
46
+ /**
47
+ * Encode bytes into a standard Base64 string.
48
+ */
49
+ export function encodeBase64(bytes) {
50
+ if (bytes.length === 0)
51
+ return "";
52
+ const outLen = Math.ceil(bytes.length / 3) * 4;
53
+ const out = new Array(outLen);
54
+ let i = 0;
55
+ let o = 0;
56
+ for (; i + 2 < bytes.length; i += 3) {
57
+ const n = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
58
+ out[o++] = BASE64_ALPHABET[(n >> 18) & 63];
59
+ out[o++] = BASE64_ALPHABET[(n >> 12) & 63];
60
+ out[o++] = BASE64_ALPHABET[(n >> 6) & 63];
61
+ out[o++] = BASE64_ALPHABET[n & 63];
62
+ }
63
+ const remaining = bytes.length - i;
64
+ if (remaining === 1) {
65
+ const n = bytes[i] << 16;
66
+ out[o++] = BASE64_ALPHABET[(n >> 18) & 63];
67
+ out[o++] = BASE64_ALPHABET[(n >> 12) & 63];
68
+ out[o++] = "=";
69
+ out[o++] = "=";
70
+ }
71
+ else if (remaining === 2) {
72
+ const n = (bytes[i] << 16) | (bytes[i + 1] << 8);
73
+ out[o++] = BASE64_ALPHABET[(n >> 18) & 63];
74
+ out[o++] = BASE64_ALPHABET[(n >> 12) & 63];
75
+ out[o++] = BASE64_ALPHABET[(n >> 6) & 63];
76
+ out[o++] = "=";
77
+ }
78
+ return out.join("");
79
+ }
80
+ /**
81
+ * Decode a Base64 (or Base64URL) string into bytes.
82
+ *
83
+ * - Whitespace is ignored.
84
+ * - Missing padding is tolerated.
85
+ * - `-`/`_` are accepted as URL-safe variants.
86
+ */
87
+ export function decodeBase64(base64) {
88
+ const s = normalizeBase64(base64);
89
+ if (s.length === 0)
90
+ return new Uint8Array(0);
91
+ let padding = 0;
92
+ if (s.endsWith("=="))
93
+ padding = 2;
94
+ else if (s.endsWith("="))
95
+ padding = 1;
96
+ const quadCount = s.length / 4;
97
+ const outLen = quadCount * 3 - padding;
98
+ const out = new Uint8Array(outLen);
99
+ let o = 0;
100
+ for (let i = 0; i < s.length; i += 4) {
101
+ const c0 = s.charCodeAt(i);
102
+ const c1 = s.charCodeAt(i + 1);
103
+ const c2 = s.charCodeAt(i + 2);
104
+ const c3 = s.charCodeAt(i + 3);
105
+ const v0 = DECODE_TABLE[c0];
106
+ const v1 = DECODE_TABLE[c1];
107
+ if (v0 === 0xff || v1 === 0xff) {
108
+ throw new Error("Invalid base64: invalid character");
109
+ }
110
+ const isPad2 = c2 === 0x3d; // '='
111
+ const isPad3 = c3 === 0x3d;
112
+ const v2 = isPad2 ? 0 : DECODE_TABLE[c2];
113
+ const v3 = isPad3 ? 0 : DECODE_TABLE[c3];
114
+ if ((!isPad2 && v2 === 0xff) || (!isPad3 && v3 === 0xff)) {
115
+ throw new Error("Invalid base64: invalid character");
116
+ }
117
+ const n = (v0 << 18) | (v1 << 12) | (v2 << 6) | v3;
118
+ out[o++] = (n >> 16) & 0xff;
119
+ if (!isPad2) {
120
+ if (o >= out.length)
121
+ break;
122
+ out[o++] = (n >> 8) & 0xff;
123
+ }
124
+ if (!isPad3) {
125
+ if (o >= out.length)
126
+ break;
127
+ out[o++] = n & 0xff;
128
+ }
129
+ if (isPad2 || isPad3) {
130
+ // Padding is only valid in the final quartet.
131
+ if (i + 4 !== s.length) {
132
+ throw new Error("Invalid base64: padding can only appear at the end");
133
+ }
134
+ // If third char is padding, fourth must also be padding.
135
+ if (isPad2 && !isPad3) {
136
+ throw new Error("Invalid base64: invalid padding");
137
+ }
138
+ }
139
+ }
140
+ return out;
141
+ }
142
+ /**
143
+ * Create a base64 data URL.
144
+ */
145
+ export function toDataUrl(mime, bytes) {
146
+ if (!mime)
147
+ throw new Error("mime is required");
148
+ return `data:${mime};base64,${encodeBase64(bytes)}`;
149
+ }
150
+ /**
151
+ * Parse a base64 data URL.
152
+ *
153
+ * Supports `data:<mime>;base64,<payload>`.
154
+ */
155
+ export function parseDataUrl(url) {
156
+ if (!url.startsWith("data:")) {
157
+ throw new Error("Invalid data URL: must start with 'data:'");
158
+ }
159
+ const commaIndex = url.indexOf(",");
160
+ if (commaIndex === -1) {
161
+ throw new Error("Invalid data URL: missing ',' separator");
162
+ }
163
+ const meta = url.slice(5, commaIndex);
164
+ const payload = url.slice(commaIndex + 1);
165
+ // We only support base64 payloads.
166
+ const metaParts = meta.split(";");
167
+ const mime = metaParts[0] || "application/octet-stream";
168
+ const isBase64 = metaParts.some((p) => p.toLowerCase() === "base64");
169
+ if (!isBase64) {
170
+ throw new Error("Invalid data URL: only base64 payloads are supported");
171
+ }
172
+ return { mime, bytes: decodeBase64(payload) };
173
+ }
@@ -25,6 +25,8 @@ export declare class GIFEncoder {
25
25
  private quantize;
26
26
  private nextPowerOf2;
27
27
  private getBitsPerColor;
28
- encode(): Uint8Array;
28
+ encode(options?: {
29
+ loop?: number;
30
+ }): Uint8Array;
29
31
  }
30
32
  //# sourceMappingURL=gif_encoder.d.ts.map
@@ -165,11 +165,13 @@ export class GIFEncoder {
165
165
  }
166
166
  return Math.max(2, bits);
167
167
  }
168
- encode() {
168
+ encode(options) {
169
169
  if (this.frames.length === 0) {
170
170
  throw new Error("No frames to encode");
171
171
  }
172
172
  const output = [];
173
+ // Get loop count from options (default to 0 = infinite)
174
+ const loopCount = options?.loop ?? 0;
173
175
  // Quantize first frame for Global Color Table
174
176
  const firstFrame = this.frames[0];
175
177
  const { palette: globalPalette, indexed: firstIndexed } = this.quantize(firstFrame.data);
@@ -206,7 +208,7 @@ export class GIFEncoder {
206
208
  this.writeString(output, "NETSCAPE2.0");
207
209
  output.push(3); // Sub-block Size
208
210
  output.push(1); // Loop Indicator (1 = loop)
209
- this.writeUint16LE(output, 0); // Loop Count (0 = infinite)
211
+ this.writeUint16LE(output, loopCount); // Loop Count (0 = infinite, 1+ = specific count)
210
212
  output.push(0); // Block Terminator
211
213
  }
212
214
  // Encode frames
@@ -186,4 +186,35 @@ export declare function flipHorizontal(data: Uint8Array, width: number, height:
186
186
  * @returns Flipped image data
187
187
  */
188
188
  export declare function flipVertical(data: Uint8Array, width: number, height: number): Uint8Array;
189
+ /**
190
+ * Convert RGB color to CMYK color space
191
+ * @param r Red component (0-255)
192
+ * @param g Green component (0-255)
193
+ * @param b Blue component (0-255)
194
+ * @returns CMYK values: [c (0-1), m (0-1), y (0-1), k (0-1)]
195
+ */
196
+ export declare function rgbToCmyk(r: number, g: number, b: number): [number, number, number, number];
197
+ /**
198
+ * Convert CMYK color to RGB color space
199
+ * @param c Cyan component (0-1)
200
+ * @param m Magenta component (0-1)
201
+ * @param y Yellow component (0-1)
202
+ * @param k Key/Black component (0-1)
203
+ * @returns RGB values: [r (0-255), g (0-255), b (0-255)]
204
+ */
205
+ export declare function cmykToRgb(c: number, m: number, y: number, k: number): [number, number, number];
206
+ /**
207
+ * Convert RGBA image data to CMYK representation
208
+ * Returns a Float32Array with 4 values per pixel (C, M, Y, K) in 0-1 range
209
+ * @param data Image data (RGBA)
210
+ * @returns CMYK image data as Float32Array (4 values per pixel)
211
+ */
212
+ export declare function rgbaToCmyk(data: Uint8Array): Float32Array;
213
+ /**
214
+ * Convert CMYK image data to RGBA representation
215
+ * @param cmykData CMYK image data (4 values per pixel in 0-1 range)
216
+ * @param alpha Optional alpha value for all pixels (0-255, default: 255)
217
+ * @returns RGBA image data
218
+ */
219
+ export declare function cmykToRgba(cmykData: Float32Array, alpha?: number): Uint8Array;
189
220
  //# sourceMappingURL=image_processing.d.ts.map
@@ -743,3 +743,91 @@ export function flipVertical(data, width, height) {
743
743
  }
744
744
  return result;
745
745
  }
746
+ /**
747
+ * Convert RGB color to CMYK color space
748
+ * @param r Red component (0-255)
749
+ * @param g Green component (0-255)
750
+ * @param b Blue component (0-255)
751
+ * @returns CMYK values: [c (0-1), m (0-1), y (0-1), k (0-1)]
752
+ */
753
+ export function rgbToCmyk(r, g, b) {
754
+ // Normalize RGB values to 0-1 range
755
+ const rNorm = r / 255;
756
+ const gNorm = g / 255;
757
+ const bNorm = b / 255;
758
+ // Calculate K (key/black)
759
+ const k = 1 - Math.max(rNorm, gNorm, bNorm);
760
+ // If K is 1 (pure black), CMY are undefined but conventionally set to 0
761
+ if (k === 1) {
762
+ return [0, 0, 0, 1];
763
+ }
764
+ // Calculate CMY components
765
+ const c = (1 - rNorm - k) / (1 - k);
766
+ const m = (1 - gNorm - k) / (1 - k);
767
+ const y = (1 - bNorm - k) / (1 - k);
768
+ return [c, m, y, k];
769
+ }
770
+ /**
771
+ * Convert CMYK color to RGB color space
772
+ * @param c Cyan component (0-1)
773
+ * @param m Magenta component (0-1)
774
+ * @param y Yellow component (0-1)
775
+ * @param k Key/Black component (0-1)
776
+ * @returns RGB values: [r (0-255), g (0-255), b (0-255)]
777
+ */
778
+ export function cmykToRgb(c, m, y, k) {
779
+ // Convert CMYK to RGB
780
+ const r = 255 * (1 - c) * (1 - k);
781
+ const g = 255 * (1 - m) * (1 - k);
782
+ const b = 255 * (1 - y) * (1 - k);
783
+ return [
784
+ Math.round(Math.max(0, Math.min(255, r))),
785
+ Math.round(Math.max(0, Math.min(255, g))),
786
+ Math.round(Math.max(0, Math.min(255, b))),
787
+ ];
788
+ }
789
+ /**
790
+ * Convert RGBA image data to CMYK representation
791
+ * Returns a Float32Array with 4 values per pixel (C, M, Y, K) in 0-1 range
792
+ * @param data Image data (RGBA)
793
+ * @returns CMYK image data as Float32Array (4 values per pixel)
794
+ */
795
+ export function rgbaToCmyk(data) {
796
+ const pixelCount = data.length / 4;
797
+ const result = new Float32Array(pixelCount * 4);
798
+ for (let i = 0; i < data.length; i += 4) {
799
+ const r = data[i];
800
+ const g = data[i + 1];
801
+ const b = data[i + 2];
802
+ const [c, m, y, k] = rgbToCmyk(r, g, b);
803
+ const outIdx = (i / 4) * 4;
804
+ result[outIdx] = c;
805
+ result[outIdx + 1] = m;
806
+ result[outIdx + 2] = y;
807
+ result[outIdx + 3] = k;
808
+ }
809
+ return result;
810
+ }
811
+ /**
812
+ * Convert CMYK image data to RGBA representation
813
+ * @param cmykData CMYK image data (4 values per pixel in 0-1 range)
814
+ * @param alpha Optional alpha value for all pixels (0-255, default: 255)
815
+ * @returns RGBA image data
816
+ */
817
+ export function cmykToRgba(cmykData, alpha = 255) {
818
+ const pixelCount = cmykData.length / 4;
819
+ const result = new Uint8Array(pixelCount * 4);
820
+ for (let i = 0; i < cmykData.length; i += 4) {
821
+ const c = cmykData[i];
822
+ const m = cmykData[i + 1];
823
+ const y = cmykData[i + 2];
824
+ const k = cmykData[i + 3];
825
+ const [r, g, b] = cmykToRgb(c, m, y, k);
826
+ const outIdx = i;
827
+ result[outIdx] = r;
828
+ result[outIdx + 1] = g;
829
+ result[outIdx + 2] = b;
830
+ result[outIdx + 3] = alpha;
831
+ }
832
+ return result;
833
+ }
@@ -8,7 +8,17 @@
8
8
  * This is a pure JavaScript implementation that handles common JPEG files.
9
9
  * For complex or non-standard JPEGs, the ImageDecoder API fallback is preferred.
10
10
  */
11
- import type { ImageDecoderOptions } from "../types.js";
11
+ import type { ImageDecoderOptions, JPEGQuantizedCoefficients } from "../types.js";
12
+ /**
13
+ * Extended decoder options including coefficient extraction
14
+ */
15
+ interface JPEGDecoderOptions extends ImageDecoderOptions {
16
+ /**
17
+ * When true, stores quantized DCT coefficients for later retrieval
18
+ * via getQuantizedCoefficients(). Coefficients are stored in zigzag order.
19
+ */
20
+ extractCoefficients?: boolean;
21
+ }
12
22
  export declare class JPEGDecoder {
13
23
  private data;
14
24
  private pos;
@@ -29,8 +39,20 @@ export declare class JPEGDecoder {
29
39
  private successiveLow;
30
40
  private scanComponentIds;
31
41
  private eobRun;
32
- constructor(data: Uint8Array, settings?: ImageDecoderOptions);
42
+ private quantizedCoefficients;
43
+ constructor(data: Uint8Array, settings?: JPEGDecoderOptions);
33
44
  decode(): Uint8Array;
45
+ /**
46
+ * Get the quantized DCT coefficients after decoding
47
+ * Only available if extractCoefficients option was set to true
48
+ * @returns JPEGQuantizedCoefficients or undefined if not available
49
+ */
50
+ getQuantizedCoefficients(): JPEGQuantizedCoefficients | undefined;
51
+ /**
52
+ * Store quantized coefficients in the output structure
53
+ * Called after decoding when extractCoefficients is true
54
+ */
55
+ private storeQuantizedCoefficients;
34
56
  private readMarker;
35
57
  private readUint16;
36
58
  private skipSegment;
@@ -49,4 +71,5 @@ export declare class JPEGDecoder {
49
71
  private idct;
50
72
  private convertToRGB;
51
73
  }
74
+ export {};
52
75
  //# sourceMappingURL=jpeg_decoder.d.ts.map