@flighthq/surface 0.1.0

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 (210) hide show
  1. package/dist/index.d.ts +43 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +42 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/surface.d.ts +16 -0
  6. package/dist/surface.d.ts.map +1 -0
  7. package/dist/surface.js +84 -0
  8. package/dist/surface.js.map +1 -0
  9. package/dist/surfaceAffine.d.ts +27 -0
  10. package/dist/surfaceAffine.d.ts.map +1 -0
  11. package/dist/surfaceAffine.js +159 -0
  12. package/dist/surfaceAffine.js.map +1 -0
  13. package/dist/surfaceAlpha.d.ts +27 -0
  14. package/dist/surfaceAlpha.d.ts.map +1 -0
  15. package/dist/surfaceAlpha.js +83 -0
  16. package/dist/surfaceAlpha.js.map +1 -0
  17. package/dist/surfaceBevel.d.ts +42 -0
  18. package/dist/surfaceBevel.d.ts.map +1 -0
  19. package/dist/surfaceBevel.js +102 -0
  20. package/dist/surfaceBevel.js.map +1 -0
  21. package/dist/surfaceBlur.d.ts +62 -0
  22. package/dist/surfaceBlur.d.ts.map +1 -0
  23. package/dist/surfaceBlur.js +263 -0
  24. package/dist/surfaceBlur.js.map +1 -0
  25. package/dist/surfaceChannel.d.ts +24 -0
  26. package/dist/surfaceChannel.d.ts.map +1 -0
  27. package/dist/surfaceChannel.js +126 -0
  28. package/dist/surfaceChannel.js.map +1 -0
  29. package/dist/surfaceColorMatrix.d.ts +57 -0
  30. package/dist/surfaceColorMatrix.d.ts.map +1 -0
  31. package/dist/surfaceColorMatrix.js +127 -0
  32. package/dist/surfaceColorMatrix.js.map +1 -0
  33. package/dist/surfaceCompare.d.ts +18 -0
  34. package/dist/surfaceCompare.d.ts.map +1 -0
  35. package/dist/surfaceCompare.js +64 -0
  36. package/dist/surfaceCompare.js.map +1 -0
  37. package/dist/surfaceComposite.d.ts +53 -0
  38. package/dist/surfaceComposite.d.ts.map +1 -0
  39. package/dist/surfaceComposite.js +230 -0
  40. package/dist/surfaceComposite.js.map +1 -0
  41. package/dist/surfaceConvolution.d.ts +27 -0
  42. package/dist/surfaceConvolution.d.ts.map +1 -0
  43. package/dist/surfaceConvolution.js +103 -0
  44. package/dist/surfaceConvolution.js.map +1 -0
  45. package/dist/surfaceCopy.d.ts +23 -0
  46. package/dist/surfaceCopy.d.ts.map +1 -0
  47. package/dist/surfaceCopy.js +78 -0
  48. package/dist/surfaceCopy.js.map +1 -0
  49. package/dist/surfaceCoverage.d.ts +11 -0
  50. package/dist/surfaceCoverage.d.ts.map +1 -0
  51. package/dist/surfaceCoverage.js +29 -0
  52. package/dist/surfaceCoverage.js.map +1 -0
  53. package/dist/surfaceCrop.d.ts +33 -0
  54. package/dist/surfaceCrop.d.ts.map +1 -0
  55. package/dist/surfaceCrop.js +174 -0
  56. package/dist/surfaceCrop.js.map +1 -0
  57. package/dist/surfaceDisplacement.d.ts +48 -0
  58. package/dist/surfaceDisplacement.d.ts.map +1 -0
  59. package/dist/surfaceDisplacement.js +131 -0
  60. package/dist/surfaceDisplacement.js.map +1 -0
  61. package/dist/surfaceDissolve.d.ts +21 -0
  62. package/dist/surfaceDissolve.d.ts.map +1 -0
  63. package/dist/surfaceDissolve.js +97 -0
  64. package/dist/surfaceDissolve.js.map +1 -0
  65. package/dist/surfaceDraw.d.ts +8 -0
  66. package/dist/surfaceDraw.d.ts.map +1 -0
  67. package/dist/surfaceDraw.js +14 -0
  68. package/dist/surfaceDraw.js.map +1 -0
  69. package/dist/surfaceEncode.d.ts +3 -0
  70. package/dist/surfaceEncode.d.ts.map +1 -0
  71. package/dist/surfaceEncode.js +18 -0
  72. package/dist/surfaceEncode.js.map +1 -0
  73. package/dist/surfaceFill.d.ts +12 -0
  74. package/dist/surfaceFill.d.ts.map +1 -0
  75. package/dist/surfaceFill.js +85 -0
  76. package/dist/surfaceFill.js.map +1 -0
  77. package/dist/surfaceFingerprint.d.ts +26 -0
  78. package/dist/surfaceFingerprint.d.ts.map +1 -0
  79. package/dist/surfaceFingerprint.js +99 -0
  80. package/dist/surfaceFingerprint.js.map +1 -0
  81. package/dist/surfaceFlip.d.ts +16 -0
  82. package/dist/surfaceFlip.d.ts.map +1 -0
  83. package/dist/surfaceFlip.js +98 -0
  84. package/dist/surfaceFlip.js.map +1 -0
  85. package/dist/surfaceFormat.d.ts +26 -0
  86. package/dist/surfaceFormat.d.ts.map +1 -0
  87. package/dist/surfaceFormat.js +80 -0
  88. package/dist/surfaceFormat.js.map +1 -0
  89. package/dist/surfaceFrom.d.ts +14 -0
  90. package/dist/surfaceFrom.d.ts.map +1 -0
  91. package/dist/surfaceFrom.js +87 -0
  92. package/dist/surfaceFrom.js.map +1 -0
  93. package/dist/surfaceGradient.d.ts +57 -0
  94. package/dist/surfaceGradient.d.ts.map +1 -0
  95. package/dist/surfaceGradient.js +176 -0
  96. package/dist/surfaceGradient.js.map +1 -0
  97. package/dist/surfaceGradientFill.d.ts +32 -0
  98. package/dist/surfaceGradientFill.d.ts.map +1 -0
  99. package/dist/surfaceGradientFill.js +120 -0
  100. package/dist/surfaceGradientFill.js.map +1 -0
  101. package/dist/surfaceHistogram.d.ts +20 -0
  102. package/dist/surfaceHistogram.d.ts.map +1 -0
  103. package/dist/surfaceHistogram.js +61 -0
  104. package/dist/surfaceHistogram.js.map +1 -0
  105. package/dist/surfaceImageChannel.d.ts +2 -0
  106. package/dist/surfaceImageChannel.d.ts.map +1 -0
  107. package/dist/surfaceImageChannel.js +2 -0
  108. package/dist/surfaceImageChannel.js.map +1 -0
  109. package/dist/surfaceMedian.d.ts +14 -0
  110. package/dist/surfaceMedian.d.ts.map +1 -0
  111. package/dist/surfaceMedian.js +77 -0
  112. package/dist/surfaceMedian.js.map +1 -0
  113. package/dist/surfaceMorphological.d.ts +29 -0
  114. package/dist/surfaceMorphological.d.ts.map +1 -0
  115. package/dist/surfaceMorphological.js +81 -0
  116. package/dist/surfaceMorphological.js.map +1 -0
  117. package/dist/surfaceNoise.d.ts +48 -0
  118. package/dist/surfaceNoise.d.ts.map +1 -0
  119. package/dist/surfaceNoise.js +245 -0
  120. package/dist/surfaceNoise.js.map +1 -0
  121. package/dist/surfacePaletteMap.d.ts +17 -0
  122. package/dist/surfacePaletteMap.d.ts.map +1 -0
  123. package/dist/surfacePaletteMap.js +45 -0
  124. package/dist/surfacePaletteMap.js.map +1 -0
  125. package/dist/surfacePixel.d.ts +9 -0
  126. package/dist/surfacePixel.d.ts.map +1 -0
  127. package/dist/surfacePixel.js +36 -0
  128. package/dist/surfacePixel.js.map +1 -0
  129. package/dist/surfacePixelate.d.ts +13 -0
  130. package/dist/surfacePixelate.d.ts.map +1 -0
  131. package/dist/surfacePixelate.js +61 -0
  132. package/dist/surfacePixelate.js.map +1 -0
  133. package/dist/surfaceQuery.d.ts +13 -0
  134. package/dist/surfaceQuery.d.ts.map +1 -0
  135. package/dist/surfaceQuery.js +46 -0
  136. package/dist/surfaceQuery.js.map +1 -0
  137. package/dist/surfaceRegion.d.ts +20 -0
  138. package/dist/surfaceRegion.d.ts.map +1 -0
  139. package/dist/surfaceRegion.js +28 -0
  140. package/dist/surfaceRegion.js.map +1 -0
  141. package/dist/surfaceResize.d.ts +27 -0
  142. package/dist/surfaceResize.d.ts.map +1 -0
  143. package/dist/surfaceResize.js +191 -0
  144. package/dist/surfaceResize.js.map +1 -0
  145. package/dist/surfaceRotate.d.ts +32 -0
  146. package/dist/surfaceRotate.d.ts.map +1 -0
  147. package/dist/surfaceRotate.js +143 -0
  148. package/dist/surfaceRotate.js.map +1 -0
  149. package/dist/surfaceShadow.d.ts +107 -0
  150. package/dist/surfaceShadow.d.ts.map +1 -0
  151. package/dist/surfaceShadow.js +173 -0
  152. package/dist/surfaceShadow.js.map +1 -0
  153. package/dist/surfaceSharpen.d.ts +25 -0
  154. package/dist/surfaceSharpen.d.ts.map +1 -0
  155. package/dist/surfaceSharpen.js +47 -0
  156. package/dist/surfaceSharpen.js.map +1 -0
  157. package/dist/surfaceTone.d.ts +28 -0
  158. package/dist/surfaceTone.d.ts.map +1 -0
  159. package/dist/surfaceTone.js +69 -0
  160. package/dist/surfaceTone.js.map +1 -0
  161. package/dist/surfaceTransform.d.ts +40 -0
  162. package/dist/surfaceTransform.d.ts.map +1 -0
  163. package/dist/surfaceTransform.js +163 -0
  164. package/dist/surfaceTransform.js.map +1 -0
  165. package/dist/surfaceWarp.d.ts +48 -0
  166. package/dist/surfaceWarp.d.ts.map +1 -0
  167. package/dist/surfaceWarp.js +284 -0
  168. package/dist/surfaceWarp.js.map +1 -0
  169. package/package.json +39 -0
  170. package/src/surface.test.ts +78 -0
  171. package/src/surfaceAffine.test.ts +98 -0
  172. package/src/surfaceAlpha.test.ts +113 -0
  173. package/src/surfaceBevel.test.ts +67 -0
  174. package/src/surfaceBlur.test.ts +240 -0
  175. package/src/surfaceChannel.test.ts +97 -0
  176. package/src/surfaceColorMatrix.test.ts +220 -0
  177. package/src/surfaceCompare.test.ts +92 -0
  178. package/src/surfaceComposite.test.ts +256 -0
  179. package/src/surfaceConvolution.test.ts +136 -0
  180. package/src/surfaceCopy.test.ts +54 -0
  181. package/src/surfaceCoverage.test.ts +39 -0
  182. package/src/surfaceCrop.test.ts +116 -0
  183. package/src/surfaceDisplacement.test.ts +142 -0
  184. package/src/surfaceDissolve.test.ts +99 -0
  185. package/src/surfaceDraw.test.ts +38 -0
  186. package/src/surfaceEncode.test.ts +18 -0
  187. package/src/surfaceFill.test.ts +89 -0
  188. package/src/surfaceFingerprint.test.ts +103 -0
  189. package/src/surfaceFlip.test.ts +59 -0
  190. package/src/surfaceFormat.test.ts +124 -0
  191. package/src/surfaceFrom.test.ts +62 -0
  192. package/src/surfaceGradient.test.ts +91 -0
  193. package/src/surfaceGradientFill.test.ts +107 -0
  194. package/src/surfaceHistogram.test.ts +70 -0
  195. package/src/surfaceImageChannel.test.ts +19 -0
  196. package/src/surfaceMedian.test.ts +45 -0
  197. package/src/surfaceMorphological.test.ts +75 -0
  198. package/src/surfaceNoise.test.ts +169 -0
  199. package/src/surfacePaletteMap.test.ts +55 -0
  200. package/src/surfacePixel.test.ts +99 -0
  201. package/src/surfacePixelate.test.ts +46 -0
  202. package/src/surfaceQuery.test.ts +48 -0
  203. package/src/surfaceRegion.test.ts +34 -0
  204. package/src/surfaceResize.test.ts +112 -0
  205. package/src/surfaceRotate.test.ts +119 -0
  206. package/src/surfaceShadow.test.ts +165 -0
  207. package/src/surfaceSharpen.test.ts +50 -0
  208. package/src/surfaceTone.test.ts +104 -0
  209. package/src/surfaceTransform.test.ts +134 -0
  210. package/src/surfaceWarp.test.ts +124 -0
@@ -0,0 +1,120 @@
1
+ import { invalidateImageResource } from '@flighthq/image';
2
+ /**
3
+ * Fills the `dest` region with a linear gradient defined by two points `(x0, y0)`
4
+ * and `(x1, y1)` in region-local coordinates. Each pixel's position along the
5
+ * gradient axis maps to a ramp index (0–255), which is looked up in the 256-entry
6
+ * RGBA `ramp` (1024 bytes). Build the ramp with `buildSurfaceGradientRamp`.
7
+ *
8
+ * `spread` controls what happens outside the axis span:
9
+ * - `'pad'` (default): extends the first or last stop color.
10
+ * - `'repeat'`: tiles the gradient.
11
+ * - `'reflect'`: mirrors the gradient alternately.
12
+ *
13
+ * Pixels outside the surface bounds are skipped.
14
+ */
15
+ export function fillSurfaceLinearGradient(dest, ramp, x0, y0, x1, y1, spread = 'pad') {
16
+ const dw = dest.width;
17
+ const dh = dest.height;
18
+ const data = dest.surface.data;
19
+ const surfaceWidth = dest.surface.width;
20
+ const surfaceHeight = dest.surface.height;
21
+ const axisX = x1 - x0;
22
+ const axisY = y1 - y0;
23
+ const lenSq = axisX * axisX + axisY * axisY;
24
+ const invLen = lenSq > 0 ? 1 / lenSq : 0;
25
+ for (let py = 0; py < dh; py++) {
26
+ const y = dest.y + py;
27
+ if (y < 0 || y >= surfaceHeight)
28
+ continue;
29
+ for (let px = 0; px < dw; px++) {
30
+ const x = dest.x + px;
31
+ if (x < 0 || x >= surfaceWidth)
32
+ continue;
33
+ // Project pixel onto gradient axis → t in [0, 1] maps x0→x1.
34
+ const t = ((px - x0) * axisX + (py - y0) * axisY) * invLen;
35
+ const idx = spreadIndex(t, spread);
36
+ const ri = idx * 4;
37
+ const i = (y * surfaceWidth + x) * 4;
38
+ data[i] = ramp[ri];
39
+ data[i + 1] = ramp[ri + 1];
40
+ data[i + 2] = ramp[ri + 2];
41
+ data[i + 3] = ramp[ri + 3];
42
+ }
43
+ }
44
+ invalidateImageResource(dest.surface);
45
+ }
46
+ /**
47
+ * Fills the `dest` region with a radial gradient centered at `(cx, cy)` in
48
+ * region-local coordinates with the given `radius`. An optional focal point
49
+ * `(focalX, focalY)` shifts the gradient origin (defaults to the center).
50
+ * Each pixel's normalized distance maps to a ramp index (0–255), looked up in
51
+ * the 256-entry RGBA `ramp` (1024 bytes). Build the ramp with
52
+ * `buildSurfaceGradientRamp`.
53
+ *
54
+ * `spread` controls what happens outside the radius:
55
+ * - `'pad'` (default): extends the last stop color.
56
+ * - `'repeat'`: tiles the gradient.
57
+ * - `'reflect'`: mirrors the gradient alternately.
58
+ *
59
+ * Pixels outside the surface bounds are skipped.
60
+ */
61
+ export function fillSurfaceRadialGradient(dest, ramp, cx, cy, radius, focalX = cx, focalY = cy, spread = 'pad') {
62
+ const dw = dest.width;
63
+ const dh = dest.height;
64
+ const data = dest.surface.data;
65
+ const surfaceWidth = dest.surface.width;
66
+ const surfaceHeight = dest.surface.height;
67
+ const invRadius = radius > 0 ? 1 / radius : 0;
68
+ // Focal-point offset from center.
69
+ const fdx = focalX - cx;
70
+ const fdy = focalY - cy;
71
+ for (let py = 0; py < dh; py++) {
72
+ const y = dest.y + py;
73
+ if (y < 0 || y >= surfaceHeight)
74
+ continue;
75
+ for (let px = 0; px < dw; px++) {
76
+ const x = dest.x + px;
77
+ if (x < 0 || x >= surfaceWidth)
78
+ continue;
79
+ // Distance from focal point, normalized by radius → t in [0, 1].
80
+ const dx = px - focalX;
81
+ const dy = py - focalY;
82
+ // Use the cone-ray formula for two-point focal gradient (standard SVG model).
83
+ // When focal === center this simplifies to Euclidean distance / radius.
84
+ const t = Math.sqrt(dx * dx + dy * dy) * invRadius - (dx * fdx + dy * fdy) * invRadius * invRadius;
85
+ const idx = spreadIndex(t, spread);
86
+ const ri = idx * 4;
87
+ const i = (y * surfaceWidth + x) * 4;
88
+ data[i] = ramp[ri];
89
+ data[i + 1] = ramp[ri + 1];
90
+ data[i + 2] = ramp[ri + 2];
91
+ data[i + 3] = ramp[ri + 3];
92
+ }
93
+ }
94
+ invalidateImageResource(dest.surface);
95
+ }
96
+ /**
97
+ * Converts a normalized gradient parameter `t` (range [0, 1]) into a ramp
98
+ * index (0–255), applying the requested `spread` mode for values outside [0, 1].
99
+ */
100
+ function spreadIndex(t, spread) {
101
+ let s;
102
+ switch (spread) {
103
+ case 'repeat': {
104
+ s = t - Math.floor(t);
105
+ break;
106
+ }
107
+ case 'reflect': {
108
+ const wrapped = t - Math.floor(t / 2) * 2;
109
+ s = wrapped <= 1 ? wrapped : 2 - wrapped;
110
+ break;
111
+ }
112
+ default: {
113
+ // 'pad'
114
+ s = Math.max(0, Math.min(1, t));
115
+ break;
116
+ }
117
+ }
118
+ return Math.min(255, Math.round(s * 255));
119
+ }
120
+ //# sourceMappingURL=surfaceGradientFill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceGradientFill.js","sourceRoot":"","sources":["../src/surfaceGradientFill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAG1D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,yBAAyB,CACvC,IAA6B,EAC7B,IAAiC,EACjC,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,SAAyB,KAAK;IAE9B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;IACtB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;IACvB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;IACxC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC1C,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IAC5C,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,aAAa;YAAE,SAAS;QAC1C,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,YAAY;gBAAE,SAAS;YACzC,6DAA6D;YAC7D,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,GAAG,MAAM,CAAC;YAC3D,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YACnC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;YACnB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,yBAAyB,CACvC,IAA6B,EAC7B,IAAiC,EACjC,EAAU,EACV,EAAU,EACV,MAAc,EACd,SAAiB,EAAE,EACnB,SAAiB,EAAE,EACnB,SAAyB,KAAK;IAE9B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;IACtB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;IACvB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;IACxC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC1C,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,kCAAkC;IAClC,MAAM,GAAG,GAAG,MAAM,GAAG,EAAE,CAAC;IACxB,MAAM,GAAG,GAAG,MAAM,GAAG,EAAE,CAAC;IACxB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,aAAa;YAAE,SAAS;QAC1C,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,YAAY;gBAAE,SAAS;YACzC,iEAAiE;YACjE,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;YACvB,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;YACvB,8EAA8E;YAC9E,wEAAwE;YACxE,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,SAAS,GAAG,SAAS,CAAC;YACnG,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YACnC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;YACnB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,CAAS,EAAE,MAAsB;IACpD,IAAI,CAAS,CAAC;IACd,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM;QACR,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAC1C,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;YACzC,MAAM;QACR,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,QAAQ;YACR,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAChC,MAAM;QACR,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { SurfaceHistogram, SurfaceRegion } from '@flighthq/types';
2
+ /**
3
+ * Applies histogram equalization to `source`, writing into `dest`. Each RGB
4
+ * channel is equalized independently using its cumulative distribution function,
5
+ * spreading the tonal range across the full 0..255 output. The alpha channel is
6
+ * copied unchanged.
7
+ *
8
+ * Safe to pass the same surface and region in `dest` and `source` for in-place
9
+ * equalization (the palette map reads each pixel before writing it).
10
+ */
11
+ export declare function equalizeSurfaceHistogram(dest: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>): void;
12
+ /**
13
+ * Counts how many pixels in the `source` region fall into each 0..255 value,
14
+ * per channel, and returns four 256-entry arrays. Region pixels outside the
15
+ * surface are skipped; an empty region yields all-zero bins.
16
+ *
17
+ * Allocates the result arrays; this is an analysis query, not a hot-path pass.
18
+ */
19
+ export declare function getSurfaceHistogram(source: Readonly<SurfaceRegion>): SurfaceHistogram;
20
+ //# sourceMappingURL=surfaceHistogram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceHistogram.d.ts","sourceRoot":"","sources":["../src/surfaceHistogram.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIvE;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,IAAI,CAa7G;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,gBAAgB,CAqBrF"}
@@ -0,0 +1,61 @@
1
+ import { invalidateImageResource } from '@flighthq/image';
2
+ import { applySurfacePaletteMap } from './surfacePaletteMap';
3
+ /**
4
+ * Applies histogram equalization to `source`, writing into `dest`. Each RGB
5
+ * channel is equalized independently using its cumulative distribution function,
6
+ * spreading the tonal range across the full 0..255 output. The alpha channel is
7
+ * copied unchanged.
8
+ *
9
+ * Safe to pass the same surface and region in `dest` and `source` for in-place
10
+ * equalization (the palette map reads each pixel before writing it).
11
+ */
12
+ export function equalizeSurfaceHistogram(dest, source) {
13
+ const histogram = getSurfaceHistogram(source);
14
+ const total = source.width * source.height;
15
+ applySurfacePaletteMap(dest, source, buildEqualizeMap(histogram.red, total), buildEqualizeMap(histogram.green, total), buildEqualizeMap(histogram.blue, total), null);
16
+ invalidateImageResource(dest.surface);
17
+ }
18
+ /**
19
+ * Counts how many pixels in the `source` region fall into each 0..255 value,
20
+ * per channel, and returns four 256-entry arrays. Region pixels outside the
21
+ * surface are skipped; an empty region yields all-zero bins.
22
+ *
23
+ * Allocates the result arrays; this is an analysis query, not a hot-path pass.
24
+ */
25
+ export function getSurfaceHistogram(source) {
26
+ const red = new Array(256).fill(0);
27
+ const green = new Array(256).fill(0);
28
+ const blue = new Array(256).fill(0);
29
+ const alpha = new Array(256).fill(0);
30
+ const data = source.surface.data;
31
+ const surfaceWidth = source.surface.width;
32
+ for (let py = 0; py < source.height; py++) {
33
+ const y = source.y + py;
34
+ if (y < 0 || y >= source.surface.height)
35
+ continue;
36
+ for (let px = 0; px < source.width; px++) {
37
+ const x = source.x + px;
38
+ if (x < 0 || x >= surfaceWidth)
39
+ continue;
40
+ const i = (y * surfaceWidth + x) * 4;
41
+ red[data[i]]++;
42
+ green[data[i + 1]]++;
43
+ blue[data[i + 2]]++;
44
+ alpha[data[i + 3]]++;
45
+ }
46
+ }
47
+ return { alpha, blue, green, red };
48
+ }
49
+ function buildEqualizeMap(bins, total) {
50
+ const map = new Array(256);
51
+ let cdf = 0;
52
+ let cdfMin = -1;
53
+ for (let i = 0; i < 256; i++) {
54
+ cdf += bins[i];
55
+ if (bins[i] > 0 && cdfMin === -1)
56
+ cdfMin = cdf;
57
+ map[i] = total === cdfMin ? i : Math.round(((cdf - cdfMin) / (total - cdfMin)) * 255);
58
+ }
59
+ return map;
60
+ }
61
+ //# sourceMappingURL=surfaceHistogram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceHistogram.js","sourceRoot":"","sources":["../src/surfaceHistogram.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { ImageChannel } from '@flighthq/types';
2
+ //# sourceMappingURL=surfaceImageChannel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceImageChannel.d.ts","sourceRoot":"","sources":["../src/surfaceImageChannel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { ImageChannel } from '@flighthq/types';
2
+ //# sourceMappingURL=surfaceImageChannel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceImageChannel.js","sourceRoot":"","sources":["../src/surfaceImageChannel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { SurfaceRegion } from '@flighthq/types';
2
+ /**
3
+ * Applies a median filter to `source`, writing into `out`. Each output channel
4
+ * is the median of that channel over the `(2 * radius + 1)²` neighborhood,
5
+ * clamped at the surface edges. Median filtering removes salt-and-pepper noise
6
+ * and despeckles while preserving edges — something a linear convolution blur
7
+ * cannot do.
8
+ *
9
+ * `out` must be at least `source.width * source.height * 4` bytes and must NOT
10
+ * alias `source.surface.data` — each output pixel reads a neighborhood of
11
+ * source pixels.
12
+ */
13
+ export declare function medianSurface(out: Uint8ClampedArray, source: Readonly<SurfaceRegion>, radius: number): void;
14
+ //# sourceMappingURL=surfaceMedian.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceMedian.d.ts","sourceRoot":"","sources":["../src/surfaceMedian.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA4C3G"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Applies a median filter to `source`, writing into `out`. Each output channel
3
+ * is the median of that channel over the `(2 * radius + 1)²` neighborhood,
4
+ * clamped at the surface edges. Median filtering removes salt-and-pepper noise
5
+ * and despeckles while preserving edges — something a linear convolution blur
6
+ * cannot do.
7
+ *
8
+ * `out` must be at least `source.width * source.height * 4` bytes and must NOT
9
+ * alias `source.surface.data` — each output pixel reads a neighborhood of
10
+ * source pixels.
11
+ */
12
+ export function medianSurface(out, source, radius) {
13
+ const r = Math.max(0, Math.round(radius));
14
+ const w = source.width;
15
+ const h = source.height;
16
+ const surfaceWidth = source.surface.width;
17
+ const surfaceHeight = source.surface.height;
18
+ const data = source.surface.data;
19
+ const area = (2 * r + 1) * (2 * r + 1);
20
+ // Window scratch is reused across calls and grown as needed — a median pass
21
+ // is allocation-free after its first use at a given radius.
22
+ if (_windowRed === null || _windowRed.length < area) {
23
+ _windowRed = new Uint8Array(area);
24
+ _windowGreen = new Uint8Array(area);
25
+ _windowBlue = new Uint8Array(area);
26
+ _windowAlpha = new Uint8Array(area);
27
+ }
28
+ const rs = _windowRed;
29
+ const gs = _windowGreen;
30
+ const bs = _windowBlue;
31
+ const as = _windowAlpha;
32
+ for (let py = 0; py < h; py++) {
33
+ for (let px = 0; px < w; px++) {
34
+ let n = 0;
35
+ for (let ky = -r; ky <= r; ky++) {
36
+ const sy = Math.max(0, Math.min(surfaceHeight - 1, source.y + py + ky));
37
+ for (let kx = -r; kx <= r; kx++) {
38
+ const sx = Math.max(0, Math.min(surfaceWidth - 1, source.x + px + kx));
39
+ const si = (sy * surfaceWidth + sx) * 4;
40
+ rs[n] = data[si];
41
+ gs[n] = data[si + 1];
42
+ bs[n] = data[si + 2];
43
+ as[n] = data[si + 3];
44
+ n++;
45
+ }
46
+ }
47
+ const mid = n >> 1;
48
+ const di = (py * w + px) * 4;
49
+ out[di] = medianOf(rs, n, mid);
50
+ out[di + 1] = medianOf(gs, n, mid);
51
+ out[di + 2] = medianOf(bs, n, mid);
52
+ out[di + 3] = medianOf(as, n, mid);
53
+ }
54
+ }
55
+ }
56
+ // Insertion sort of the first `n` entries, then return the element at `mid`.
57
+ // `n` is small (an odd square), so insertion sort beats Array.sort's overhead
58
+ // and avoids per-pixel allocation.
59
+ function medianOf(values, n, mid) {
60
+ for (let i = 1; i < n; i++) {
61
+ const v = values[i];
62
+ let j = i - 1;
63
+ while (j >= 0 && values[j] > v) {
64
+ values[j + 1] = values[j];
65
+ j--;
66
+ }
67
+ values[j + 1] = v;
68
+ }
69
+ return values[mid];
70
+ }
71
+ // Per-window channel scratch, reused across calls and grown to the largest
72
+ // neighborhood seen so far.
73
+ let _windowRed = null;
74
+ let _windowGreen = null;
75
+ let _windowBlue = null;
76
+ let _windowAlpha = null;
77
+ //# sourceMappingURL=surfaceMedian.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceMedian.js","sourceRoot":"","sources":["../src/surfaceMedian.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { SurfaceRegion } from '@flighthq/types';
2
+ /**
3
+ * Applies morphological dilation to `source`, writing into `out`. Each output
4
+ * channel is the maximum of that channel over the `(2 * radius + 1)²`
5
+ * neighbourhood; all four channels (RGBA) are dilated independently.
6
+ *
7
+ * Dilation expands bright regions and thickens shapes. It is the dual of
8
+ * `erodeSurface` — applying erosion then dilation gives a morphological opening,
9
+ * the reverse gives a closing.
10
+ *
11
+ * `out` must be at least `source.width * source.height * 4` bytes and must NOT
12
+ * alias `source.surface.data` — each output pixel reads a neighbourhood of
13
+ * source pixels.
14
+ */
15
+ export declare function dilateSurface(out: Uint8ClampedArray, source: Readonly<SurfaceRegion>, radius: number): void;
16
+ /**
17
+ * Applies morphological erosion to `source`, writing into `out`. Each output
18
+ * channel is the minimum of that channel over the `(2 * radius + 1)²`
19
+ * neighbourhood; all four channels (RGBA) are eroded independently.
20
+ *
21
+ * Erosion shrinks bright regions and thins shapes. It is the dual of
22
+ * `dilateSurface`.
23
+ *
24
+ * `out` must be at least `source.width * source.height * 4` bytes and must NOT
25
+ * alias `source.surface.data` — each output pixel reads a neighbourhood of
26
+ * source pixels.
27
+ */
28
+ export declare function erodeSurface(out: Uint8ClampedArray, source: Readonly<SurfaceRegion>, radius: number): void;
29
+ //# sourceMappingURL=surfaceMorphological.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceMorphological.d.ts","sourceRoot":"","sources":["../src/surfaceMorphological.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAE3G;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAE1G"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Applies morphological dilation to `source`, writing into `out`. Each output
3
+ * channel is the maximum of that channel over the `(2 * radius + 1)²`
4
+ * neighbourhood; all four channels (RGBA) are dilated independently.
5
+ *
6
+ * Dilation expands bright regions and thickens shapes. It is the dual of
7
+ * `erodeSurface` — applying erosion then dilation gives a morphological opening,
8
+ * the reverse gives a closing.
9
+ *
10
+ * `out` must be at least `source.width * source.height * 4` bytes and must NOT
11
+ * alias `source.surface.data` — each output pixel reads a neighbourhood of
12
+ * source pixels.
13
+ */
14
+ export function dilateSurface(out, source, radius) {
15
+ applyMorphological(out, source, radius, true);
16
+ }
17
+ /**
18
+ * Applies morphological erosion to `source`, writing into `out`. Each output
19
+ * channel is the minimum of that channel over the `(2 * radius + 1)²`
20
+ * neighbourhood; all four channels (RGBA) are eroded independently.
21
+ *
22
+ * Erosion shrinks bright regions and thins shapes. It is the dual of
23
+ * `dilateSurface`.
24
+ *
25
+ * `out` must be at least `source.width * source.height * 4` bytes and must NOT
26
+ * alias `source.surface.data` — each output pixel reads a neighbourhood of
27
+ * source pixels.
28
+ */
29
+ export function erodeSurface(out, source, radius) {
30
+ applyMorphological(out, source, radius, false);
31
+ }
32
+ function applyMorphological(out, source, radius, dilate) {
33
+ const r = Math.max(0, Math.round(radius));
34
+ const w = source.width;
35
+ const h = source.height;
36
+ const surfaceWidth = source.surface.width;
37
+ const surfaceHeight = source.surface.height;
38
+ const data = source.surface.data;
39
+ const identity = dilate ? 0 : 255;
40
+ for (let py = 0; py < h; py++) {
41
+ for (let px = 0; px < w; px++) {
42
+ let vR = identity;
43
+ let vG = identity;
44
+ let vB = identity;
45
+ let vA = identity;
46
+ for (let ky = -r; ky <= r; ky++) {
47
+ const sy = Math.max(0, Math.min(surfaceHeight - 1, source.y + py + ky));
48
+ for (let kx = -r; kx <= r; kx++) {
49
+ const sx = Math.max(0, Math.min(surfaceWidth - 1, source.x + px + kx));
50
+ const si = (sy * surfaceWidth + sx) * 4;
51
+ if (dilate) {
52
+ if (data[si] > vR)
53
+ vR = data[si];
54
+ if (data[si + 1] > vG)
55
+ vG = data[si + 1];
56
+ if (data[si + 2] > vB)
57
+ vB = data[si + 2];
58
+ if (data[si + 3] > vA)
59
+ vA = data[si + 3];
60
+ }
61
+ else {
62
+ if (data[si] < vR)
63
+ vR = data[si];
64
+ if (data[si + 1] < vG)
65
+ vG = data[si + 1];
66
+ if (data[si + 2] < vB)
67
+ vB = data[si + 2];
68
+ if (data[si + 3] < vA)
69
+ vA = data[si + 3];
70
+ }
71
+ }
72
+ }
73
+ const di = (py * w + px) * 4;
74
+ out[di] = vR;
75
+ out[di + 1] = vG;
76
+ out[di + 2] = vB;
77
+ out[di + 3] = vA;
78
+ }
79
+ }
80
+ }
81
+ //# sourceMappingURL=surfaceMorphological.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceMorphological.js","sourceRoot":"","sources":["../src/surfaceMorphological.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { SurfaceRegion } from '@flighthq/types';
2
+ /**
3
+ * Fills the `dest` region with uniform random noise in `[low, high]`, derived
4
+ * deterministically from `seed` (the same seed always produces the same image,
5
+ * which a `Math.random()` fill could not guarantee — important for reproducible
6
+ * tests and a future C port). Region pixels outside the surface are skipped.
7
+ *
8
+ * When `grayScale` is true, R, G, and B share one value per pixel; otherwise
9
+ * each channel is independent. Alpha is set fully opaque (255).
10
+ */
11
+ export declare function fillSurfaceNoise(dest: Readonly<SurfaceRegion>, seed: number, low?: number, high?: number, grayScale?: boolean): void;
12
+ /**
13
+ * Fills `out` with fractal value noise summed over `octaves`. `baseX` and
14
+ * `baseY` are the wavelengths (in pixels) of the first octave: larger values
15
+ * produce smoother, lower-frequency noise. Each successive octave doubles the
16
+ * frequency and halves the amplitude. Output is normalized to 0..255.
17
+ *
18
+ * - `baseX`, `baseY`: wavelengths in pixels of the first octave (larger = smoother).
19
+ * - `octaves`: number of frequency doublings (1 = smooth; higher = more detail).
20
+ * - `seed`: deterministic integer seed.
21
+ * - `stitch`: when `true`, the noise field tiles seamlessly at the region borders.
22
+ * - `grayScale`: when `true`, R=G=B share one noise channel. Overrides
23
+ * `channelOptions` for the RGB channels.
24
+ * - `channelOptions`: bitmask of channels to fill (default `0x7` = RGB, matching
25
+ * OpenFL's `perlinNoise` default). Channels not selected are left unchanged in
26
+ * `dest`, except alpha: when the A bit is not selected, alpha is set opaque
27
+ * (255) rather than left as-is. Use `SURFACE_NOISE_CHANNEL_*` constants. When
28
+ * `grayScale` is true the same field drives all selected RGB channels.
29
+ *
30
+ * Output range is normalized to 0..255. Alpha defaults to 255 unless the A
31
+ * bit is explicitly included in `channelOptions`.
32
+ */
33
+ export declare function fillSurfacePerlinNoise(dest: Readonly<SurfaceRegion>, baseX: number, baseY: number, octaves: number, seed: number, grayScale?: boolean, stitch?: boolean, channelOptions?: number): void;
34
+ /**
35
+ * Fills `dest` with fractal **turbulence** (absolute-value fBm) value noise,
36
+ * matching OpenFL's `BitmapData.perlinNoise` with `fractalNoise: false`.
37
+ * Turbulence sums `abs(octave)` values, producing a more vigorous, ridge-like
38
+ * texture than the smooth fractal sum.
39
+ *
40
+ * Parameters are identical to `fillSurfacePerlinNoise` except there is no
41
+ * `fractalNoise` flag (this function _is_ the turbulence variant).
42
+ */
43
+ export declare function fillSurfaceTurbulence(dest: Readonly<SurfaceRegion>, baseX: number, baseY: number, octaves: number, seed: number, grayScale?: boolean, stitch?: boolean, channelOptions?: number): void;
44
+ export declare const SURFACE_NOISE_CHANNEL_A = 8;
45
+ export declare const SURFACE_NOISE_CHANNEL_B = 4;
46
+ export declare const SURFACE_NOISE_CHANNEL_G = 2;
47
+ export declare const SURFACE_NOISE_CHANNEL_R = 1;
48
+ //# sourceMappingURL=surfaceNoise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceNoise.d.ts","sourceRoot":"","sources":["../src/surfaceNoise.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAAU,EACf,IAAI,GAAE,MAAY,EAClB,SAAS,GAAE,OAAe,GACzB,IAAI,CA+BN;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,OAAe,EAC1B,MAAM,GAAE,OAAe,EACvB,cAAc,GAAE,MAAY,GAC3B,IAAI,CA4CN;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,OAAe,EAC1B,MAAM,GAAE,OAAe,EACvB,cAAc,GAAE,MAAY,GAC3B,IAAI,CA6CN;AAED,eAAO,MAAM,uBAAuB,IAAM,CAAC;AAC3C,eAAO,MAAM,uBAAuB,IAAM,CAAC;AAC3C,eAAO,MAAM,uBAAuB,IAAM,CAAC;AAC3C,eAAO,MAAM,uBAAuB,IAAM,CAAC"}