cross-image 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +160 -32
  2. package/esm/mod.d.ts +2 -1
  3. package/esm/mod.js +2 -1
  4. package/esm/src/formats/jpeg.d.ts +12 -1
  5. package/esm/src/formats/jpeg.js +633 -4
  6. package/esm/src/formats/png_base.d.ts +8 -0
  7. package/esm/src/formats/png_base.js +176 -3
  8. package/esm/src/formats/ppm.d.ts +50 -0
  9. package/esm/src/formats/ppm.js +242 -0
  10. package/esm/src/formats/tiff.d.ts +10 -1
  11. package/esm/src/formats/tiff.js +194 -44
  12. package/esm/src/formats/webp.d.ts +9 -2
  13. package/esm/src/formats/webp.js +211 -62
  14. package/esm/src/image.d.ts +81 -0
  15. package/esm/src/image.js +282 -5
  16. package/esm/src/types.d.ts +41 -1
  17. package/esm/src/utils/image_processing.d.ts +98 -0
  18. package/esm/src/utils/image_processing.js +440 -0
  19. package/esm/src/utils/metadata/xmp.d.ts +52 -0
  20. package/esm/src/utils/metadata/xmp.js +325 -0
  21. package/esm/src/utils/resize.d.ts +4 -0
  22. package/esm/src/utils/resize.js +74 -0
  23. package/package.json +1 -1
  24. package/script/mod.d.ts +2 -1
  25. package/script/mod.js +4 -2
  26. package/script/src/formats/jpeg.d.ts +12 -1
  27. package/script/src/formats/jpeg.js +633 -4
  28. package/script/src/formats/png_base.d.ts +8 -0
  29. package/script/src/formats/png_base.js +176 -3
  30. package/script/src/formats/ppm.d.ts +50 -0
  31. package/script/src/formats/ppm.js +246 -0
  32. package/script/src/formats/tiff.d.ts +10 -1
  33. package/script/src/formats/tiff.js +194 -44
  34. package/script/src/formats/webp.d.ts +9 -2
  35. package/script/src/formats/webp.js +211 -62
  36. package/script/src/image.d.ts +81 -0
  37. package/script/src/image.js +280 -3
  38. package/script/src/types.d.ts +41 -1
  39. package/script/src/utils/image_processing.d.ts +98 -0
  40. package/script/src/utils/image_processing.js +451 -0
  41. package/script/src/utils/metadata/xmp.d.ts +52 -0
  42. package/script/src/utils/metadata/xmp.js +333 -0
  43. package/script/src/utils/resize.d.ts +4 -0
  44. package/script/src/utils/resize.js +75 -0
@@ -14,6 +14,7 @@ const ico_js_1 = require("./formats/ico.js");
14
14
  const dng_js_1 = require("./formats/dng.js");
15
15
  const pam_js_1 = require("./formats/pam.js");
16
16
  const pcx_js_1 = require("./formats/pcx.js");
17
+ const ppm_js_1 = require("./formats/ppm.js");
17
18
  const ascii_js_1 = require("./formats/ascii.js");
18
19
  const security_js_1 = require("./utils/security.js");
19
20
  /**
@@ -183,6 +184,18 @@ class Image {
183
184
  }
184
185
  throw new Error("Unsupported or unrecognized image format");
185
186
  }
187
+ /**
188
+ * Get supported metadata fields for a specific format
189
+ * @param format Format name (e.g., "jpeg", "png", "webp")
190
+ * @returns Array of supported metadata field names, or undefined if format doesn't support metadata
191
+ */
192
+ static getSupportedMetadata(format) {
193
+ const formatHandler = Image.formats.find((f) => f.name === format.toLowerCase());
194
+ if (!formatHandler) {
195
+ throw new Error(`Unknown image format: ${format}`);
196
+ }
197
+ return formatHandler.getSupportedMetadata?.();
198
+ }
186
199
  /**
187
200
  * Read an image from bytes
188
201
  * @deprecated Use `decode()` instead. This method will be removed in a future version.
@@ -303,19 +316,98 @@ class Image {
303
316
  resize(options) {
304
317
  if (!this.imageData)
305
318
  throw new Error("No image loaded");
306
- const { width, height, method = "bilinear" } = options;
319
+ const { width, height, method = "bilinear", fit = "stretch" } = options;
307
320
  // Validate new dimensions for security (prevent integer overflow and heap exhaustion)
308
321
  (0, security_js_1.validateImageDimensions)(width, height);
309
322
  const { data: srcData, width: srcWidth, height: srcHeight } = this.imageData;
323
+ // Handle fitting modes
324
+ let targetWidth = width;
325
+ let targetHeight = height;
326
+ let shouldCenter = false;
327
+ const fitMode = fit === "contain" ? "fit" : fit === "cover" ? "fill" : fit;
328
+ if (fitMode === "fit" || fitMode === "fill") {
329
+ const srcAspect = srcWidth / srcHeight;
330
+ const targetAspect = width / height;
331
+ if (fitMode === "fit") {
332
+ // Fit within dimensions (letterbox)
333
+ if (srcAspect > targetAspect) {
334
+ // Source is wider - fit to width
335
+ targetWidth = width;
336
+ targetHeight = Math.round(width / srcAspect);
337
+ }
338
+ else {
339
+ // Source is taller - fit to height
340
+ targetWidth = Math.round(height * srcAspect);
341
+ targetHeight = height;
342
+ }
343
+ shouldCenter = true;
344
+ }
345
+ else {
346
+ // Fill dimensions (crop)
347
+ if (srcAspect > targetAspect) {
348
+ // Source is wider - fit to height and crop width
349
+ targetWidth = Math.round(height * srcAspect);
350
+ targetHeight = height;
351
+ }
352
+ else {
353
+ // Source is taller - fit to width and crop height
354
+ targetWidth = width;
355
+ targetHeight = Math.round(width / srcAspect);
356
+ }
357
+ shouldCenter = true;
358
+ }
359
+ }
360
+ // Perform the resize
310
361
  let resizedData;
311
362
  if (method === "nearest") {
312
- resizedData = (0, resize_js_1.resizeNearest)(srcData, srcWidth, srcHeight, width, height);
363
+ resizedData = (0, resize_js_1.resizeNearest)(srcData, srcWidth, srcHeight, targetWidth, targetHeight);
364
+ }
365
+ else if (method === "bicubic") {
366
+ resizedData = (0, resize_js_1.resizeBicubic)(srcData, srcWidth, srcHeight, targetWidth, targetHeight);
313
367
  }
314
368
  else {
315
- resizedData = (0, resize_js_1.resizeBilinear)(srcData, srcWidth, srcHeight, width, height);
369
+ resizedData = (0, resize_js_1.resizeBilinear)(srcData, srcWidth, srcHeight, targetWidth, targetHeight);
316
370
  }
317
371
  // Preserve metadata when resizing
318
372
  const metadata = this.imageData.metadata;
373
+ // If we need to center (fit mode) or crop (fill mode), create a canvas
374
+ if (shouldCenter && (targetWidth !== width || targetHeight !== height)) {
375
+ const canvas = new Uint8Array(width * height * 4);
376
+ // Fill with transparent black by default
377
+ canvas.fill(0);
378
+ if (fitMode === "fit") {
379
+ // Center the resized image (letterbox)
380
+ const offsetX = Math.floor((width - targetWidth) / 2);
381
+ const offsetY = Math.floor((height - targetHeight) / 2);
382
+ for (let y = 0; y < targetHeight; y++) {
383
+ for (let x = 0; x < targetWidth; x++) {
384
+ const srcIdx = (y * targetWidth + x) * 4;
385
+ const dstIdx = ((y + offsetY) * width + (x + offsetX)) * 4;
386
+ canvas[dstIdx] = resizedData[srcIdx];
387
+ canvas[dstIdx + 1] = resizedData[srcIdx + 1];
388
+ canvas[dstIdx + 2] = resizedData[srcIdx + 2];
389
+ canvas[dstIdx + 3] = resizedData[srcIdx + 3];
390
+ }
391
+ }
392
+ resizedData = canvas;
393
+ }
394
+ else {
395
+ // Crop to fill (center crop)
396
+ const offsetX = Math.floor((targetWidth - width) / 2);
397
+ const offsetY = Math.floor((targetHeight - height) / 2);
398
+ for (let y = 0; y < height; y++) {
399
+ for (let x = 0; x < width; x++) {
400
+ const srcIdx = ((y + offsetY) * targetWidth + (x + offsetX)) * 4;
401
+ const dstIdx = (y * width + x) * 4;
402
+ canvas[dstIdx] = resizedData[srcIdx];
403
+ canvas[dstIdx + 1] = resizedData[srcIdx + 1];
404
+ canvas[dstIdx + 2] = resizedData[srcIdx + 2];
405
+ canvas[dstIdx + 3] = resizedData[srcIdx + 3];
406
+ }
407
+ }
408
+ resizedData = canvas;
409
+ }
410
+ }
319
411
  this.imageData = {
320
412
  width,
321
413
  height,
@@ -441,6 +533,17 @@ class Image {
441
533
  this.imageData.data = (0, image_processing_js_1.adjustSaturation)(this.imageData.data, amount);
442
534
  return this;
443
535
  }
536
+ /**
537
+ * Adjust hue of the image by rotating the color wheel
538
+ * @param degrees Hue rotation in degrees (any value accepted, wraps at 360)
539
+ * @returns This image instance for chaining
540
+ */
541
+ hue(degrees) {
542
+ if (!this.imageData)
543
+ throw new Error("No image loaded");
544
+ this.imageData.data = (0, image_processing_js_1.adjustHue)(this.imageData.data, degrees);
545
+ return this;
546
+ }
444
547
  /**
445
548
  * Invert colors of the image
446
549
  * @returns This image instance for chaining
@@ -461,6 +564,61 @@ class Image {
461
564
  this.imageData.data = (0, image_processing_js_1.grayscale)(this.imageData.data);
462
565
  return this;
463
566
  }
567
+ /**
568
+ * Apply sepia tone effect to the image
569
+ * @returns This image instance for chaining
570
+ */
571
+ sepia() {
572
+ if (!this.imageData)
573
+ throw new Error("No image loaded");
574
+ this.imageData.data = (0, image_processing_js_1.sepia)(this.imageData.data);
575
+ return this;
576
+ }
577
+ /**
578
+ * Apply box blur filter to the image
579
+ * @param radius Blur radius (default: 1)
580
+ * @returns This image instance for chaining
581
+ */
582
+ blur(radius = 1) {
583
+ if (!this.imageData)
584
+ throw new Error("No image loaded");
585
+ this.imageData.data = (0, image_processing_js_1.boxBlur)(this.imageData.data, this.imageData.width, this.imageData.height, radius);
586
+ return this;
587
+ }
588
+ /**
589
+ * Apply Gaussian blur filter to the image
590
+ * @param radius Blur radius (default: 1)
591
+ * @param sigma Optional standard deviation (if not provided, calculated from radius)
592
+ * @returns This image instance for chaining
593
+ */
594
+ gaussianBlur(radius = 1, sigma) {
595
+ if (!this.imageData)
596
+ throw new Error("No image loaded");
597
+ this.imageData.data = (0, image_processing_js_1.gaussianBlur)(this.imageData.data, this.imageData.width, this.imageData.height, radius, sigma);
598
+ return this;
599
+ }
600
+ /**
601
+ * Apply sharpen filter to the image
602
+ * @param amount Sharpening amount (0-1, default: 0.5)
603
+ * @returns This image instance for chaining
604
+ */
605
+ sharpen(amount = 0.5) {
606
+ if (!this.imageData)
607
+ throw new Error("No image loaded");
608
+ this.imageData.data = (0, image_processing_js_1.sharpen)(this.imageData.data, this.imageData.width, this.imageData.height, amount);
609
+ return this;
610
+ }
611
+ /**
612
+ * Apply median filter to reduce noise
613
+ * @param radius Filter radius (default: 1)
614
+ * @returns This image instance for chaining
615
+ */
616
+ medianFilter(radius = 1) {
617
+ if (!this.imageData)
618
+ throw new Error("No image loaded");
619
+ this.imageData.data = (0, image_processing_js_1.medianFilter)(this.imageData.data, this.imageData.width, this.imageData.height, radius);
620
+ return this;
621
+ }
464
622
  /**
465
623
  * Fill a rectangular region with a color
466
624
  * @param x Starting X position
@@ -549,6 +707,124 @@ class Image {
549
707
  this.imageData.data[idx + 3] = a;
550
708
  return this;
551
709
  }
710
+ /**
711
+ * Rotate the image 90 degrees clockwise
712
+ * @returns This image instance for chaining
713
+ */
714
+ rotate90() {
715
+ if (!this.imageData)
716
+ throw new Error("No image loaded");
717
+ const result = (0, image_processing_js_1.rotate90)(this.imageData.data, this.imageData.width, this.imageData.height);
718
+ this.imageData.width = result.width;
719
+ this.imageData.height = result.height;
720
+ this.imageData.data = result.data;
721
+ // Update physical dimensions if DPI is set
722
+ if (this.imageData.metadata) {
723
+ const metadata = this.imageData.metadata;
724
+ if (metadata.dpiX && metadata.dpiY) {
725
+ // Swap physical dimensions
726
+ const tempPhysical = metadata.physicalWidth;
727
+ this.imageData.metadata.physicalWidth = metadata.physicalHeight;
728
+ this.imageData.metadata.physicalHeight = tempPhysical;
729
+ // Swap DPI
730
+ const tempDpi = metadata.dpiX;
731
+ this.imageData.metadata.dpiX = metadata.dpiY;
732
+ this.imageData.metadata.dpiY = tempDpi;
733
+ }
734
+ }
735
+ return this;
736
+ }
737
+ /**
738
+ * Rotate the image 180 degrees
739
+ * @returns This image instance for chaining
740
+ */
741
+ rotate180() {
742
+ if (!this.imageData)
743
+ throw new Error("No image loaded");
744
+ this.imageData.data = (0, image_processing_js_1.rotate180)(this.imageData.data, this.imageData.width, this.imageData.height);
745
+ return this;
746
+ }
747
+ /**
748
+ * Rotate the image 270 degrees clockwise (or 90 degrees counter-clockwise)
749
+ * @returns This image instance for chaining
750
+ */
751
+ rotate270() {
752
+ if (!this.imageData)
753
+ throw new Error("No image loaded");
754
+ const result = (0, image_processing_js_1.rotate270)(this.imageData.data, this.imageData.width, this.imageData.height);
755
+ this.imageData.width = result.width;
756
+ this.imageData.height = result.height;
757
+ this.imageData.data = result.data;
758
+ // Update physical dimensions if DPI is set
759
+ if (this.imageData.metadata) {
760
+ const metadata = this.imageData.metadata;
761
+ if (metadata.dpiX && metadata.dpiY) {
762
+ // Swap physical dimensions
763
+ const tempPhysical = metadata.physicalWidth;
764
+ this.imageData.metadata.physicalWidth = metadata.physicalHeight;
765
+ this.imageData.metadata.physicalHeight = tempPhysical;
766
+ // Swap DPI
767
+ const tempDpi = metadata.dpiX;
768
+ this.imageData.metadata.dpiX = metadata.dpiY;
769
+ this.imageData.metadata.dpiY = tempDpi;
770
+ }
771
+ }
772
+ return this;
773
+ }
774
+ /**
775
+ * Rotate the image by the specified angle in degrees
776
+ * @param degrees Rotation angle in degrees (positive = clockwise, negative = counter-clockwise)
777
+ * @returns This image instance for chaining
778
+ *
779
+ * @example
780
+ * ```ts
781
+ * image.rotate(90); // Rotate 90° clockwise
782
+ * image.rotate(-90); // Rotate 90° counter-clockwise
783
+ * image.rotate(180); // Rotate 180°
784
+ * image.rotate(45); // Rotate 45° clockwise (rounded to nearest 90°)
785
+ * ```
786
+ */
787
+ rotate(degrees) {
788
+ // Normalize to 0-360 range
789
+ let normalizedDegrees = degrees % 360;
790
+ if (normalizedDegrees < 0) {
791
+ normalizedDegrees += 360;
792
+ }
793
+ // Round to nearest 90 degrees
794
+ const rounded = Math.round(normalizedDegrees / 90) * 90;
795
+ // Apply rotation based on rounded value
796
+ switch (rounded % 360) {
797
+ case 90:
798
+ return this.rotate90();
799
+ case 180:
800
+ return this.rotate180();
801
+ case 270:
802
+ return this.rotate270();
803
+ default:
804
+ // 0 or 360 degrees - no rotation needed
805
+ return this;
806
+ }
807
+ }
808
+ /**
809
+ * Flip the image horizontally (mirror)
810
+ * @returns This image instance for chaining
811
+ */
812
+ flipHorizontal() {
813
+ if (!this.imageData)
814
+ throw new Error("No image loaded");
815
+ this.imageData.data = (0, image_processing_js_1.flipHorizontal)(this.imageData.data, this.imageData.width, this.imageData.height);
816
+ return this;
817
+ }
818
+ /**
819
+ * Flip the image vertically
820
+ * @returns This image instance for chaining
821
+ */
822
+ flipVertical() {
823
+ if (!this.imageData)
824
+ throw new Error("No image loaded");
825
+ this.imageData.data = (0, image_processing_js_1.flipVertical)(this.imageData.data, this.imageData.width, this.imageData.height);
826
+ return this;
827
+ }
552
828
  }
553
829
  exports.Image = Image;
554
830
  Object.defineProperty(Image, "formats", {
@@ -567,6 +843,7 @@ Object.defineProperty(Image, "formats", {
567
843
  new dng_js_1.DNGFormat(),
568
844
  new pam_js_1.PAMFormat(),
569
845
  new pcx_js_1.PCXFormat(),
846
+ new ppm_js_1.PPMFormat(),
570
847
  new ascii_js_1.ASCIIFormat(),
571
848
  ]
572
849
  });
@@ -24,6 +24,32 @@ export interface ImageMetadata {
24
24
  copyright?: string;
25
25
  /** Creation date */
26
26
  creationDate?: Date;
27
+ /** Camera make/manufacturer (e.g., "Canon", "Nikon") */
28
+ cameraMake?: string;
29
+ /** Camera model (e.g., "Canon EOS 5D Mark IV") */
30
+ cameraModel?: string;
31
+ /** Lens make/manufacturer */
32
+ lensMake?: string;
33
+ /** Lens model */
34
+ lensModel?: string;
35
+ /** ISO speed rating (e.g., 100, 400, 3200) */
36
+ iso?: number;
37
+ /** Exposure time / Shutter speed in seconds (e.g., 0.0125 = 1/80s) */
38
+ exposureTime?: number;
39
+ /** F-number / Aperture (e.g., 2.8, 5.6, 16) */
40
+ fNumber?: number;
41
+ /** Focal length in millimeters (e.g., 50, 85, 200) */
42
+ focalLength?: number;
43
+ /** Flash mode (0 = no flash, 1 = flash fired) */
44
+ flash?: number;
45
+ /** White balance mode (0 = auto, 1 = manual) */
46
+ whiteBalance?: number;
47
+ /** Orientation (1 = normal, 3 = 180°, 6 = 90° CW, 8 = 90° CCW) */
48
+ orientation?: number;
49
+ /** Software used to create/edit the image */
50
+ software?: string;
51
+ /** User comment / notes */
52
+ userComment?: string;
27
53
  /** Custom metadata fields */
28
54
  custom?: Record<string, string | number | boolean>;
29
55
  }
@@ -88,7 +114,16 @@ export interface ResizeOptions {
88
114
  /** Target height in pixels */
89
115
  height: number;
90
116
  /** Resize method (default: "bilinear") */
91
- method?: "nearest" | "bilinear";
117
+ method?: "nearest" | "bilinear" | "bicubic";
118
+ /**
119
+ * Fitting mode (default: "stretch")
120
+ * - "stretch": Stretch image to fill dimensions (may distort)
121
+ * - "fit": Fit image within dimensions maintaining aspect ratio (may have letterboxing)
122
+ * - "fill": Fill dimensions maintaining aspect ratio (may crop)
123
+ * - "cover": Alias for "fill"
124
+ * - "contain": Alias for "fit"
125
+ */
126
+ fit?: "stretch" | "fit" | "fill" | "cover" | "contain";
92
127
  }
93
128
  /**
94
129
  * Options for ASCII art encoding
@@ -163,5 +198,10 @@ export interface ImageFormat {
163
198
  * Check if the format supports multiple frames
164
199
  */
165
200
  supportsMultipleFrames?(): boolean;
201
+ /**
202
+ * Get the list of metadata fields supported by this format
203
+ * @returns Array of metadata field names that can be persisted
204
+ */
205
+ getSupportedMetadata?(): Array<keyof ImageMetadata>;
166
206
  }
167
207
  //# sourceMappingURL=types.d.ts.map
@@ -44,6 +44,13 @@ export declare function adjustExposure(data: Uint8Array, amount: number): Uint8A
44
44
  * @returns New image data with adjusted saturation
45
45
  */
46
46
  export declare function adjustSaturation(data: Uint8Array, amount: number): Uint8Array;
47
+ /**
48
+ * Adjust hue of an image by rotating the hue wheel
49
+ * @param data Image data (RGBA)
50
+ * @param degrees Hue rotation in degrees (any value accepted, wraps at 360)
51
+ * @returns New image data with adjusted hue
52
+ */
53
+ export declare function adjustHue(data: Uint8Array, degrees: number): Uint8Array;
47
54
  /**
48
55
  * Invert colors of an image
49
56
  * @param data Image data (RGBA)
@@ -88,4 +95,95 @@ export declare function crop(data: Uint8Array, width: number, height: number, x:
88
95
  width: number;
89
96
  height: number;
90
97
  };
98
+ /**
99
+ * Apply a box blur filter to an image
100
+ * @param data Image data (RGBA)
101
+ * @param width Image width
102
+ * @param height Image height
103
+ * @param radius Blur radius (default: 1)
104
+ * @returns New image data with box blur applied
105
+ */
106
+ export declare function boxBlur(data: Uint8Array, width: number, height: number, radius?: number): Uint8Array;
107
+ /**
108
+ * Apply Gaussian blur to an image
109
+ * @param data Image data (RGBA)
110
+ * @param width Image width
111
+ * @param height Image height
112
+ * @param radius Blur radius (default: 1)
113
+ * @param sigma Optional standard deviation (if not provided, calculated from radius)
114
+ * @returns New image data with Gaussian blur applied
115
+ */
116
+ export declare function gaussianBlur(data: Uint8Array, width: number, height: number, radius?: number, sigma?: number): Uint8Array;
117
+ /**
118
+ * Apply sharpen filter to an image
119
+ * @param data Image data (RGBA)
120
+ * @param width Image width
121
+ * @param height Image height
122
+ * @param amount Sharpening amount (0-1, default: 0.5)
123
+ * @returns New image data with sharpening applied
124
+ */
125
+ export declare function sharpen(data: Uint8Array, width: number, height: number, amount?: number): Uint8Array;
126
+ /**
127
+ * Apply sepia tone effect to an image
128
+ * @param data Image data (RGBA)
129
+ * @returns New image data with sepia tone applied
130
+ */
131
+ export declare function sepia(data: Uint8Array): Uint8Array;
132
+ /**
133
+ * Apply median filter to reduce noise
134
+ * @param data Image data (RGBA)
135
+ * @param width Image width
136
+ * @param height Image height
137
+ * @param radius Filter radius (default: 1)
138
+ * @returns New image data with median filter applied
139
+ */
140
+ export declare function medianFilter(data: Uint8Array, width: number, height: number, radius?: number): Uint8Array;
141
+ /**
142
+ * Rotate image 90 degrees clockwise
143
+ * @param data Image data (RGBA)
144
+ * @param width Image width
145
+ * @param height Image height
146
+ * @returns Rotated image data with swapped dimensions
147
+ */
148
+ export declare function rotate90(data: Uint8Array, width: number, height: number): {
149
+ data: Uint8Array;
150
+ width: number;
151
+ height: number;
152
+ };
153
+ /**
154
+ * Rotate image 180 degrees
155
+ * @param data Image data (RGBA)
156
+ * @param width Image width
157
+ * @param height Image height
158
+ * @returns Rotated image data with same dimensions
159
+ */
160
+ export declare function rotate180(data: Uint8Array, width: number, height: number): Uint8Array;
161
+ /**
162
+ * Rotate image 270 degrees clockwise (or 90 degrees counter-clockwise)
163
+ * @param data Image data (RGBA)
164
+ * @param width Image width
165
+ * @param height Image height
166
+ * @returns Rotated image data with swapped dimensions
167
+ */
168
+ export declare function rotate270(data: Uint8Array, width: number, height: number): {
169
+ data: Uint8Array;
170
+ width: number;
171
+ height: number;
172
+ };
173
+ /**
174
+ * Flip image horizontally (mirror)
175
+ * @param data Image data (RGBA)
176
+ * @param width Image width
177
+ * @param height Image height
178
+ * @returns Flipped image data
179
+ */
180
+ export declare function flipHorizontal(data: Uint8Array, width: number, height: number): Uint8Array;
181
+ /**
182
+ * Flip image vertically
183
+ * @param data Image data (RGBA)
184
+ * @param width Image width
185
+ * @param height Image height
186
+ * @returns Flipped image data
187
+ */
188
+ export declare function flipVertical(data: Uint8Array, width: number, height: number): Uint8Array;
91
189
  //# sourceMappingURL=image_processing.d.ts.map