cross-image 0.2.0 → 0.2.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 +41 -28
  2. package/esm/mod.d.ts +4 -1
  3. package/esm/mod.js +4 -1
  4. package/esm/src/formats/apng.d.ts +50 -0
  5. package/esm/src/formats/apng.js +364 -0
  6. package/esm/src/formats/bmp.d.ts +0 -6
  7. package/esm/src/formats/bmp.js +24 -47
  8. package/esm/src/formats/dng.js +4 -4
  9. package/esm/src/formats/gif.d.ts +0 -2
  10. package/esm/src/formats/gif.js +10 -16
  11. package/esm/src/formats/ico.d.ts +41 -0
  12. package/esm/src/formats/ico.js +214 -0
  13. package/esm/src/formats/pcx.js +1 -1
  14. package/esm/src/formats/png.d.ts +2 -21
  15. package/esm/src/formats/png.js +5 -429
  16. package/esm/src/formats/png_base.d.ts +108 -0
  17. package/esm/src/formats/png_base.js +487 -0
  18. package/esm/src/formats/ppm.d.ts +50 -0
  19. package/esm/src/formats/ppm.js +242 -0
  20. package/esm/src/formats/tiff.d.ts +4 -0
  21. package/esm/src/formats/tiff.js +163 -44
  22. package/esm/src/formats/webp.d.ts +0 -1
  23. package/esm/src/formats/webp.js +4 -7
  24. package/esm/src/image.d.ts +30 -0
  25. package/esm/src/image.js +62 -1
  26. package/esm/src/utils/byte_utils.d.ts +30 -0
  27. package/esm/src/utils/byte_utils.js +50 -0
  28. package/esm/src/utils/gif_encoder.d.ts +3 -2
  29. package/esm/src/utils/gif_encoder.js +115 -48
  30. package/esm/src/utils/image_processing.d.ts +43 -0
  31. package/esm/src/utils/image_processing.js +230 -0
  32. package/package.json +1 -1
  33. package/script/mod.d.ts +4 -1
  34. package/script/mod.js +8 -2
  35. package/script/src/formats/apng.d.ts +50 -0
  36. package/script/src/formats/apng.js +368 -0
  37. package/script/src/formats/bmp.d.ts +0 -6
  38. package/script/src/formats/bmp.js +24 -47
  39. package/script/src/formats/dng.js +4 -4
  40. package/script/src/formats/gif.d.ts +0 -2
  41. package/script/src/formats/gif.js +10 -16
  42. package/script/src/formats/ico.d.ts +41 -0
  43. package/script/src/formats/ico.js +218 -0
  44. package/script/src/formats/pcx.js +1 -1
  45. package/script/src/formats/png.d.ts +2 -21
  46. package/script/src/formats/png.js +5 -429
  47. package/script/src/formats/png_base.d.ts +108 -0
  48. package/script/src/formats/png_base.js +491 -0
  49. package/script/src/formats/ppm.d.ts +50 -0
  50. package/script/src/formats/ppm.js +246 -0
  51. package/script/src/formats/tiff.d.ts +4 -0
  52. package/script/src/formats/tiff.js +163 -44
  53. package/script/src/formats/webp.d.ts +0 -1
  54. package/script/src/formats/webp.js +4 -7
  55. package/script/src/image.d.ts +30 -0
  56. package/script/src/image.js +61 -0
  57. package/script/src/utils/byte_utils.d.ts +30 -0
  58. package/script/src/utils/byte_utils.js +58 -0
  59. package/script/src/utils/gif_encoder.d.ts +3 -2
  60. package/script/src/utils/gif_encoder.js +115 -48
  61. package/script/src/utils/image_processing.d.ts +43 -0
  62. package/script/src/utils/image_processing.js +235 -0
@@ -4,14 +4,17 @@ exports.Image = void 0;
4
4
  const resize_js_1 = require("./utils/resize.js");
5
5
  const image_processing_js_1 = require("./utils/image_processing.js");
6
6
  const png_js_1 = require("./formats/png.js");
7
+ const apng_js_1 = require("./formats/apng.js");
7
8
  const jpeg_js_1 = require("./formats/jpeg.js");
8
9
  const webp_js_1 = require("./formats/webp.js");
9
10
  const gif_js_1 = require("./formats/gif.js");
10
11
  const tiff_js_1 = require("./formats/tiff.js");
11
12
  const bmp_js_1 = require("./formats/bmp.js");
13
+ const ico_js_1 = require("./formats/ico.js");
12
14
  const dng_js_1 = require("./formats/dng.js");
13
15
  const pam_js_1 = require("./formats/pam.js");
14
16
  const pcx_js_1 = require("./formats/pcx.js");
17
+ const ppm_js_1 = require("./formats/ppm.js");
15
18
  const ascii_js_1 = require("./formats/ascii.js");
16
19
  const security_js_1 = require("./utils/security.js");
17
20
  /**
@@ -459,6 +462,61 @@ class Image {
459
462
  this.imageData.data = (0, image_processing_js_1.grayscale)(this.imageData.data);
460
463
  return this;
461
464
  }
465
+ /**
466
+ * Apply sepia tone effect to the image
467
+ * @returns This image instance for chaining
468
+ */
469
+ sepia() {
470
+ if (!this.imageData)
471
+ throw new Error("No image loaded");
472
+ this.imageData.data = (0, image_processing_js_1.sepia)(this.imageData.data);
473
+ return this;
474
+ }
475
+ /**
476
+ * Apply box blur filter to the image
477
+ * @param radius Blur radius (default: 1)
478
+ * @returns This image instance for chaining
479
+ */
480
+ blur(radius = 1) {
481
+ if (!this.imageData)
482
+ throw new Error("No image loaded");
483
+ this.imageData.data = (0, image_processing_js_1.boxBlur)(this.imageData.data, this.imageData.width, this.imageData.height, radius);
484
+ return this;
485
+ }
486
+ /**
487
+ * Apply Gaussian blur filter to the image
488
+ * @param radius Blur radius (default: 1)
489
+ * @param sigma Optional standard deviation (if not provided, calculated from radius)
490
+ * @returns This image instance for chaining
491
+ */
492
+ gaussianBlur(radius = 1, sigma) {
493
+ if (!this.imageData)
494
+ throw new Error("No image loaded");
495
+ this.imageData.data = (0, image_processing_js_1.gaussianBlur)(this.imageData.data, this.imageData.width, this.imageData.height, radius, sigma);
496
+ return this;
497
+ }
498
+ /**
499
+ * Apply sharpen filter to the image
500
+ * @param amount Sharpening amount (0-1, default: 0.5)
501
+ * @returns This image instance for chaining
502
+ */
503
+ sharpen(amount = 0.5) {
504
+ if (!this.imageData)
505
+ throw new Error("No image loaded");
506
+ this.imageData.data = (0, image_processing_js_1.sharpen)(this.imageData.data, this.imageData.width, this.imageData.height, amount);
507
+ return this;
508
+ }
509
+ /**
510
+ * Apply median filter to reduce noise
511
+ * @param radius Filter radius (default: 1)
512
+ * @returns This image instance for chaining
513
+ */
514
+ medianFilter(radius = 1) {
515
+ if (!this.imageData)
516
+ throw new Error("No image loaded");
517
+ this.imageData.data = (0, image_processing_js_1.medianFilter)(this.imageData.data, this.imageData.width, this.imageData.height, radius);
518
+ return this;
519
+ }
462
520
  /**
463
521
  * Fill a rectangular region with a color
464
522
  * @param x Starting X position
@@ -555,14 +613,17 @@ Object.defineProperty(Image, "formats", {
555
613
  writable: true,
556
614
  value: [
557
615
  new png_js_1.PNGFormat(),
616
+ new apng_js_1.APNGFormat(),
558
617
  new jpeg_js_1.JPEGFormat(),
559
618
  new webp_js_1.WebPFormat(),
560
619
  new gif_js_1.GIFFormat(),
561
620
  new tiff_js_1.TIFFFormat(),
562
621
  new bmp_js_1.BMPFormat(),
622
+ new ico_js_1.ICOFormat(),
563
623
  new dng_js_1.DNGFormat(),
564
624
  new pam_js_1.PAMFormat(),
565
625
  new pcx_js_1.PCXFormat(),
626
+ new ppm_js_1.PPMFormat(),
566
627
  new ascii_js_1.ASCIIFormat(),
567
628
  ]
568
629
  });
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Shared byte-level read/write utilities for image formats
3
+ * These functions handle reading and writing multi-byte integers
4
+ * in little-endian byte order, commonly used in BMP, ICO, GIF, and other formats.
5
+ */
6
+ /**
7
+ * Read a 16-bit unsigned integer in little-endian format
8
+ */
9
+ export declare function readUint16LE(data: Uint8Array, offset: number): number;
10
+ /**
11
+ * Read a 32-bit unsigned integer in little-endian format
12
+ */
13
+ export declare function readUint32LE(data: Uint8Array, offset: number): number;
14
+ /**
15
+ * Read a 32-bit signed integer in little-endian format
16
+ */
17
+ export declare function readInt32LE(data: Uint8Array, offset: number): number;
18
+ /**
19
+ * Write a 16-bit unsigned integer in little-endian format
20
+ */
21
+ export declare function writeUint16LE(data: Uint8Array, offset: number, value: number): void;
22
+ /**
23
+ * Write a 32-bit unsigned integer in little-endian format
24
+ */
25
+ export declare function writeUint32LE(data: Uint8Array, offset: number, value: number): void;
26
+ /**
27
+ * Write a 32-bit signed integer in little-endian format
28
+ */
29
+ export declare function writeInt32LE(data: Uint8Array, offset: number, value: number): void;
30
+ //# sourceMappingURL=byte_utils.d.ts.map
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Shared byte-level read/write utilities for image formats
4
+ * These functions handle reading and writing multi-byte integers
5
+ * in little-endian byte order, commonly used in BMP, ICO, GIF, and other formats.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.readUint16LE = readUint16LE;
9
+ exports.readUint32LE = readUint32LE;
10
+ exports.readInt32LE = readInt32LE;
11
+ exports.writeUint16LE = writeUint16LE;
12
+ exports.writeUint32LE = writeUint32LE;
13
+ exports.writeInt32LE = writeInt32LE;
14
+ // Constants for signed/unsigned integer conversion
15
+ const INT32_MAX = 0x7fffffff;
16
+ const UINT32_RANGE = 0x100000000;
17
+ /**
18
+ * Read a 16-bit unsigned integer in little-endian format
19
+ */
20
+ function readUint16LE(data, offset) {
21
+ return data[offset] | (data[offset + 1] << 8);
22
+ }
23
+ /**
24
+ * Read a 32-bit unsigned integer in little-endian format
25
+ */
26
+ function readUint32LE(data, offset) {
27
+ return data[offset] | (data[offset + 1] << 8) |
28
+ (data[offset + 2] << 16) | (data[offset + 3] << 24);
29
+ }
30
+ /**
31
+ * Read a 32-bit signed integer in little-endian format
32
+ */
33
+ function readInt32LE(data, offset) {
34
+ const value = readUint32LE(data, offset);
35
+ return value > INT32_MAX ? value - UINT32_RANGE : value;
36
+ }
37
+ /**
38
+ * Write a 16-bit unsigned integer in little-endian format
39
+ */
40
+ function writeUint16LE(data, offset, value) {
41
+ data[offset] = value & 0xff;
42
+ data[offset + 1] = (value >>> 8) & 0xff;
43
+ }
44
+ /**
45
+ * Write a 32-bit unsigned integer in little-endian format
46
+ */
47
+ function writeUint32LE(data, offset, value) {
48
+ data[offset] = value & 0xff;
49
+ data[offset + 1] = (value >>> 8) & 0xff;
50
+ data[offset + 2] = (value >>> 16) & 0xff;
51
+ data[offset + 3] = (value >>> 24) & 0xff;
52
+ }
53
+ /**
54
+ * Write a 32-bit signed integer in little-endian format
55
+ */
56
+ function writeInt32LE(data, offset, value) {
57
+ writeUint32LE(data, offset, value < 0 ? value + UINT32_RANGE : value);
58
+ }
@@ -5,8 +5,9 @@
5
5
  export declare class GIFEncoder {
6
6
  private width;
7
7
  private height;
8
- private data;
9
- constructor(width: number, height: number, data: Uint8Array);
8
+ private frames;
9
+ constructor(width: number, height: number, data?: Uint8Array);
10
+ addFrame(data: Uint8Array, delay?: number): void;
10
11
  private writeBytes;
11
12
  private writeUint16LE;
12
13
  private writeString;
@@ -20,15 +20,20 @@ class GIFEncoder {
20
20
  writable: true,
21
21
  value: void 0
22
22
  });
23
- Object.defineProperty(this, "data", {
23
+ Object.defineProperty(this, "frames", {
24
24
  enumerable: true,
25
25
  configurable: true,
26
26
  writable: true,
27
- value: void 0
27
+ value: []
28
28
  });
29
29
  this.width = width;
30
30
  this.height = height;
31
- this.data = data;
31
+ if (data) {
32
+ this.addFrame(data);
33
+ }
34
+ }
35
+ addFrame(data, delay = 0) {
36
+ this.frames.push({ data, delay });
32
37
  }
33
38
  writeBytes(output, bytes) {
34
39
  output.push(...bytes);
@@ -57,7 +62,7 @@ class GIFEncoder {
57
62
  /**
58
63
  * Quantize RGBA image to 256 colors using median cut algorithm
59
64
  */
60
- quantize() {
65
+ quantize(data) {
61
66
  // Simple quantization: collect unique colors and build palette
62
67
  const colorMap = new Map();
63
68
  const colors = [];
@@ -68,10 +73,10 @@ class GIFEncoder {
68
73
  const rgStep = 255 / RG_LEVELS; // Step size for R/G quantization
69
74
  const bStep = 255 / B_LEVELS; // Step size for B quantization
70
75
  // Collect unique colors
71
- for (let i = 0; i < this.data.length; i += 4) {
72
- const r = this.data[i];
73
- const g = this.data[i + 1];
74
- const b = this.data[i + 2];
76
+ for (let i = 0; i < data.length; i += 4) {
77
+ const r = data[i];
78
+ const g = data[i + 1];
79
+ const b = data[i + 2];
75
80
  const key = `${r},${g},${b}`;
76
81
  if (!colorMap.has(key) && colors.length < 256) {
77
82
  colorMap.set(key, colors.length);
@@ -86,12 +91,12 @@ class GIFEncoder {
86
91
  colorMap.clear();
87
92
  colors.length = 0;
88
93
  useColorReduction = true;
89
- for (let i = 0; i < this.data.length; i += 4) {
94
+ for (let i = 0; i < data.length; i += 4) {
90
95
  // Reduce color depth: 3 bits for R/G channels, 2 bits for B channel
91
96
  // This gives us 8 bits total = 256 possible colors
92
- const r = this.quantizeChannel(this.data[i], RG_LEVELS, rgStep);
93
- const g = this.quantizeChannel(this.data[i + 1], RG_LEVELS, rgStep);
94
- const b = this.quantizeChannel(this.data[i + 2], B_LEVELS, bStep);
97
+ const r = this.quantizeChannel(data[i], RG_LEVELS, rgStep);
98
+ const g = this.quantizeChannel(data[i + 1], RG_LEVELS, rgStep);
99
+ const b = this.quantizeChannel(data[i + 2], B_LEVELS, bStep);
95
100
  const key = `${r},${g},${b}`;
96
101
  if (!colorMap.has(key)) {
97
102
  if (colors.length < 256) {
@@ -115,10 +120,10 @@ class GIFEncoder {
115
120
  }
116
121
  // Create indexed data
117
122
  const indexed = new Uint8Array(this.width * this.height);
118
- for (let i = 0, j = 0; i < this.data.length; i += 4, j++) {
119
- let r = this.data[i];
120
- let g = this.data[i + 1];
121
- let b = this.data[i + 2];
123
+ for (let i = 0, j = 0; i < data.length; i += 4, j++) {
124
+ let r = data[i];
125
+ let g = data[i + 1];
126
+ let b = data[i + 2];
122
127
  // Apply color reduction if it was used for building the palette
123
128
  if (useColorReduction) {
124
129
  r = this.quantizeChannel(r, RG_LEVELS, rgStep);
@@ -164,10 +169,14 @@ class GIFEncoder {
164
169
  return Math.max(2, bits);
165
170
  }
166
171
  encode() {
172
+ if (this.frames.length === 0) {
173
+ throw new Error("No frames to encode");
174
+ }
167
175
  const output = [];
168
- // Quantize image
169
- const { palette, indexed } = this.quantize();
170
- const paletteSize = palette.length / 3;
176
+ // Quantize first frame for Global Color Table
177
+ const firstFrame = this.frames[0];
178
+ const { palette: globalPalette, indexed: firstIndexed } = this.quantize(firstFrame.data);
179
+ const paletteSize = globalPalette.length / 3;
171
180
  const bitsPerColor = this.getBitsPerColor(paletteSize);
172
181
  // Header
173
182
  this.writeString(output, "GIF89a");
@@ -190,38 +199,96 @@ class GIFEncoder {
190
199
  // So we need to write that many colors, padding if necessary
191
200
  const gctSize = 1 << bitsPerColor;
192
201
  const paddedPalette = new Uint8Array(gctSize * 3);
193
- paddedPalette.set(palette);
202
+ paddedPalette.set(globalPalette);
194
203
  this.writeBytes(output, paddedPalette);
195
- // Image Descriptor
196
- output.push(0x2c); // Image Separator
197
- // Image position and dimensions
198
- this.writeUint16LE(output, 0); // Left
199
- this.writeUint16LE(output, 0); // Top
200
- this.writeUint16LE(output, this.width);
201
- this.writeUint16LE(output, this.height);
202
- // Packed field:
203
- // - Local Color Table Flag (1 bit): 0
204
- // - Interlace Flag (1 bit): 0
205
- // - Sort Flag (1 bit): 0
206
- // - Reserved (2 bits): 0
207
- // - Size of Local Color Table (3 bits): 0
208
- output.push(0);
209
- // LZW Minimum Code Size
210
- const minCodeSize = Math.max(2, bitsPerColor);
211
- output.push(minCodeSize);
212
- // Compress image data with LZW
213
- const encoder = new lzw_js_1.LZWEncoder(minCodeSize);
214
- const compressed = encoder.compress(indexed);
215
- // Write compressed data in sub-blocks (max 255 bytes per block)
216
- for (let i = 0; i < compressed.length; i += 255) {
217
- const blockSize = Math.min(255, compressed.length - i);
218
- output.push(blockSize);
219
- for (let j = 0; j < blockSize; j++) {
220
- output.push(compressed[i + j]);
204
+ // Netscape Application Extension (Looping)
205
+ if (this.frames.length > 1) {
206
+ output.push(0x21); // Extension Introducer
207
+ output.push(0xff); // Application Extension Label
208
+ output.push(11); // Block Size
209
+ this.writeString(output, "NETSCAPE2.0");
210
+ output.push(3); // Sub-block Size
211
+ output.push(1); // Loop Indicator (1 = loop)
212
+ this.writeUint16LE(output, 0); // Loop Count (0 = infinite)
213
+ output.push(0); // Block Terminator
214
+ }
215
+ // Encode frames
216
+ for (let i = 0; i < this.frames.length; i++) {
217
+ const frame = this.frames[i];
218
+ let indexed;
219
+ let useLocalPalette = false;
220
+ let localPalette = null;
221
+ let localBitsPerColor = bitsPerColor;
222
+ if (i === 0) {
223
+ indexed = firstIndexed;
224
+ }
225
+ else {
226
+ // Quantize subsequent frames
227
+ // For simplicity, we use a Local Color Table for each frame to ensure colors are correct
228
+ const result = this.quantize(frame.data);
229
+ indexed = result.indexed;
230
+ localPalette = result.palette;
231
+ useLocalPalette = true;
232
+ const localPaletteSize = localPalette.length / 3;
233
+ localBitsPerColor = this.getBitsPerColor(localPaletteSize);
221
234
  }
235
+ // Graphic Control Extension
236
+ output.push(0x21); // Extension Introducer
237
+ output.push(0xf9); // Graphic Control Label
238
+ output.push(4); // Byte Size
239
+ // Packed Field
240
+ // Reserved (3 bits)
241
+ // Disposal Method (3 bits): 2 (Restore to background) - usually safe for animation
242
+ // User Input Flag (1 bit): 0
243
+ // Transparent Color Flag (1 bit): 0
244
+ output.push(0x08); // Disposal method 2 (Restore to background)
245
+ // Delay Time (1/100ths of a second)
246
+ // Default to 10 (100ms) if not specified
247
+ const delay = frame.delay > 0 ? Math.round(frame.delay / 10) : 10;
248
+ this.writeUint16LE(output, delay);
249
+ // Transparent Color Index
250
+ output.push(0);
251
+ output.push(0); // Block Terminator
252
+ // Image Descriptor
253
+ output.push(0x2c); // Image Separator
254
+ this.writeUint16LE(output, 0); // Left
255
+ this.writeUint16LE(output, 0); // Top
256
+ this.writeUint16LE(output, this.width);
257
+ this.writeUint16LE(output, this.height);
258
+ // Packed Field
259
+ if (useLocalPalette && localPalette) {
260
+ // LCT Flag: 1
261
+ // Interlace: 0
262
+ // Sort: 0
263
+ // Reserved: 0
264
+ // Size of LCT: localBitsPerColor - 1
265
+ const lctPacked = 0x80 | (localBitsPerColor - 1);
266
+ output.push(lctPacked);
267
+ // Write Local Color Table
268
+ const lctSize = 1 << localBitsPerColor;
269
+ const paddedLct = new Uint8Array(lctSize * 3);
270
+ paddedLct.set(localPalette);
271
+ this.writeBytes(output, paddedLct);
272
+ }
273
+ else {
274
+ output.push(0); // No LCT
275
+ }
276
+ // LZW Minimum Code Size
277
+ const minCodeSize = Math.max(2, useLocalPalette ? localBitsPerColor : bitsPerColor);
278
+ output.push(minCodeSize);
279
+ // Compress image data with LZW
280
+ const encoder = new lzw_js_1.LZWEncoder(minCodeSize);
281
+ const compressed = encoder.compress(indexed);
282
+ // Write compressed data in sub-blocks (max 255 bytes per block)
283
+ for (let k = 0; k < compressed.length; k += 255) {
284
+ const blockSize = Math.min(255, compressed.length - k);
285
+ output.push(blockSize);
286
+ for (let j = 0; j < blockSize; j++) {
287
+ output.push(compressed[k + j]);
288
+ }
289
+ }
290
+ output.push(0); // Block Terminator
222
291
  }
223
- // Block Terminator
224
- output.push(0);
225
292
  // Trailer
226
293
  output.push(0x3b);
227
294
  return new Uint8Array(output);
@@ -88,4 +88,47 @@ export declare function crop(data: Uint8Array, width: number, height: number, x:
88
88
  width: number;
89
89
  height: number;
90
90
  };
91
+ /**
92
+ * Apply a box blur filter to an image
93
+ * @param data Image data (RGBA)
94
+ * @param width Image width
95
+ * @param height Image height
96
+ * @param radius Blur radius (default: 1)
97
+ * @returns New image data with box blur applied
98
+ */
99
+ export declare function boxBlur(data: Uint8Array, width: number, height: number, radius?: number): Uint8Array;
100
+ /**
101
+ * Apply Gaussian blur to an image
102
+ * @param data Image data (RGBA)
103
+ * @param width Image width
104
+ * @param height Image height
105
+ * @param radius Blur radius (default: 1)
106
+ * @param sigma Optional standard deviation (if not provided, calculated from radius)
107
+ * @returns New image data with Gaussian blur applied
108
+ */
109
+ export declare function gaussianBlur(data: Uint8Array, width: number, height: number, radius?: number, sigma?: number): Uint8Array;
110
+ /**
111
+ * Apply sharpen filter to an image
112
+ * @param data Image data (RGBA)
113
+ * @param width Image width
114
+ * @param height Image height
115
+ * @param amount Sharpening amount (0-1, default: 0.5)
116
+ * @returns New image data with sharpening applied
117
+ */
118
+ export declare function sharpen(data: Uint8Array, width: number, height: number, amount?: number): Uint8Array;
119
+ /**
120
+ * Apply sepia tone effect to an image
121
+ * @param data Image data (RGBA)
122
+ * @returns New image data with sepia tone applied
123
+ */
124
+ export declare function sepia(data: Uint8Array): Uint8Array;
125
+ /**
126
+ * Apply median filter to reduce noise
127
+ * @param data Image data (RGBA)
128
+ * @param width Image width
129
+ * @param height Image height
130
+ * @param radius Filter radius (default: 1)
131
+ * @returns New image data with median filter applied
132
+ */
133
+ export declare function medianFilter(data: Uint8Array, width: number, height: number, radius?: number): Uint8Array;
91
134
  //# sourceMappingURL=image_processing.d.ts.map