react-native-parity-blur 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.
- package/LICENSE +20 -0
- package/ParityBlur.podspec +20 -0
- package/README.md +198 -0
- package/android/build.gradle +57 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/parityblur/AndroidBlurCalibration.kt +82 -0
- package/android/src/main/java/com/parityblur/BlurEngine.kt +132 -0
- package/android/src/main/java/com/parityblur/ParityBlurDebug.kt +24 -0
- package/android/src/main/java/com/parityblur/ParityBlurPackage.kt +17 -0
- package/android/src/main/java/com/parityblur/ParityBlurView.kt +542 -0
- package/android/src/main/java/com/parityblur/ParityBlurViewManager.kt +161 -0
- package/android/src/main/java/com/parityblur/PipelineMath.kt +202 -0
- package/android/src/main/java/com/parityblur/PixelCopySnapshotProvider.kt +108 -0
- package/android/src/main/java/com/parityblur/SoftwareSnapshotProvider.kt +173 -0
- package/android/src/main/java/com/parityblur/WindowBlurContext.kt +116 -0
- package/android/src/test/java/com/parityblur/MiniJson.kt +179 -0
- package/android/src/test/java/com/parityblur/PipelineFixturesTest.kt +222 -0
- package/ios/BlurEngine.swift +106 -0
- package/ios/ColorPipeline.swift +72 -0
- package/ios/MetalPresentationSurface.swift +51 -0
- package/ios/ParityBlurCoreView.swift +382 -0
- package/ios/ParityBlurDebug.swift +18 -0
- package/ios/ParityBlurView.h +14 -0
- package/ios/ParityBlurView.mm +135 -0
- package/ios/PipelineMath.swift +177 -0
- package/ios/SnapshotProvider.swift +128 -0
- package/ios/WindowBlurContext.swift +111 -0
- package/lib/module/BlurView.js +124 -0
- package/lib/module/BlurView.js.map +1 -0
- package/lib/module/ParityBlurViewNativeComponent.ts +82 -0
- package/lib/module/defaults.js +13 -0
- package/lib/module/defaults.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/pipeline/androidCalibration.js +55 -0
- package/lib/module/pipeline/androidCalibration.js.map +1 -0
- package/lib/module/pipeline/captureRect.js +151 -0
- package/lib/module/pipeline/captureRect.js.map +1 -0
- package/lib/module/pipeline/color.js +82 -0
- package/lib/module/pipeline/color.js.map +1 -0
- package/lib/module/pipeline/constants.js +65 -0
- package/lib/module/pipeline/constants.js.map +1 -0
- package/lib/module/pipeline/downsample.js +61 -0
- package/lib/module/pipeline/downsample.js.map +1 -0
- package/lib/module/pipeline/index.js +23 -0
- package/lib/module/pipeline/index.js.map +1 -0
- package/lib/module/pipeline/overlay.js +56 -0
- package/lib/module/pipeline/overlay.js.map +1 -0
- package/lib/module/pipeline/saturation.js +52 -0
- package/lib/module/pipeline/saturation.js.map +1 -0
- package/lib/module/pipeline/types.js +23 -0
- package/lib/module/pipeline/types.js.map +1 -0
- package/lib/module/pipeline/units.js +33 -0
- package/lib/module/pipeline/units.js.map +1 -0
- package/lib/module/presets.js +96 -0
- package/lib/module/presets.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/BlurView.d.ts +16 -0
- package/lib/typescript/src/BlurView.d.ts.map +1 -0
- package/lib/typescript/src/ParityBlurViewNativeComponent.d.ts +63 -0
- package/lib/typescript/src/ParityBlurViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/defaults.d.ts +12 -0
- package/lib/typescript/src/defaults.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/androidCalibration.d.ts +42 -0
- package/lib/typescript/src/pipeline/androidCalibration.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/captureRect.d.ts +84 -0
- package/lib/typescript/src/pipeline/captureRect.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/color.d.ts +19 -0
- package/lib/typescript/src/pipeline/color.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/constants.d.ts +52 -0
- package/lib/typescript/src/pipeline/constants.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/downsample.d.ts +31 -0
- package/lib/typescript/src/pipeline/downsample.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/index.d.ts +20 -0
- package/lib/typescript/src/pipeline/index.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/overlay.d.ts +31 -0
- package/lib/typescript/src/pipeline/overlay.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/saturation.d.ts +38 -0
- package/lib/typescript/src/pipeline/saturation.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/types.d.ts +32 -0
- package/lib/typescript/src/pipeline/types.d.ts.map +1 -0
- package/lib/typescript/src/pipeline/units.d.ts +23 -0
- package/lib/typescript/src/pipeline/units.d.ts.map +1 -0
- package/lib/typescript/src/presets.d.ts +57 -0
- package/lib/typescript/src/presets.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +116 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +167 -0
- package/src/BlurView.tsx +195 -0
- package/src/ParityBlurViewNativeComponent.ts +82 -0
- package/src/defaults.ts +20 -0
- package/src/index.ts +10 -0
- package/src/pipeline/androidCalibration.ts +64 -0
- package/src/pipeline/captureRect.ts +172 -0
- package/src/pipeline/color.ts +66 -0
- package/src/pipeline/constants.ts +65 -0
- package/src/pipeline/downsample.ts +74 -0
- package/src/pipeline/index.ts +20 -0
- package/src/pipeline/overlay.ts +46 -0
- package/src/pipeline/saturation.ts +65 -0
- package/src/pipeline/types.ts +37 -0
- package/src/pipeline/units.ts +32 -0
- package/src/presets.ts +103 -0
- package/src/types.ts +132 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Android RenderEffect calibration (plan §5.2).
|
|
5
|
+
*
|
|
6
|
+
* INTERNAL MODULE. The single place the HWUI sigma<->radius relation lives on
|
|
7
|
+
* the TypeScript side; the Kotlin `AndroidBlurCalibration` must mirror it
|
|
8
|
+
* exactly. Verified on a Pixel 6a (API 36) in M0: radiusForSigma(10) exactly
|
|
9
|
+
* equals 16.454486... (matching the on-device measurement 16.45449).
|
|
10
|
+
*
|
|
11
|
+
* Relation (HWUI): sigma = SLOPE * radiusPlatform + INTERCEPT
|
|
12
|
+
* Inverse: radiusPlatform = (sigma - INTERCEPT) / SLOPE
|
|
13
|
+
*
|
|
14
|
+
* When sigmaSnapshot <= INTERCEPT (0.5) the inverse is non-positive, so we
|
|
15
|
+
* clamp to a no-blur passthrough rather than feeding a bogus radius to
|
|
16
|
+
* RenderEffect.createBlurEffect (plan §5.2 "no-op blur" for very small sigma).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { ANDROID_MIN_BLUR_SIGMA, HWUI_SIGMA_INTERCEPT, HWUI_SIGMA_SLOPE } from "./constants.js";
|
|
20
|
+
/**
|
|
21
|
+
* Forward relation, exposed for tests/verification: the sigma that HWUI
|
|
22
|
+
* produces for a given platform radius.
|
|
23
|
+
*/
|
|
24
|
+
export function sigmaForRadius(radiusPlatform) {
|
|
25
|
+
return HWUI_SIGMA_SLOPE * radiusPlatform + HWUI_SIGMA_INTERCEPT;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Inverse relation: the platform radius required to achieve a target
|
|
30
|
+
* snapshot-domain sigma. Below the intercept this returns a no-blur result.
|
|
31
|
+
* Monotonically non-decreasing in sigmaSnapshot.
|
|
32
|
+
*/
|
|
33
|
+
export function radiusForSigma(sigmaSnapshot) {
|
|
34
|
+
if (!Number.isFinite(sigmaSnapshot) || sigmaSnapshot <= ANDROID_MIN_BLUR_SIGMA) {
|
|
35
|
+
return {
|
|
36
|
+
noBlur: true,
|
|
37
|
+
radiusPlatform: 0
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
noBlur: false,
|
|
42
|
+
radiusPlatform: (sigmaSnapshot - HWUI_SIGMA_INTERCEPT) / HWUI_SIGMA_SLOPE
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* iOS MPSImageGaussianBlur takes the snapshot-domain sigma directly (plan §5.3).
|
|
48
|
+
* Provided here for symmetry so both platform mappings live in the reference.
|
|
49
|
+
* Sigma at or below 0 means no blur.
|
|
50
|
+
*/
|
|
51
|
+
export function iosSigmaForSigma(sigmaSnapshot) {
|
|
52
|
+
if (!Number.isFinite(sigmaSnapshot) || sigmaSnapshot <= 0) return 0;
|
|
53
|
+
return sigmaSnapshot;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=androidCalibration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ANDROID_MIN_BLUR_SIGMA","HWUI_SIGMA_INTERCEPT","HWUI_SIGMA_SLOPE","sigmaForRadius","radiusPlatform","radiusForSigma","sigmaSnapshot","Number","isFinite","noBlur","iosSigmaForSigma"],"sourceRoot":"../../../src","sources":["pipeline/androidCalibration.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SACEA,sBAAsB,EACtBC,oBAAoB,EACpBC,gBAAgB,QACX,gBAAa;AAYpB;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAACC,cAAsB,EAAU;EAC7D,OAAOF,gBAAgB,GAAGE,cAAc,GAAGH,oBAAoB;AACjE;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,cAAcA,CAACC,aAAqB,EAAoB;EACtE,IAAI,CAACC,MAAM,CAACC,QAAQ,CAACF,aAAa,CAAC,IAAIA,aAAa,IAAIN,sBAAsB,EAAE;IAC9E,OAAO;MAAES,MAAM,EAAE,IAAI;MAAEL,cAAc,EAAE;IAAE,CAAC;EAC5C;EACA,OAAO;IACLK,MAAM,EAAE,KAAK;IACbL,cAAc,EAAE,CAACE,aAAa,GAAGL,oBAAoB,IAAIC;EAC3D,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASQ,gBAAgBA,CAACJ,aAAqB,EAAU;EAC9D,IAAI,CAACC,MAAM,CAACC,QAAQ,CAACF,aAAa,CAAC,IAAIA,aAAa,IAAI,CAAC,EAAE,OAAO,CAAC;EACnE,OAAOA,aAAa;AACtB","ignoreList":[]}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Capture-rect math (plan §7, §12).
|
|
5
|
+
*
|
|
6
|
+
* INTERNAL MODULE. All rectangles here are in TARGET-LOCAL DEVICE PIXELS unless
|
|
7
|
+
* a field/return is explicitly documented as snapshot pixels.
|
|
8
|
+
*
|
|
9
|
+
* Pipeline of this module:
|
|
10
|
+
* 1. supportMarginPx — Gaussian support margin = ceil(K * sigmaPx)
|
|
11
|
+
* 2. expandCaptureRect — expand visible rect by margin, clamp to target bounds
|
|
12
|
+
* 3. snapshotRectFor — map the clamped device-px rect into integer snapshot
|
|
13
|
+
* pixels (floor origin, ceil far edge = conservative
|
|
14
|
+
* cover)
|
|
15
|
+
* 4. cropRectFor — the sub-region of the snapshot that maps back to the
|
|
16
|
+
* visible rect (fractional, snapshot px)
|
|
17
|
+
* 5. cropRectToViewPx — inverse mapping used to prove round-tripping
|
|
18
|
+
*
|
|
19
|
+
* Rounding rule (LOCKED): in the snapshot domain the origin FLOORS and the far
|
|
20
|
+
* edge CEILS, so `size = ceil(farEdge/D) - floor(origin/D)`. This is the
|
|
21
|
+
* conservative reading of "floor for origin, ceil for size": it guarantees
|
|
22
|
+
* every device pixel of the clamped capture rect is covered by the snapshot
|
|
23
|
+
* rect, at the cost of at most one extra snapshot pixel per side. A naive
|
|
24
|
+
* `floor(origin), ceil(width)` would fail to cover the far edge and is NOT used.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { CAPTURE_SUPPORT_K } from "./constants.js";
|
|
28
|
+
/** Gaussian support margin in device px (plan §7): ceil(K * sigmaPx). */
|
|
29
|
+
export function supportMarginPx(sigmaPx, k = CAPTURE_SUPPORT_K) {
|
|
30
|
+
if (!Number.isFinite(sigmaPx) || sigmaPx <= 0) return 0;
|
|
31
|
+
return Math.ceil(k * sigmaPx);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Intersection of two rects; empty (zero-size) rect if they do not overlap. */
|
|
35
|
+
export function intersectRect(a, b) {
|
|
36
|
+
const x0 = Math.max(a.x, b.x);
|
|
37
|
+
const y0 = Math.max(a.y, b.y);
|
|
38
|
+
const x1 = Math.min(a.x + a.width, b.x + b.width);
|
|
39
|
+
const y1 = Math.min(a.y + a.height, b.y + b.height);
|
|
40
|
+
const width = Math.max(0, x1 - x0);
|
|
41
|
+
const height = Math.max(0, y1 - y0);
|
|
42
|
+
if (width === 0 || height === 0) {
|
|
43
|
+
return {
|
|
44
|
+
x: x0,
|
|
45
|
+
y: y0,
|
|
46
|
+
width: 0,
|
|
47
|
+
height: 0
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
x: x0,
|
|
52
|
+
y: y0,
|
|
53
|
+
width,
|
|
54
|
+
height
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Expand the visible blur rect by the Gaussian support margin and clamp to the
|
|
60
|
+
* target bounds. Returns a float device-px rect (plan §7). The margin only
|
|
61
|
+
* covers content that exists inside the target; CLAMP handles the outer edge
|
|
62
|
+
* where the margin was cut off (plan §8).
|
|
63
|
+
*/
|
|
64
|
+
export function expandCaptureRect(visibleRect, targetBounds, sigmaPx, k = CAPTURE_SUPPORT_K) {
|
|
65
|
+
const margin = supportMarginPx(sigmaPx, k);
|
|
66
|
+
const expanded = {
|
|
67
|
+
x: visibleRect.x - margin,
|
|
68
|
+
y: visibleRect.y - margin,
|
|
69
|
+
width: visibleRect.width + 2 * margin,
|
|
70
|
+
height: visibleRect.height + 2 * margin
|
|
71
|
+
};
|
|
72
|
+
return intersectRect(expanded, targetBounds);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Area of a rect in device px^2 (helper for downsample selection). */
|
|
76
|
+
export function rectArea(r) {
|
|
77
|
+
return r.width * r.height;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Map a clamped device-px capture rect into integer snapshot pixels for
|
|
82
|
+
* downsample factor D. Floor the origin, ceil the far edge (conservative
|
|
83
|
+
* cover). The returned rect is in SNAPSHOT PIXELS (indices), so its device-px
|
|
84
|
+
* footprint is `snapshotRect * D`.
|
|
85
|
+
*/
|
|
86
|
+
export function snapshotRectFor(captureRectPx, downsample) {
|
|
87
|
+
const x = Math.floor(captureRectPx.x / downsample);
|
|
88
|
+
const y = Math.floor(captureRectPx.y / downsample);
|
|
89
|
+
const farX = Math.ceil((captureRectPx.x + captureRectPx.width) / downsample);
|
|
90
|
+
const farY = Math.ceil((captureRectPx.y + captureRectPx.height) / downsample);
|
|
91
|
+
return {
|
|
92
|
+
x,
|
|
93
|
+
y,
|
|
94
|
+
width: Math.max(0, farX - x),
|
|
95
|
+
height: Math.max(0, farY - y)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The fractional crop rect, in SNAPSHOT PIXELS, that selects the visible region
|
|
101
|
+
* out of the (larger) snapshot rect after blur. Because the snapshot origin was
|
|
102
|
+
* floored, the crop origin carries a fractional remainder in [0, 1) snapshot px
|
|
103
|
+
* which the upsample step resolves with bilinear sampling (plan §12).
|
|
104
|
+
*
|
|
105
|
+
* cropX = visibleRect.x / D - snapshotRect.x
|
|
106
|
+
* cropW = visibleRect.width / D
|
|
107
|
+
*/
|
|
108
|
+
export function cropRectFor(visibleRect, snapshotRect, downsample) {
|
|
109
|
+
return {
|
|
110
|
+
x: visibleRect.x / downsample - snapshotRect.x,
|
|
111
|
+
y: visibleRect.y / downsample - snapshotRect.y,
|
|
112
|
+
width: visibleRect.width / downsample,
|
|
113
|
+
height: visibleRect.height / downsample
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Inverse of {@link cropRectFor}: map a snapshot-px crop rect back to
|
|
119
|
+
* target-local device px. Used to verify round-tripping (should recover the
|
|
120
|
+
* original visible rect within half a snapshot pixel = D/2 device px).
|
|
121
|
+
*/
|
|
122
|
+
export function cropRectToViewPx(cropRect, snapshotRect, downsample) {
|
|
123
|
+
return {
|
|
124
|
+
x: (snapshotRect.x + cropRect.x) * downsample,
|
|
125
|
+
y: (snapshotRect.y + cropRect.y) * downsample,
|
|
126
|
+
width: cropRect.width * downsample,
|
|
127
|
+
height: cropRect.height * downsample
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Assemble the full capture plan for a given visible rect, target bounds,
|
|
132
|
+
* sigmaPx and pre-resolved downsample factor. Downsample resolution lives in
|
|
133
|
+
* downsample.ts and takes `captureAreaPx` from this same computation, so the
|
|
134
|
+
* caller sequences: expand -> area -> resolveDownsample -> buildCapturePlan.
|
|
135
|
+
*/
|
|
136
|
+
export function buildCapturePlan(visibleRect, targetBounds, sigmaPx, downsample, k = CAPTURE_SUPPORT_K) {
|
|
137
|
+
const marginPx = supportMarginPx(sigmaPx, k);
|
|
138
|
+
const captureRectPx = expandCaptureRect(visibleRect, targetBounds, sigmaPx, k);
|
|
139
|
+
const snapshotRect = snapshotRectFor(captureRectPx, downsample);
|
|
140
|
+
const cropRect = cropRectFor(visibleRect, snapshotRect, downsample);
|
|
141
|
+
return {
|
|
142
|
+
visibleRect,
|
|
143
|
+
marginPx,
|
|
144
|
+
captureRectPx,
|
|
145
|
+
captureAreaPx: rectArea(captureRectPx),
|
|
146
|
+
downsample,
|
|
147
|
+
snapshotRect,
|
|
148
|
+
cropRect
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=captureRect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["CAPTURE_SUPPORT_K","supportMarginPx","sigmaPx","k","Number","isFinite","Math","ceil","intersectRect","a","b","x0","max","x","y0","y","x1","min","width","y1","height","expandCaptureRect","visibleRect","targetBounds","margin","expanded","rectArea","r","snapshotRectFor","captureRectPx","downsample","floor","farX","farY","cropRectFor","snapshotRect","cropRectToViewPx","cropRect","buildCapturePlan","marginPx","captureAreaPx"],"sourceRoot":"../../../src","sources":["pipeline/captureRect.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Color parsing for the overlay prop.
|
|
5
|
+
*
|
|
6
|
+
* INTERNAL MODULE. Parses the subset of CSS color syntaxes React Native
|
|
7
|
+
* accepts for a string color prop into straight-alpha RGBA in [0,1]:
|
|
8
|
+
* - 'transparent'
|
|
9
|
+
* - #rgb / #rgba / #rrggbb / #rrggbbaa
|
|
10
|
+
* - rgb(r,g,b) / rgba(r,g,b,a) (r,g,b integer 0-255, a float 0-1)
|
|
11
|
+
*
|
|
12
|
+
* Any unrecognised value returns a fully-transparent color (no overlay), which
|
|
13
|
+
* is the documented default (plan §11). The native backends parse the same
|
|
14
|
+
* prop with their platform color parsers; this reference fixes the expected
|
|
15
|
+
* numeric result for parity fixtures.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export const TRANSPARENT = {
|
|
19
|
+
r: 0,
|
|
20
|
+
g: 0,
|
|
21
|
+
b: 0,
|
|
22
|
+
a: 0
|
|
23
|
+
};
|
|
24
|
+
function clamp01(v) {
|
|
25
|
+
return v < 0 ? 0 : v > 1 ? 1 : v;
|
|
26
|
+
}
|
|
27
|
+
function hexPair(s) {
|
|
28
|
+
return parseInt(s, 16) / 255;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Parse a color string into straight-alpha RGBA. Unrecognised -> transparent. */
|
|
32
|
+
export function parseColor(input) {
|
|
33
|
+
if (input == null) return TRANSPARENT;
|
|
34
|
+
const s = input.trim().toLowerCase();
|
|
35
|
+
if (s === 'transparent') return TRANSPARENT;
|
|
36
|
+
if (s.startsWith('#')) {
|
|
37
|
+
const hex = s.slice(1);
|
|
38
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
39
|
+
const r = hexPair(hex[0] + hex[0]);
|
|
40
|
+
const g = hexPair(hex[1] + hex[1]);
|
|
41
|
+
const b = hexPair(hex[2] + hex[2]);
|
|
42
|
+
const a = hex.length === 4 ? hexPair(hex[3] + hex[3]) : 1;
|
|
43
|
+
return {
|
|
44
|
+
r,
|
|
45
|
+
g,
|
|
46
|
+
b,
|
|
47
|
+
a
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (hex.length === 6 || hex.length === 8) {
|
|
51
|
+
const r = hexPair(hex.slice(0, 2));
|
|
52
|
+
const g = hexPair(hex.slice(2, 4));
|
|
53
|
+
const b = hexPair(hex.slice(4, 6));
|
|
54
|
+
const a = hex.length === 8 ? hexPair(hex.slice(6, 8)) : 1;
|
|
55
|
+
return {
|
|
56
|
+
r,
|
|
57
|
+
g,
|
|
58
|
+
b,
|
|
59
|
+
a
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return TRANSPARENT;
|
|
63
|
+
}
|
|
64
|
+
const m = s.match(/^rgba?\(([^)]+)\)$/);
|
|
65
|
+
if (m) {
|
|
66
|
+
const parts = m[1].split(',').map(p => p.trim());
|
|
67
|
+
if (parts.length === 3 || parts.length === 4) {
|
|
68
|
+
const r = clamp01(parseFloat(parts[0]) / 255);
|
|
69
|
+
const g = clamp01(parseFloat(parts[1]) / 255);
|
|
70
|
+
const b = clamp01(parseFloat(parts[2]) / 255);
|
|
71
|
+
const a = parts.length === 4 ? clamp01(parseFloat(parts[3])) : 1;
|
|
72
|
+
if ([r, g, b, a].every(v => Number.isFinite(v))) return {
|
|
73
|
+
r,
|
|
74
|
+
g,
|
|
75
|
+
b,
|
|
76
|
+
a
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return TRANSPARENT;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TRANSPARENT","r","g","b","a","clamp01","v","hexPair","s","parseInt","parseColor","input","trim","toLowerCase","startsWith","hex","slice","length","m","match","parts","split","map","p","parseFloat","every","Number","isFinite"],"sourceRoot":"../../../src","sources":["pipeline/color.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Locked calibration constants for the canonical pipeline.
|
|
5
|
+
*
|
|
6
|
+
* INTERNAL MODULE. These are the single source of truth for the reference
|
|
7
|
+
* implementation. Native backends must mirror these exact values. Per the
|
|
8
|
+
* plan (§5.2, §38) constants remain provisional until the parity milestone,
|
|
9
|
+
* but M0 device verification already confirmed the HWUI relation on API 36.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* HWUI RenderEffect Gaussian relation, verified exact on a Pixel 6a (API 36)
|
|
14
|
+
* in M0: `sigma = HWUI_SIGMA_SLOPE * radiusPlatform + HWUI_SIGMA_INTERCEPT`.
|
|
15
|
+
* Isolated here so a future version-aware calibration can override it in one
|
|
16
|
+
* place (plan §5.2). Do NOT inline these anywhere else.
|
|
17
|
+
*/
|
|
18
|
+
export const HWUI_SIGMA_SLOPE = 0.57735;
|
|
19
|
+
export const HWUI_SIGMA_INTERCEPT = 0.5;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Below this snapshot-domain sigma the Android RenderEffect relation inverts
|
|
23
|
+
* to a non-positive radius, so we emit a no-blur passthrough instead. Equal to
|
|
24
|
+
* HWUI_SIGMA_INTERCEPT by construction (radius 0 <=> sigma 0.5).
|
|
25
|
+
*/
|
|
26
|
+
export const ANDROID_MIN_BLUR_SIGMA = HWUI_SIGMA_INTERCEPT;
|
|
27
|
+
|
|
28
|
+
/** Gaussian support multiplier for capture expansion (plan §7). */
|
|
29
|
+
export const CAPTURE_SUPPORT_K = 3;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Auto-downsample: target lower bound on snapshot-domain sigma. Keeping
|
|
33
|
+
* sigmaSnapshot at or above this prevents over-downsampling that would make
|
|
34
|
+
* the kernel degenerate (plan §12). 1 snapshot px.
|
|
35
|
+
*/
|
|
36
|
+
export const MIN_SIGMA_SNAPSHOT = 1.0;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Auto-downsample: captures with area (device px^2) below this are considered
|
|
40
|
+
* "small" and are never downsampled beyond 2x — aggressive reduction of a tiny
|
|
41
|
+
* region buys no meaningful performance while degrading quality.
|
|
42
|
+
* 256 * 256 device px.
|
|
43
|
+
*/
|
|
44
|
+
export const SMALL_CAPTURE_AREA_PX = 256 * 256;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Auto-downsample: per-quality ceiling on the downsample factor (plan §13).
|
|
48
|
+
* high -> prefer 1x or 2x
|
|
49
|
+
* balanced -> prefer 2x or 4x
|
|
50
|
+
* performance -> prefer 4x or 8x
|
|
51
|
+
*/
|
|
52
|
+
export const QUALITY_MAX_DOWNSAMPLE = {
|
|
53
|
+
high: 2,
|
|
54
|
+
balanced: 4,
|
|
55
|
+
performance: 8
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Rec. 709 luminance coefficients (plan §10). Sum to 1.0. Used for the
|
|
60
|
+
* saturation matrix on both platforms.
|
|
61
|
+
*/
|
|
62
|
+
export const LUMA_R = 0.2126;
|
|
63
|
+
export const LUMA_G = 0.7152;
|
|
64
|
+
export const LUMA_B = 0.0722;
|
|
65
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["HWUI_SIGMA_SLOPE","HWUI_SIGMA_INTERCEPT","ANDROID_MIN_BLUR_SIGMA","CAPTURE_SUPPORT_K","MIN_SIGMA_SNAPSHOT","SMALL_CAPTURE_AREA_PX","QUALITY_MAX_DOWNSAMPLE","high","balanced","performance","LUMA_R","LUMA_G","LUMA_B"],"sourceRoot":"../../../src","sources":["pipeline/constants.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,gBAAgB,GAAG,OAAO;AACvC,OAAO,MAAMC,oBAAoB,GAAG,GAAG;;AAEvC;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,sBAAsB,GAAGD,oBAAoB;;AAE1D;AACA,OAAO,MAAME,iBAAiB,GAAG,CAAC;;AAElC;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,kBAAkB,GAAG,GAAG;;AAErC;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,qBAAqB,GAAG,GAAG,GAAG,GAAG;;AAE9C;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,sBAGZ,GAAG;EACFC,IAAI,EAAE,CAAC;EACPC,QAAQ,EAAE,CAAC;EACXC,WAAW,EAAE;AACf,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAMC,MAAM,GAAG,MAAM;AAC5B,OAAO,MAAMC,MAAM,GAAG,MAAM;AAC5B,OAAO,MAAMC,MAAM,GAAG,MAAM","ignoreList":[]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Auto downsample selection (plan §12, §13).
|
|
5
|
+
*
|
|
6
|
+
* INTERNAL MODULE. Deterministic function of (sigmaPx, captureAreaPx, quality)
|
|
7
|
+
* -> D in {1,2,4,8}. Both backends must select identically for identical input.
|
|
8
|
+
*
|
|
9
|
+
* The chosen factor is the largest allowed value that satisfies ALL of three
|
|
10
|
+
* independent ceilings, then snapped down to a real factor in {1,2,4,8}:
|
|
11
|
+
*
|
|
12
|
+
* 1. quality ceiling — QUALITY_MAX_DOWNSAMPLE[quality]
|
|
13
|
+
* 2. sigma floor — keep sigmaSnapshot = sigmaPx / D >= MIN_SIGMA_SNAPSHOT,
|
|
14
|
+
* i.e. D <= floor(sigmaPx / MIN_SIGMA_SNAPSHOT)
|
|
15
|
+
* 3. area ceiling — tiny captures (< SMALL_CAPTURE_AREA_PX) never exceed 2x
|
|
16
|
+
*
|
|
17
|
+
* See docs/PIPELINE_SPEC.md for the locked decision table.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { MIN_SIGMA_SNAPSHOT, QUALITY_MAX_DOWNSAMPLE, SMALL_CAPTURE_AREA_PX } from "./constants.js";
|
|
21
|
+
import { DOWNSAMPLE_FACTORS } from "./types.js";
|
|
22
|
+
|
|
23
|
+
/** Largest allowed factor in {8,4,2,1} that is <= cap (never below 1). */
|
|
24
|
+
function largestFactorAtMost(cap) {
|
|
25
|
+
for (const factor of DOWNSAMPLE_FACTORS) {
|
|
26
|
+
if (factor <= cap) return factor;
|
|
27
|
+
}
|
|
28
|
+
return 1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the auto-selected downsample factor.
|
|
33
|
+
*
|
|
34
|
+
* @param sigmaPx device-pixel sigma (blurRadius * displayScale)
|
|
35
|
+
* @param captureAreaPx expanded capture area in device px^2
|
|
36
|
+
* @param quality quality tier
|
|
37
|
+
*/
|
|
38
|
+
export function autoDownsample(sigmaPx, captureAreaPx, quality) {
|
|
39
|
+
// No blur requested -> never downsample.
|
|
40
|
+
if (!Number.isFinite(sigmaPx) || sigmaPx <= 0) return 1;
|
|
41
|
+
const maxByQuality = QUALITY_MAX_DOWNSAMPLE[quality];
|
|
42
|
+
|
|
43
|
+
// Sigma floor: keep snapshot sigma at/above the minimum useful value.
|
|
44
|
+
const maxBySigma = Math.floor(sigmaPx / MIN_SIGMA_SNAPSHOT);
|
|
45
|
+
|
|
46
|
+
// Area ceiling: small captures are capped at 2x.
|
|
47
|
+
const area = Number.isFinite(captureAreaPx) ? captureAreaPx : 0;
|
|
48
|
+
const maxByArea = area < SMALL_CAPTURE_AREA_PX ? 2 : 8;
|
|
49
|
+
const cap = Math.min(maxByQuality, maxBySigma, maxByArea);
|
|
50
|
+
return largestFactorAtMost(cap);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Resolve a public `downsample` prop to a concrete factor. An explicit numeric
|
|
55
|
+
* value is honoured verbatim; 'auto' delegates to {@link autoDownsample}.
|
|
56
|
+
*/
|
|
57
|
+
export function resolveDownsample(prop, sigmaPx, captureAreaPx, quality) {
|
|
58
|
+
if (prop === 'auto') return autoDownsample(sigmaPx, captureAreaPx, quality);
|
|
59
|
+
return prop;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=downsample.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["MIN_SIGMA_SNAPSHOT","QUALITY_MAX_DOWNSAMPLE","SMALL_CAPTURE_AREA_PX","DOWNSAMPLE_FACTORS","largestFactorAtMost","cap","factor","autoDownsample","sigmaPx","captureAreaPx","quality","Number","isFinite","maxByQuality","maxBySigma","Math","floor","area","maxByArea","min","resolveDownsample","prop"],"sourceRoot":"../../../src","sources":["pipeline/downsample.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SACEA,kBAAkB,EAClBC,sBAAsB,EACtBC,qBAAqB,QAChB,gBAAa;AAEpB,SAASC,kBAAkB,QAAQ,YAAS;;AAE5C;AACA,SAASC,mBAAmBA,CAACC,GAAW,EAAc;EACpD,KAAK,MAAMC,MAAM,IAAIH,kBAAkB,EAAE;IACvC,IAAIG,MAAM,IAAID,GAAG,EAAE,OAAOC,MAAM;EAClC;EACA,OAAO,CAAC;AACV;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAC5BC,OAAe,EACfC,aAAqB,EACrBC,OAAoB,EACR;EACZ;EACA,IAAI,CAACC,MAAM,CAACC,QAAQ,CAACJ,OAAO,CAAC,IAAIA,OAAO,IAAI,CAAC,EAAE,OAAO,CAAC;EAEvD,MAAMK,YAAY,GAAGZ,sBAAsB,CAACS,OAAO,CAAC;;EAEpD;EACA,MAAMI,UAAU,GAAGC,IAAI,CAACC,KAAK,CAACR,OAAO,GAAGR,kBAAkB,CAAC;;EAE3D;EACA,MAAMiB,IAAI,GAAGN,MAAM,CAACC,QAAQ,CAACH,aAAa,CAAC,GAAGA,aAAa,GAAG,CAAC;EAC/D,MAAMS,SAAS,GAAGD,IAAI,GAAGf,qBAAqB,GAAG,CAAC,GAAG,CAAC;EAEtD,MAAMG,GAAG,GAAGU,IAAI,CAACI,GAAG,CAACN,YAAY,EAAEC,UAAU,EAAEI,SAAS,CAAC;EACzD,OAAOd,mBAAmB,CAACC,GAAG,CAAC;AACjC;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASe,iBAAiBA,CAC/BC,IAAoB,EACpBb,OAAe,EACfC,aAAqB,EACrBC,OAAoB,EACR;EACZ,IAAIW,IAAI,KAAK,MAAM,EAAE,OAAOd,cAAc,CAACC,OAAO,EAAEC,aAAa,EAAEC,OAAO,CAAC;EAC3E,OAAOW,IAAI;AACb","ignoreList":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Canonical pipeline reference implementation — INTERNAL barrel.
|
|
5
|
+
*
|
|
6
|
+
* This module is the executable form of docs/PIPELINE_SPEC.md: pure TypeScript,
|
|
7
|
+
* no react-native imports, no side effects. Native backends (Kotlin / Swift)
|
|
8
|
+
* must reproduce these exact rules.
|
|
9
|
+
*
|
|
10
|
+
* IMPORTANT: this barrel is intentionally NOT re-exported from src/index.ts.
|
|
11
|
+
* It is a spec/testing artifact, not part of the package's public API.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export * from "./types.js";
|
|
15
|
+
export * from "./constants.js";
|
|
16
|
+
export * from "./units.js";
|
|
17
|
+
export * from "./androidCalibration.js";
|
|
18
|
+
export * from "./downsample.js";
|
|
19
|
+
export * from "./captureRect.js";
|
|
20
|
+
export * from "./saturation.js";
|
|
21
|
+
export * from "./color.js";
|
|
22
|
+
export * from "./overlay.js";
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["pipeline/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,cAAc,YAAS;AACvB,cAAc,gBAAa;AAC3B,cAAc,YAAS;AACvB,cAAc,yBAAsB;AACpC,cAAc,iBAAc;AAC5B,cAAc,kBAAe;AAC7B,cAAc,iBAAc;AAC5B,cAAc,YAAS;AACvB,cAAc,cAAW","ignoreList":[]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Overlay source-over compositing (plan §11).
|
|
5
|
+
*
|
|
6
|
+
* INTERNAL MODULE. The overlay color (straight alpha, parsed from the prop) is
|
|
7
|
+
* the SOURCE; the saturated blur result is the DESTINATION. Applied AFTER
|
|
8
|
+
* saturation, BEFORE final clipping (plan §6 step 10). This is the only tint in
|
|
9
|
+
* the pipeline — no hidden platform tint is permitted.
|
|
10
|
+
*
|
|
11
|
+
* Straight-alpha (non-premultiplied) source-over, per channel:
|
|
12
|
+
*
|
|
13
|
+
* outA = srcA + dstA * (1 - srcA)
|
|
14
|
+
* outC = (srcC*srcA + dstC*dstA*(1 - srcA)) / outA (outA > 0)
|
|
15
|
+
* 0 (outA = 0)
|
|
16
|
+
*
|
|
17
|
+
* In v1 the capture surface is an opaque backdrop, so dstA = 1 and this reduces
|
|
18
|
+
* to the familiar linear blend outC = srcC*srcA + dstC*(1 - srcA), outA = 1.
|
|
19
|
+
* The general form is implemented so the reference stays correct if a future
|
|
20
|
+
* version captures translucent backdrops.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Source-over composite of a straight-alpha source over a straight-alpha
|
|
25
|
+
* destination. Returns straight-alpha RGBA.
|
|
26
|
+
*/
|
|
27
|
+
export function sourceOver(src, dst) {
|
|
28
|
+
const outA = src.a + dst.a * (1 - src.a);
|
|
29
|
+
if (outA <= 0) return {
|
|
30
|
+
r: 0,
|
|
31
|
+
g: 0,
|
|
32
|
+
b: 0,
|
|
33
|
+
a: 0
|
|
34
|
+
};
|
|
35
|
+
const blend = (sc, dc) => (sc * src.a + dc * dst.a * (1 - src.a)) / outA;
|
|
36
|
+
return {
|
|
37
|
+
r: blend(src.r, dst.r),
|
|
38
|
+
g: blend(src.g, dst.g),
|
|
39
|
+
b: blend(src.b, dst.b),
|
|
40
|
+
a: outA
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Convenience: composite an overlay color over an opaque (alpha=1) blurred
|
|
46
|
+
* pixel — the v1 case. Equivalent to sourceOver(overlay, {..dst, a:1}).
|
|
47
|
+
*/
|
|
48
|
+
export function overlayOnOpaque(overlay, dst) {
|
|
49
|
+
return sourceOver(overlay, {
|
|
50
|
+
r: dst.r,
|
|
51
|
+
g: dst.g,
|
|
52
|
+
b: dst.b,
|
|
53
|
+
a: 1
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["sourceOver","src","dst","outA","a","r","g","b","blend","sc","dc","overlayOnOpaque","overlay"],"sourceRoot":"../../../src","sources":["pipeline/overlay.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA,OAAO,SAASA,UAAUA,CAACC,GAAS,EAAEC,GAAS,EAAQ;EACrD,MAAMC,IAAI,GAAGF,GAAG,CAACG,CAAC,GAAGF,GAAG,CAACE,CAAC,IAAI,CAAC,GAAGH,GAAG,CAACG,CAAC,CAAC;EACxC,IAAID,IAAI,IAAI,CAAC,EAAE,OAAO;IAAEE,CAAC,EAAE,CAAC;IAAEC,CAAC,EAAE,CAAC;IAAEC,CAAC,EAAE,CAAC;IAAEH,CAAC,EAAE;EAAE,CAAC;EAChD,MAAMI,KAAK,GAAGA,CAACC,EAAU,EAAEC,EAAU,KACnC,CAACD,EAAE,GAAGR,GAAG,CAACG,CAAC,GAAGM,EAAE,GAAGR,GAAG,CAACE,CAAC,IAAI,CAAC,GAAGH,GAAG,CAACG,CAAC,CAAC,IAAID,IAAI;EAChD,OAAO;IACLE,CAAC,EAAEG,KAAK,CAACP,GAAG,CAACI,CAAC,EAAEH,GAAG,CAACG,CAAC,CAAC;IACtBC,CAAC,EAAEE,KAAK,CAACP,GAAG,CAACK,CAAC,EAAEJ,GAAG,CAACI,CAAC,CAAC;IACtBC,CAAC,EAAEC,KAAK,CAACP,GAAG,CAACM,CAAC,EAAEL,GAAG,CAACK,CAAC,CAAC;IACtBH,CAAC,EAAED;EACL,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASQ,eAAeA,CAACC,OAAa,EAAEV,GAAS,EAAQ;EAC9D,OAAOF,UAAU,CAACY,OAAO,EAAE;IAAEP,CAAC,EAAEH,GAAG,CAACG,CAAC;IAAEC,CAAC,EAAEJ,GAAG,CAACI,CAAC;IAAEC,CAAC,EAAEL,GAAG,CAACK,CAAC;IAAEH,CAAC,EAAE;EAAE,CAAC,CAAC;AACpE","ignoreList":[]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Saturation color matrix (plan §10).
|
|
5
|
+
*
|
|
6
|
+
* INTERNAL MODULE. One canonical 4x5 color matrix (Android ColorMatrix layout:
|
|
7
|
+
* 4 output rows R,G,B,A; 5 columns R,G,B,A,offset) using Rec.709 luminance
|
|
8
|
+
* coefficients. Applied AFTER blur, BEFORE overlay (plan §6 step 9).
|
|
9
|
+
*
|
|
10
|
+
* For saturation s and luma coefficients (lr,lg,lb) with t = 1 - s:
|
|
11
|
+
*
|
|
12
|
+
* R' = (t*lr + s)*R + t*lg*G + t*lb*B
|
|
13
|
+
* G' = t*lr*R + (t*lg + s)*G + t*lb*B
|
|
14
|
+
* B' = t*lr*R + t*lg*G + (t*lb + s)*B
|
|
15
|
+
* A' = A
|
|
16
|
+
*
|
|
17
|
+
* s = 1 -> identity; s = 0 -> luminance grayscale; s > 1 -> more saturated.
|
|
18
|
+
*
|
|
19
|
+
* The alpha row is untouched and there is no offset column (all offsets 0).
|
|
20
|
+
* The matrix operates on the same channel representation the backend blurs in
|
|
21
|
+
* (gamma-space, straight color for the opaque v1 backdrop). It does NOT itself
|
|
22
|
+
* premultiply — see docs/PIPELINE_SPEC.md §Color.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { LUMA_B, LUMA_G, LUMA_R } from "./constants.js";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Row-major 4x5 saturation matrix (20 numbers), matching Android's
|
|
29
|
+
* ColorMatrix and directly transcribable to a Metal 4x4 + bias.
|
|
30
|
+
*/
|
|
31
|
+
export function saturationMatrix(s, lr = LUMA_R, lg = LUMA_G, lb = LUMA_B) {
|
|
32
|
+
const t = 1 - s;
|
|
33
|
+
return [t * lr + s, t * lg, t * lb, 0, 0, t * lr, t * lg + s, t * lb, 0, 0, t * lr, t * lg, t * lb + s, 0, 0, 0, 0, 0, 1, 0];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Apply a 4x5 saturation matrix to a straight-alpha RGBA tuple (channels in
|
|
38
|
+
* [0,1]). Returned RGB is clamped to [0,1]; alpha is passed through untouched.
|
|
39
|
+
* Reference for backend parity tests.
|
|
40
|
+
*/
|
|
41
|
+
export function applySaturation(matrix, r, g, b, a) {
|
|
42
|
+
const clamp01 = v => v < 0 ? 0 : v > 1 ? 1 : v;
|
|
43
|
+
const m = matrix;
|
|
44
|
+
return {
|
|
45
|
+
// Indices per row-major 4x5 layout.
|
|
46
|
+
r: clamp01(m[0] * r + m[1] * g + m[2] * b + m[3] * a + m[4]),
|
|
47
|
+
g: clamp01(m[5] * r + m[6] * g + m[7] * b + m[8] * a + m[9]),
|
|
48
|
+
b: clamp01(m[10] * r + m[11] * g + m[12] * b + m[13] * a + m[14]),
|
|
49
|
+
a: m[15] * r + m[16] * g + m[17] * b + m[18] * a + m[19]
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=saturation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["LUMA_B","LUMA_G","LUMA_R","saturationMatrix","s","lr","lg","lb","t","applySaturation","matrix","r","g","b","a","clamp01","v","m"],"sourceRoot":"../../../src","sources":["pipeline/saturation.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,MAAM,EAAEC,MAAM,EAAEC,MAAM,QAAQ,gBAAa;;AAEpD;AACA;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAC9BC,CAAS,EACTC,EAAU,GAAGH,MAAM,EACnBI,EAAU,GAAGL,MAAM,EACnBM,EAAU,GAAGP,MAAM,EACT;EACV,MAAMQ,CAAC,GAAG,CAAC,GAAGJ,CAAC;EACf,OAAO,CACLI,CAAC,GAAGH,EAAE,GAAGD,CAAC,EAAEI,CAAC,GAAGF,EAAE,EAAEE,CAAC,GAAGD,EAAE,EAAE,CAAC,EAAE,CAAC,EAChCC,CAAC,GAAGH,EAAE,EAAEG,CAAC,GAAGF,EAAE,GAAGF,CAAC,EAAEI,CAAC,GAAGD,EAAE,EAAE,CAAC,EAAE,CAAC,EAChCC,CAAC,GAAGH,EAAE,EAAEG,CAAC,GAAGF,EAAE,EAAEE,CAAC,GAAGD,EAAE,GAAGH,CAAC,EAAE,CAAC,EAAE,CAAC,EAChC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CACd;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,eAAeA,CAC7BC,MAAgB,EAChBC,CAAS,EACTC,CAAS,EACTC,CAAS,EACTC,CAAS,EACuC;EAChD,MAAMC,OAAO,GAAIC,CAAS,IAAMA,CAAC,GAAG,CAAC,GAAG,CAAC,GAAGA,CAAC,GAAG,CAAC,GAAG,CAAC,GAAGA,CAAE;EAC1D,MAAMC,CAAC,GAAGP,MAAM;EAChB,OAAO;IACL;IACAC,CAAC,EAAEI,OAAO,CAACE,CAAC,CAAC,CAAC,CAAC,GAAIN,CAAC,GAAGM,CAAC,CAAC,CAAC,CAAC,GAAIL,CAAC,GAAGK,CAAC,CAAC,CAAC,CAAC,GAAIJ,CAAC,GAAGI,CAAC,CAAC,CAAC,CAAC,GAAIH,CAAC,GAAGG,CAAC,CAAC,CAAC,CAAE,CAAC;IACjEL,CAAC,EAAEG,OAAO,CAACE,CAAC,CAAC,CAAC,CAAC,GAAIN,CAAC,GAAGM,CAAC,CAAC,CAAC,CAAC,GAAIL,CAAC,GAAGK,CAAC,CAAC,CAAC,CAAC,GAAIJ,CAAC,GAAGI,CAAC,CAAC,CAAC,CAAC,GAAIH,CAAC,GAAGG,CAAC,CAAC,CAAC,CAAE,CAAC;IACjEJ,CAAC,EAAEE,OAAO,CAACE,CAAC,CAAC,EAAE,CAAC,GAAIN,CAAC,GAAGM,CAAC,CAAC,EAAE,CAAC,GAAIL,CAAC,GAAGK,CAAC,CAAC,EAAE,CAAC,GAAIJ,CAAC,GAAGI,CAAC,CAAC,EAAE,CAAC,GAAIH,CAAC,GAAGG,CAAC,CAAC,EAAE,CAAE,CAAC;IACtEH,CAAC,EAAEG,CAAC,CAAC,EAAE,CAAC,GAAIN,CAAC,GAAGM,CAAC,CAAC,EAAE,CAAC,GAAIL,CAAC,GAAGK,CAAC,CAAC,EAAE,CAAC,GAAIJ,CAAC,GAAGI,CAAC,CAAC,EAAE,CAAC,GAAIH,CAAC,GAAGG,CAAC,CAAC,EAAE;EAC7D,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared value types for the canonical pipeline reference implementation.
|
|
5
|
+
*
|
|
6
|
+
* INTERNAL MODULE. Nothing here is re-exported from src/index.ts. These types
|
|
7
|
+
* describe the language-neutral contract that both native backends implement;
|
|
8
|
+
* they are the executable form of docs/PIPELINE_SPEC.md.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Integer downsample factor actually used by the pipeline (never 'auto'). */
|
|
12
|
+
|
|
13
|
+
/** The four concrete downsample factors, largest first (selection order). */
|
|
14
|
+
export const DOWNSAMPLE_FACTORS = [8, 4, 2, 1];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Axis-aligned rectangle. Units are documented per-field by the producing
|
|
18
|
+
* function (device px in target-local space, or snapshot px). Origin is the
|
|
19
|
+
* top-left corner; width/height grow right/down.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** Straight-alpha RGBA colour, all channels normalised to [0, 1]. */
|
|
23
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DOWNSAMPLE_FACTORS"],"sourceRoot":"../../../src","sources":["pipeline/types.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;;AAGA;AACA,OAAO,MAAMA,kBAAyC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;;AAErE;AACA;AACA;AACA;AACA;;AAQA","ignoreList":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Canonical unit conversions (plan §5.1).
|
|
5
|
+
*
|
|
6
|
+
* INTERNAL MODULE. Pure functions, no side effects, no react-native imports.
|
|
7
|
+
*
|
|
8
|
+
* blurRadius = Gaussian sigma in dp (public unit)
|
|
9
|
+
* sigmaPx = blurRadius * displayScale (device pixels)
|
|
10
|
+
* sigmaSnapshot= sigmaPx / D (downsampled snapshot px)
|
|
11
|
+
*
|
|
12
|
+
* The blur backend always receives a parameter derived from sigmaSnapshot.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Convert the public blurRadius (sigma in dp) to sigma in device pixels.
|
|
17
|
+
* Non-finite or negative inputs clamp to 0 (plan §28 safe clamping).
|
|
18
|
+
*/
|
|
19
|
+
export function sigmaPxFromDp(blurRadiusDp, displayScale) {
|
|
20
|
+
if (!Number.isFinite(blurRadiusDp) || blurRadiusDp <= 0) return 0;
|
|
21
|
+
if (!Number.isFinite(displayScale) || displayScale <= 0) return 0;
|
|
22
|
+
return blurRadiusDp * displayScale;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Convert device-pixel sigma to snapshot-domain sigma given a downsample
|
|
27
|
+
* factor D. D is a positive integer in {1,2,4,8}.
|
|
28
|
+
*/
|
|
29
|
+
export function sigmaSnapshotFromPx(sigmaPx, downsample) {
|
|
30
|
+
if (!Number.isFinite(sigmaPx) || sigmaPx <= 0) return 0;
|
|
31
|
+
return sigmaPx / downsample;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=units.js.map
|