@flighthq/effects 0.1.0 → 0.2.1-next.410.a23f189

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 (168) hide show
  1. package/dist/bevelEffect.d.ts +3 -0
  2. package/dist/bevelEffect.d.ts.map +1 -0
  3. package/dist/bevelEffect.js +5 -0
  4. package/dist/bevelEffect.js.map +1 -0
  5. package/dist/blendEffect.d.ts +3 -0
  6. package/dist/blendEffect.d.ts.map +1 -0
  7. package/dist/blendEffect.js +10 -0
  8. package/dist/blendEffect.js.map +1 -0
  9. package/dist/blendModeMath.d.ts +6 -0
  10. package/dist/blendModeMath.d.ts.map +1 -0
  11. package/dist/blendModeMath.js +172 -0
  12. package/dist/blendModeMath.js.map +1 -0
  13. package/dist/blurDownsample.d.ts +17 -0
  14. package/dist/blurDownsample.d.ts.map +1 -0
  15. package/dist/blurDownsample.js +35 -0
  16. package/dist/blurDownsample.js.map +1 -0
  17. package/dist/blurEffect.d.ts +3 -0
  18. package/dist/blurEffect.d.ts.map +1 -0
  19. package/dist/blurEffect.js +7 -0
  20. package/dist/blurEffect.js.map +1 -0
  21. package/dist/boxBlurMath.d.ts +27 -0
  22. package/dist/boxBlurMath.d.ts.map +1 -0
  23. package/dist/boxBlurMath.js +64 -0
  24. package/dist/boxBlurMath.js.map +1 -0
  25. package/dist/compositeEffect.d.ts +3 -0
  26. package/dist/compositeEffect.d.ts.map +1 -0
  27. package/dist/compositeEffect.js +10 -0
  28. package/dist/compositeEffect.js.map +1 -0
  29. package/dist/compositeOperatorMath.d.ts +3 -0
  30. package/dist/compositeOperatorMath.d.ts.map +1 -0
  31. package/dist/compositeOperatorMath.js +65 -0
  32. package/dist/compositeOperatorMath.js.map +1 -0
  33. package/dist/convolutionEffect.d.ts +3 -0
  34. package/dist/convolutionEffect.d.ts.map +1 -0
  35. package/dist/convolutionEffect.js +4 -0
  36. package/dist/convolutionEffect.js.map +1 -0
  37. package/dist/dropShadowEffect.d.ts +3 -0
  38. package/dist/dropShadowEffect.d.ts.map +1 -0
  39. package/dist/dropShadowEffect.js +5 -0
  40. package/dist/dropShadowEffect.js.map +1 -0
  41. package/dist/gaussianKernel.d.ts +17 -0
  42. package/dist/gaussianKernel.d.ts.map +1 -0
  43. package/dist/gaussianKernel.js +49 -0
  44. package/dist/gaussianKernel.js.map +1 -0
  45. package/dist/gradientBevelEffect.d.ts +3 -0
  46. package/dist/gradientBevelEffect.d.ts.map +1 -0
  47. package/dist/gradientBevelEffect.js +5 -0
  48. package/dist/gradientBevelEffect.js.map +1 -0
  49. package/dist/gradientGlowEffect.d.ts +3 -0
  50. package/dist/gradientGlowEffect.d.ts.map +1 -0
  51. package/dist/gradientGlowEffect.js +5 -0
  52. package/dist/gradientGlowEffect.js.map +1 -0
  53. package/dist/index.d.ts +18 -13
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +18 -13
  56. package/dist/index.js.map +1 -1
  57. package/dist/innerGlowEffect.d.ts +3 -0
  58. package/dist/innerGlowEffect.d.ts.map +1 -0
  59. package/dist/innerGlowEffect.js +5 -0
  60. package/dist/innerGlowEffect.js.map +1 -0
  61. package/dist/innerShadowEffect.d.ts +3 -0
  62. package/dist/innerShadowEffect.d.ts.map +1 -0
  63. package/dist/innerShadowEffect.js +5 -0
  64. package/dist/innerShadowEffect.js.map +1 -0
  65. package/dist/linearSampledGaussian.d.ts +22 -0
  66. package/dist/linearSampledGaussian.d.ts.map +1 -0
  67. package/dist/linearSampledGaussian.js +56 -0
  68. package/dist/linearSampledGaussian.js.map +1 -0
  69. package/dist/medianEffect.d.ts +3 -0
  70. package/dist/medianEffect.d.ts.map +1 -0
  71. package/dist/medianEffect.js +4 -0
  72. package/dist/medianEffect.js.map +1 -0
  73. package/dist/outerGlowEffect.d.ts +3 -0
  74. package/dist/outerGlowEffect.d.ts.map +1 -0
  75. package/dist/outerGlowEffect.js +5 -0
  76. package/dist/outerGlowEffect.js.map +1 -0
  77. package/dist/renderEffectDefaults.js +51 -20
  78. package/dist/renderEffectDefaults.js.map +1 -1
  79. package/dist/renderEffectInputs.js +11 -11
  80. package/dist/renderEffectInputs.js.map +1 -1
  81. package/package.json +7 -2
  82. package/src/bevelEffect.test.ts +14 -0
  83. package/src/blendEffect.test.ts +23 -0
  84. package/src/blendModeMath.test.ts +160 -0
  85. package/src/blurDownsample.test.ts +46 -0
  86. package/src/blurEffect.test.ts +17 -0
  87. package/src/boxBlurMath.test.ts +96 -0
  88. package/src/compositeEffect.test.ts +21 -0
  89. package/src/compositeOperatorMath.test.ts +45 -0
  90. package/src/convolutionEffect.test.ts +20 -0
  91. package/src/dropShadowEffect.test.ts +14 -0
  92. package/src/gaussianKernel.test.ts +80 -0
  93. package/src/gradientBevelEffect.test.ts +21 -0
  94. package/src/gradientGlowEffect.test.ts +21 -0
  95. package/src/innerGlowEffect.test.ts +15 -0
  96. package/src/innerShadowEffect.test.ts +15 -0
  97. package/src/linearSampledGaussian.test.ts +87 -0
  98. package/src/medianEffect.test.ts +11 -0
  99. package/src/outerGlowEffect.test.ts +14 -0
  100. package/src/renderEffectDefaults.test.ts +13 -5
  101. package/src/renderEffectInputs.test.ts +3 -5
  102. package/src/renderEffectInterpolation.test.ts +6 -9
  103. package/src/renderEffectValidation.test.ts +2 -2
  104. package/dist/brightnessContrastEffect.d.ts +0 -3
  105. package/dist/brightnessContrastEffect.d.ts.map +0 -1
  106. package/dist/brightnessContrastEffect.js +0 -4
  107. package/dist/brightnessContrastEffect.js.map +0 -1
  108. package/dist/channelMixerEffect.d.ts +0 -3
  109. package/dist/channelMixerEffect.d.ts.map +0 -1
  110. package/dist/channelMixerEffect.js +0 -4
  111. package/dist/channelMixerEffect.js.map +0 -1
  112. package/dist/colorBlindSimulationEffect.d.ts +0 -3
  113. package/dist/colorBlindSimulationEffect.d.ts.map +0 -1
  114. package/dist/colorBlindSimulationEffect.js +0 -4
  115. package/dist/colorBlindSimulationEffect.js.map +0 -1
  116. package/dist/colorGradeEffect.d.ts +0 -3
  117. package/dist/colorGradeEffect.d.ts.map +0 -1
  118. package/dist/colorGradeEffect.js +0 -4
  119. package/dist/colorGradeEffect.js.map +0 -1
  120. package/dist/colorScienceMath.d.ts +0 -9
  121. package/dist/colorScienceMath.d.ts.map +0 -1
  122. package/dist/colorScienceMath.js +0 -135
  123. package/dist/colorScienceMath.js.map +0 -1
  124. package/dist/exposureEffect.d.ts +0 -3
  125. package/dist/exposureEffect.d.ts.map +0 -1
  126. package/dist/exposureEffect.js +0 -4
  127. package/dist/exposureEffect.js.map +0 -1
  128. package/dist/grayscaleEffect.d.ts +0 -3
  129. package/dist/grayscaleEffect.d.ts.map +0 -1
  130. package/dist/grayscaleEffect.js +0 -4
  131. package/dist/grayscaleEffect.js.map +0 -1
  132. package/dist/hueSaturationEffect.d.ts +0 -3
  133. package/dist/hueSaturationEffect.d.ts.map +0 -1
  134. package/dist/hueSaturationEffect.js +0 -4
  135. package/dist/hueSaturationEffect.js.map +0 -1
  136. package/dist/invertEffect.d.ts +0 -3
  137. package/dist/invertEffect.d.ts.map +0 -1
  138. package/dist/invertEffect.js +0 -4
  139. package/dist/invertEffect.js.map +0 -1
  140. package/dist/liftGammaGainEffect.d.ts +0 -3
  141. package/dist/liftGammaGainEffect.d.ts.map +0 -1
  142. package/dist/liftGammaGainEffect.js +0 -4
  143. package/dist/liftGammaGainEffect.js.map +0 -1
  144. package/dist/lookupTableGradeEffect.d.ts +0 -3
  145. package/dist/lookupTableGradeEffect.d.ts.map +0 -1
  146. package/dist/lookupTableGradeEffect.js +0 -4
  147. package/dist/lookupTableGradeEffect.js.map +0 -1
  148. package/dist/lutMath.d.ts +0 -7
  149. package/dist/lutMath.d.ts.map +0 -1
  150. package/dist/lutMath.js +0 -39
  151. package/dist/lutMath.js.map +0 -1
  152. package/dist/sepiaEffect.d.ts +0 -3
  153. package/dist/sepiaEffect.d.ts.map +0 -1
  154. package/dist/sepiaEffect.js +0 -4
  155. package/dist/sepiaEffect.js.map +0 -1
  156. package/src/brightnessContrastEffect.test.ts +0 -14
  157. package/src/channelMixerEffect.test.ts +0 -12
  158. package/src/colorBlindSimulationEffect.test.ts +0 -13
  159. package/src/colorGradeEffect.test.ts +0 -11
  160. package/src/colorScienceMath.test.ts +0 -160
  161. package/src/exposureEffect.test.ts +0 -7
  162. package/src/grayscaleEffect.test.ts +0 -11
  163. package/src/hueSaturationEffect.test.ts +0 -15
  164. package/src/invertEffect.test.ts +0 -11
  165. package/src/liftGammaGainEffect.test.ts +0 -15
  166. package/src/lookupTableGradeEffect.test.ts +0 -11
  167. package/src/lutMath.test.ts +0 -67
  168. package/src/sepiaEffect.test.ts +0 -11
package/dist/lutMath.js DELETED
@@ -1,39 +0,0 @@
1
- // LUT (lookup-table) recipe math for LookupTableGradeEffect. Substrate-agnostic helpers for
2
- // sampling 3D color LUTs stored as 2D strip-encoded textures. All functions are alias-safe.
3
- // Computes the UV coordinate in the 2D strip-encoded LUT texture that corresponds to an RGB color.
4
- // A 3D LUT of size N is encoded as a horizontal strip of N² tiles each of size N×1:
5
- // U encodes the B channel (tile index + R-within-tile).
6
- // V encodes the G channel (row within the strip, normalized to [0,1]).
7
- // Writes [u, v] into `out`. Caller applies bilinear filtering.
8
- // Alias-safe.
9
- export function computeLookupTableCoord(r, // normalized R channel [0..1].
10
- g, // normalized G channel [0..1].
11
- b, // normalized B channel [0..1].
12
- lutSize, // cube size of the LUT (e.g. 16, 32, 64).
13
- out) {
14
- const n = Math.max(1, lutSize);
15
- const halfTexel = 0.5 / n;
16
- // Clamp inputs to avoid bleeding at the LUT boundary.
17
- const rc = Math.max(0, Math.min(1, r));
18
- const gc = Math.max(0, Math.min(1, g));
19
- const bc = Math.max(0, Math.min(1, b));
20
- // B determines which horizontal tile (0..n-1).
21
- const bSlice = bc * (n - 1);
22
- const bIndex = Math.floor(bSlice);
23
- // U: tile offset + R within the tile.
24
- const u = (bIndex + rc * (1 - 1 / n) + halfTexel) / n;
25
- // V: G channel (one row per G step, stored bottom-to-top; some encoders are inverted — callers
26
- // can flip V if needed for their texture's storage convention).
27
- const v = gc * (1 - 1 / n) + halfTexel;
28
- out[0] = u;
29
- out[1] = v;
30
- }
31
- // Returns the [width, height] in pixels of the 2D strip texture required to store a 3D LUT of
32
- // the given cube size. Width = size², height = size (one row of G steps).
33
- // Writes [width, height] into `out`.
34
- export function getLookupTableTileLayout(lutSize, out) {
35
- const n = Math.max(1, lutSize);
36
- out[0] = n * n; // width: n tiles × n pixels each.
37
- out[1] = n; // height: one row per G step.
38
- }
39
- //# sourceMappingURL=lutMath.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lutMath.js","sourceRoot":"","sources":["../src/lutMath.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,4FAA4F;AAE5F,mGAAmG;AACnG,oFAAoF;AACpF,0DAA0D;AAC1D,yEAAyE;AACzE,+DAA+D;AAC/D,cAAc;AACd,MAAM,UAAU,uBAAuB,CACrC,CAAS,EAAE,+BAA+B;AAC1C,CAAS,EAAE,+BAA+B;AAC1C,CAAS,EAAE,+BAA+B;AAC1C,OAAe,EAAE,0CAA0C;AAC3D,GAAqB;IAErB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC,CAAC;IAC1B,sDAAsD;IACtD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,+CAA+C;IAC/C,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClC,sCAAsC;IACtC,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IACtD,+FAA+F;IAC/F,gEAAgE;IAChE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;IACvC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACX,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACb,CAAC;AAED,8FAA8F;AAC9F,0EAA0E;AAC1E,qCAAqC;AACrC,MAAM,UAAU,wBAAwB,CAAC,OAAe,EAAE,GAAqB;IAC7E,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/B,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,kCAAkC;IAClD,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,8BAA8B;AAC5C,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { SepiaEffect } from '@flighthq/types';
2
- export declare function createSepiaEffect(options?: Readonly<Omit<SepiaEffect, 'kind'>>): SepiaEffect;
3
- //# sourceMappingURL=sepiaEffect.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sepiaEffect.d.ts","sourceRoot":"","sources":["../src/sepiaEffect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAM,GAAG,WAAW,CAEhG"}
@@ -1,4 +0,0 @@
1
- export function createSepiaEffect(options = {}) {
2
- return { kind: 'SepiaEffect', ...options };
3
- }
4
- //# sourceMappingURL=sepiaEffect.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sepiaEffect.js","sourceRoot":"","sources":["../src/sepiaEffect.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,iBAAiB,CAAC,UAA+C,EAAE;IACjF,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;AAC7C,CAAC"}
@@ -1,14 +0,0 @@
1
- import { createBrightnessContrastEffect } from './brightnessContrastEffect';
2
-
3
- describe('createBrightnessContrastEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createBrightnessContrastEffect().kind).toBe('BrightnessContrastEffect');
6
- });
7
-
8
- it('carries options', () => {
9
- expect(createBrightnessContrastEffect({ brightness: 0.2, contrast: 1.5 })).toMatchObject({
10
- brightness: 0.2,
11
- contrast: 1.5,
12
- });
13
- });
14
- });
@@ -1,12 +0,0 @@
1
- import { createChannelMixerEffect } from './channelMixerEffect';
2
-
3
- describe('createChannelMixerEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createChannelMixerEffect({ matrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0] }).kind).toBe('ChannelMixerEffect');
6
- });
7
-
8
- it('carries the matrix', () => {
9
- const matrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0];
10
- expect(createChannelMixerEffect({ matrix }).matrix).toBe(matrix);
11
- });
12
- });
@@ -1,13 +0,0 @@
1
- import { createColorBlindSimulationEffect } from './colorBlindSimulationEffect';
2
-
3
- describe('createColorBlindSimulationEffect', () => {
4
- it('carries options', () => {
5
- expect(createColorBlindSimulationEffect({ type: 'protanopia' })).toMatchObject({
6
- type: 'protanopia',
7
- });
8
- });
9
-
10
- it('tags the intent type', () => {
11
- expect(createColorBlindSimulationEffect().kind).toBe('ColorBlindSimulationEffect');
12
- });
13
- });
@@ -1,11 +0,0 @@
1
- import { createColorGradeEffect } from './colorGradeEffect';
2
-
3
- describe('createColorGradeEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createColorGradeEffect().kind).toBe('ColorGradeEffect');
6
- });
7
-
8
- it('carries options', () => {
9
- expect(createColorGradeEffect({ exposure: 1, saturation: 1.2 })).toMatchObject({ exposure: 1, saturation: 1.2 });
10
- });
11
- });
@@ -1,160 +0,0 @@
1
- import {
2
- computeHslToRgb,
3
- computeLinearToSrgb,
4
- computeOklabToRgb,
5
- computeRgbToHsl,
6
- computeRgbToOklab,
7
- computeSrgbToLinear,
8
- getRec709LuminanceWeights,
9
- getRec2020LuminanceWeights,
10
- } from './colorScienceMath';
11
-
12
- describe('computeHslToRgb', () => {
13
- it('hue=0, full saturation, mid lightness → red', () => {
14
- const out: [number, number, number] = [0, 0, 0];
15
- computeHslToRgb(0, 1, 0.5, out);
16
- expect(out[0]).toBeCloseTo(1, 4);
17
- expect(out[1]).toBeCloseTo(0, 4);
18
- expect(out[2]).toBeCloseTo(0, 4);
19
- });
20
- it('round-trips with computeRgbToHsl', () => {
21
- const r = 0.3;
22
- const g = 0.7;
23
- const b = 0.1;
24
- const hsl: [number, number, number] = [0, 0, 0];
25
- computeRgbToHsl(r, g, b, hsl);
26
- const rgb: [number, number, number] = [0, 0, 0];
27
- computeHslToRgb(hsl[0], hsl[1], hsl[2], rgb);
28
- expect(rgb[0]).toBeCloseTo(r, 4);
29
- expect(rgb[1]).toBeCloseTo(g, 4);
30
- expect(rgb[2]).toBeCloseTo(b, 4);
31
- });
32
- });
33
-
34
- describe('computeLinearToSrgb', () => {
35
- it('0 maps to 0', () => {
36
- expect(computeLinearToSrgb(0)).toBeCloseTo(0, 5);
37
- });
38
- it('1 maps to 1', () => {
39
- expect(computeLinearToSrgb(1)).toBeCloseTo(1, 5);
40
- });
41
- it('round-trips with computeSrgbToLinear', () => {
42
- const linear = 0.5;
43
- expect(computeSrgbToLinear(computeLinearToSrgb(linear))).toBeCloseTo(linear, 4);
44
- });
45
- it('clamps negative values to 0', () => {
46
- expect(computeLinearToSrgb(-1)).toBeCloseTo(0, 5);
47
- });
48
- });
49
-
50
- describe('computeOklabToRgb', () => {
51
- it('round-trips with computeRgbToOklab for a mid-gray', () => {
52
- const r = 0.5;
53
- const g = 0.5;
54
- const b = 0.5;
55
- const lab: [number, number, number] = [0, 0, 0];
56
- computeRgbToOklab(r, g, b, lab);
57
- const rgb: [number, number, number] = [0, 0, 0];
58
- computeOklabToRgb(lab[0], lab[1], lab[2], rgb);
59
- expect(rgb[0]).toBeCloseTo(r, 3);
60
- expect(rgb[1]).toBeCloseTo(g, 3);
61
- expect(rgb[2]).toBeCloseTo(b, 3);
62
- });
63
- it('round-trips with computeRgbToOklab for a saturated color', () => {
64
- const r = 0.8;
65
- const g = 0.2;
66
- const b = 0.1;
67
- const lab: [number, number, number] = [0, 0, 0];
68
- computeRgbToOklab(r, g, b, lab);
69
- const rgb: [number, number, number] = [0, 0, 0];
70
- computeOklabToRgb(lab[0], lab[1], lab[2], rgb);
71
- expect(rgb[0]).toBeCloseTo(r, 3);
72
- expect(rgb[1]).toBeCloseTo(g, 3);
73
- expect(rgb[2]).toBeCloseTo(b, 3);
74
- });
75
- });
76
-
77
- describe('computeRgbToHsl', () => {
78
- it('red (1,0,0) has hue 0°', () => {
79
- const out: [number, number, number] = [0, 0, 0];
80
- computeRgbToHsl(1, 0, 0, out);
81
- expect(out[0]).toBeCloseTo(0, 2);
82
- expect(out[1]).toBeCloseTo(1, 2);
83
- expect(out[2]).toBeCloseTo(0.5, 2);
84
- });
85
- it('green (0,1,0) has hue 120°', () => {
86
- const out: [number, number, number] = [0, 0, 0];
87
- computeRgbToHsl(0, 1, 0, out);
88
- expect(out[0]).toBeCloseTo(120, 2);
89
- });
90
- it('white (1,1,1) has lightness 1 and saturation 0', () => {
91
- const out: [number, number, number] = [0, 0, 0];
92
- computeRgbToHsl(1, 1, 1, out);
93
- expect(out[1]).toBeCloseTo(0, 4);
94
- expect(out[2]).toBeCloseTo(1, 5);
95
- });
96
- it('black (0,0,0) has lightness 0 and saturation 0', () => {
97
- const out: [number, number, number] = [0, 0, 0];
98
- computeRgbToHsl(0, 0, 0, out);
99
- expect(out[1]).toBeCloseTo(0, 4);
100
- expect(out[2]).toBeCloseTo(0, 5);
101
- });
102
- });
103
-
104
- describe('computeRgbToOklab', () => {
105
- it('black (0,0,0) maps to L=0', () => {
106
- const out: [number, number, number] = [0, 0, 0];
107
- computeRgbToOklab(0, 0, 0, out);
108
- expect(out[0]).toBeCloseTo(0, 4);
109
- });
110
- it('white (1,1,1) maps to L~1, a~0, b~0', () => {
111
- const out: [number, number, number] = [0, 0, 0];
112
- computeRgbToOklab(1, 1, 1, out);
113
- expect(out[0]).toBeCloseTo(1, 2);
114
- expect(out[1]).toBeCloseTo(0, 3);
115
- expect(out[2]).toBeCloseTo(0, 3);
116
- });
117
- });
118
-
119
- describe('computeSrgbToLinear', () => {
120
- it('0 maps to 0', () => {
121
- expect(computeSrgbToLinear(0)).toBeCloseTo(0, 5);
122
- });
123
- it('1 maps to 1', () => {
124
- expect(computeSrgbToLinear(1)).toBeCloseTo(1, 5);
125
- });
126
- it('round-trips with computeLinearToSrgb', () => {
127
- const srgb = 0.5;
128
- expect(computeLinearToSrgb(computeSrgbToLinear(srgb))).toBeCloseTo(srgb, 4);
129
- });
130
- });
131
-
132
- describe('getRec2020LuminanceWeights', () => {
133
- it('weights sum to 1', () => {
134
- const out: [number, number, number] = [0, 0, 0];
135
- getRec2020LuminanceWeights(out);
136
- expect(out[0] + out[1] + out[2]).toBeCloseTo(1, 5);
137
- });
138
- it('returns canonical Rec.2020 values', () => {
139
- const out: [number, number, number] = [0, 0, 0];
140
- getRec2020LuminanceWeights(out);
141
- expect(out[0]).toBeCloseTo(0.2627, 4);
142
- expect(out[1]).toBeCloseTo(0.678, 4);
143
- expect(out[2]).toBeCloseTo(0.0593, 4);
144
- });
145
- });
146
-
147
- describe('getRec709LuminanceWeights', () => {
148
- it('weights sum to 1', () => {
149
- const out: [number, number, number] = [0, 0, 0];
150
- getRec709LuminanceWeights(out);
151
- expect(out[0] + out[1] + out[2]).toBeCloseTo(1, 5);
152
- });
153
- it('returns canonical Rec.709 values', () => {
154
- const out: [number, number, number] = [0, 0, 0];
155
- getRec709LuminanceWeights(out);
156
- expect(out[0]).toBeCloseTo(0.2126, 4);
157
- expect(out[1]).toBeCloseTo(0.7152, 4);
158
- expect(out[2]).toBeCloseTo(0.0722, 4);
159
- });
160
- });
@@ -1,7 +0,0 @@
1
- import { createExposureEffect } from './exposureEffect';
2
-
3
- describe('createExposureEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createExposureEffect({ exposure: 1 }).kind).toBe('ExposureEffect');
6
- });
7
- });
@@ -1,11 +0,0 @@
1
- import { createGrayscaleEffect } from './grayscaleEffect';
2
-
3
- describe('createGrayscaleEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createGrayscaleEffect().kind).toBe('GrayscaleEffect');
6
- });
7
-
8
- it('carries options', () => {
9
- expect(createGrayscaleEffect({ intensity: 0.5 })).toMatchObject({ intensity: 0.5 });
10
- });
11
- });
@@ -1,15 +0,0 @@
1
- import { createHueSaturationEffect } from './hueSaturationEffect';
2
-
3
- describe('createHueSaturationEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createHueSaturationEffect().kind).toBe('HueSaturationEffect');
6
- });
7
-
8
- it('carries options', () => {
9
- expect(createHueSaturationEffect({ hue: 90, saturation: 1.4, lightness: 0.1 })).toMatchObject({
10
- hue: 90,
11
- saturation: 1.4,
12
- lightness: 0.1,
13
- });
14
- });
15
- });
@@ -1,11 +0,0 @@
1
- import { createInvertEffect } from './invertEffect';
2
-
3
- describe('createInvertEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createInvertEffect().kind).toBe('InvertEffect');
6
- });
7
-
8
- it('carries options', () => {
9
- expect(createInvertEffect({ intensity: 0.75 })).toMatchObject({ intensity: 0.75 });
10
- });
11
- });
@@ -1,15 +0,0 @@
1
- import { createLiftGammaGainEffect } from './liftGammaGainEffect';
2
-
3
- describe('createLiftGammaGainEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createLiftGammaGainEffect().kind).toBe('LiftGammaGainEffect');
6
- });
7
-
8
- it('carries options', () => {
9
- expect(createLiftGammaGainEffect({ lift: 0x808080ff, gamma: 0x808080ff, gain: 0x808080ff })).toMatchObject({
10
- lift: 0x808080ff,
11
- gamma: 0x808080ff,
12
- gain: 0x808080ff,
13
- });
14
- });
15
- });
@@ -1,11 +0,0 @@
1
- import { createLookupTableGradeEffect } from './lookupTableGradeEffect';
2
-
3
- describe('createLookupTableGradeEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createLookupTableGradeEffect().kind).toBe('LookupTableGradeEffect');
6
- });
7
-
8
- it('carries options', () => {
9
- expect(createLookupTableGradeEffect({ size: 32, strength: 0.8 })).toMatchObject({ size: 32, strength: 0.8 });
10
- });
11
- });
@@ -1,67 +0,0 @@
1
- import { computeLookupTableCoord, getLookupTableTileLayout } from './lutMath';
2
-
3
- describe('computeLookupTableCoord', () => {
4
- it('writes two values into out', () => {
5
- const out: [number, number] = [0, 0];
6
- computeLookupTableCoord(0.5, 0.5, 0.5, 16, out);
7
- expect(typeof out[0]).toBe('number');
8
- expect(typeof out[1]).toBe('number');
9
- });
10
- it('black (0,0,0) maps to near (0, 0)', () => {
11
- const out: [number, number] = [0, 0];
12
- computeLookupTableCoord(0, 0, 0, 16, out);
13
- expect(out[0]).toBeGreaterThanOrEqual(0);
14
- expect(out[1]).toBeGreaterThanOrEqual(0);
15
- });
16
- it('U and V are in [0, 1] range for valid input', () => {
17
- const out: [number, number] = [0, 0];
18
- computeLookupTableCoord(0.5, 0.5, 0.5, 16, out);
19
- expect(out[0]).toBeGreaterThanOrEqual(0);
20
- expect(out[0]).toBeLessThanOrEqual(1);
21
- expect(out[1]).toBeGreaterThanOrEqual(0);
22
- expect(out[1]).toBeLessThanOrEqual(1);
23
- });
24
- it('high G shifts V up', () => {
25
- const outLow: [number, number] = [0, 0];
26
- const outHigh: [number, number] = [0, 0];
27
- computeLookupTableCoord(0.5, 0.1, 0.5, 16, outLow);
28
- computeLookupTableCoord(0.5, 0.9, 0.5, 16, outHigh);
29
- expect(outHigh[1]).toBeGreaterThan(outLow[1]);
30
- });
31
- it('high B shifts U right', () => {
32
- const outLow: [number, number] = [0, 0];
33
- const outHigh: [number, number] = [0, 0];
34
- computeLookupTableCoord(0.5, 0.5, 0.1, 16, outLow);
35
- computeLookupTableCoord(0.5, 0.5, 0.9, 16, outHigh);
36
- expect(outHigh[0]).toBeGreaterThan(outLow[0]);
37
- });
38
- it('clamps out-of-range input', () => {
39
- const out1: [number, number] = [0, 0];
40
- const out2: [number, number] = [0, 0];
41
- computeLookupTableCoord(0, 0, 0, 16, out1);
42
- computeLookupTableCoord(-0.5, -0.5, -0.5, 16, out2);
43
- expect(out1[0]).toBeCloseTo(out2[0], 5);
44
- expect(out1[1]).toBeCloseTo(out2[1], 5);
45
- });
46
- });
47
-
48
- describe('getLookupTableTileLayout', () => {
49
- it('returns [size², size] for a given LUT size', () => {
50
- const out: [number, number] = [0, 0];
51
- getLookupTableTileLayout(16, out);
52
- expect(out[0]).toBe(256); // 16 * 16
53
- expect(out[1]).toBe(16);
54
- });
55
- it('works for size 32', () => {
56
- const out: [number, number] = [0, 0];
57
- getLookupTableTileLayout(32, out);
58
- expect(out[0]).toBe(1024);
59
- expect(out[1]).toBe(32);
60
- });
61
- it('handles size 1 without dividing by zero', () => {
62
- const out: [number, number] = [0, 0];
63
- getLookupTableTileLayout(1, out);
64
- expect(out[0]).toBe(1);
65
- expect(out[1]).toBe(1);
66
- });
67
- });
@@ -1,11 +0,0 @@
1
- import { createSepiaEffect } from './sepiaEffect';
2
-
3
- describe('createSepiaEffect', () => {
4
- it('tags the intent type', () => {
5
- expect(createSepiaEffect().kind).toBe('SepiaEffect');
6
- });
7
-
8
- it('carries options', () => {
9
- expect(createSepiaEffect({ intensity: 0.6 })).toMatchObject({ intensity: 0.6 });
10
- });
11
- });