tempest-react-sdk 0.38.1 → 0.38.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- var e=256;function t(e){return e instanceof HTMLVideoElement?{width:e.videoWidth,height:e.videoHeight}:e instanceof HTMLCanvasElement?{width:e.width,height:e.height}:{width:e.naturalWidth||e.width,height:e.naturalHeight||e.height}}function n(e,n){let{width:r,height:i}=t(e);if(r===0||i===0)return 0;let a=Math.min(1,256/Math.max(r,i)),o=Math.max(1,Math.round(r*a)),s=Math.max(1,Math.round(i*a)),c=n??document.createElement(`canvas`);c.width=o,c.height=s;let l=c.getContext(`2d`,{willReadFrequently:!0});if(!l)return 0;l.drawImage(e,0,0,o,s);let u=l.getImageData(0,0,o,s).data,d=0,f=o*s;for(let e=0;e<u.length;e+=4)d+=.2126*u[e]+.7152*u[e+1]+.0722*u[e+2];return d/f}function r(e,t){return e>=t}var i=class extends Error{luminance;threshold;constructor(e,t){super(`Image is too dark to analyse. Capture again in a brighter environment.`),this.name=`LowLuminanceError`,this.luminance=e,this.threshold=t}};exports.LUMINANCE_SAMPLE_MAX_EDGE=e,exports.LowLuminanceError=i,exports.computeImageLuminance=n,exports.isLuminanceAcceptable=r;
1
+ var e=256;function t(e){return e instanceof HTMLVideoElement?{width:e.videoWidth,height:e.videoHeight}:e instanceof HTMLImageElement?{width:e.naturalWidth||e.width,height:e.naturalHeight||e.height}:{width:e.width,height:e.height}}function n(e,n){let{width:r,height:i}=t(e);if(r===0||i===0)return 0;let a=Math.min(1,256/Math.max(r,i)),o=Math.max(1,Math.round(r*a)),s=Math.max(1,Math.round(i*a)),c=n??document.createElement(`canvas`);c.width=o,c.height=s;let l=c.getContext(`2d`,{willReadFrequently:!0});if(!l)return 0;l.drawImage(e,0,0,o,s);let u=l.getImageData(0,0,o,s).data,d=0,f=o*s;for(let e=0;e<u.length;e+=4)d+=.2126*u[e]+.7152*u[e+1]+.0722*u[e+2];return d/f}function r(e,t){return e>=t}var i=class extends Error{luminance;threshold;constructor(e,t){super(`Image is too dark to analyse. Capture again in a brighter environment.`),this.name=`LowLuminanceError`,this.luminance=e,this.threshold=t}};exports.LUMINANCE_SAMPLE_MAX_EDGE=e,exports.LowLuminanceError=i,exports.computeImageLuminance=n,exports.isLuminanceAcceptable=r;
2
2
  //# sourceMappingURL=luminance.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"luminance.cjs","names":[],"sources":["../../src/vision/luminance.ts"],"sourcesContent":["/**\n * Frame-brightness helpers — measure the mean luminance of an already-decoded\n * `<img>`, `<video>` or `<canvas>` so a UI can reject underexposed captures\n * before paying the cost of downstream inference.\n *\n * These are framework-agnostic pure functions; {@link useLiveLuminance} wires\n * {@link computeImageLuminance} into a React `requestAnimationFrame` loop for\n * live camera feedback.\n */\n\n/**\n * Longest edge (in pixels) the source is downsampled to before sampling.\n * Averaging over a small downsample is statistically equivalent for a\n * brightness threshold and orders of magnitude faster than reading every pixel\n * of a full-resolution camera frame.\n */\nexport const LUMINANCE_SAMPLE_MAX_EDGE = 256;\n\n/** Drawable source we can sample luminance from image, video, or canvas. */\nexport type LuminanceSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;\n\n/** Natural pixel size of the source (`0`/`0` while it is still unloaded). */\nfunction sourceSize(source: LuminanceSource): { width: number; height: number } {\n if (source instanceof HTMLVideoElement) {\n return { width: source.videoWidth, height: source.videoHeight };\n }\n if (source instanceof HTMLCanvasElement) {\n return { width: source.width, height: source.height };\n }\n return {\n width: source.naturalWidth || source.width,\n height: source.naturalHeight || source.height,\n };\n}\n\n/**\n * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded\n * `<img>`, `<video>` or `<canvas>`, scaled to `0..255`.\n *\n * The source is downsampled so its longest edge is at most\n * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is\n * created with `willReadFrequently` so repeated sampling (live feedback) stays\n * on the fast path.\n *\n * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot\n * loop; when omitted a one-shot detached canvas is created.\n *\n * @param source - the image/video/canvas to sample.\n * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.\n * @returns The mean luminance in `0..255`, or `0` when the source is unloaded\n * (zero-sized) or a 2D context is unavailable.\n */\nexport function computeImageLuminance(\n source: LuminanceSource,\n reusableCanvas?: HTMLCanvasElement,\n): number {\n const { width: srcW, height: srcH } = sourceSize(source);\n if (srcW === 0 || srcH === 0) return 0;\n\n const scale = Math.min(1, LUMINANCE_SAMPLE_MAX_EDGE / Math.max(srcW, srcH));\n const w = Math.max(1, Math.round(srcW * scale));\n const h = Math.max(1, Math.round(srcH * scale));\n\n const canvas = reusableCanvas ?? document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return 0;\n ctx.drawImage(source, 0, 0, w, h);\n\n const data = ctx.getImageData(0, 0, w, h).data;\n let sum = 0;\n const pixelCount = w * h;\n for (let i = 0; i < data.length; i += 4) {\n sum += 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];\n }\n return sum / pixelCount;\n}\n\n/**\n * Whether a measured luminance clears a brightness threshold.\n *\n * `threshold` is intentionally required — a sensible value is\n * application-specific (it depends on the model, the lighting the model was\n * trained on, and the acceptable false-reject rate), so the SDK does not bake\n * in a default.\n *\n * @param luminance - measured mean luminance in `0..255`.\n * @param threshold - minimum acceptable luminance in `0..255`.\n * @returns `true` when `luminance >= threshold`.\n */\nexport function isLuminanceAcceptable(luminance: number, threshold: number): boolean {\n return luminance >= threshold;\n}\n\n/**\n * Error raised when a captured frame is too dark to be analysed reliably.\n * Carries the measured luminance and the threshold it failed so callers can\n * surface actionable feedback.\n */\nexport class LowLuminanceError extends Error {\n /** Measured mean luminance, `0..255`. */\n readonly luminance: number;\n /** Threshold that was checked against, `0..255`. */\n readonly threshold: number;\n\n /**\n * @param luminance - the measured mean luminance in `0..255`.\n * @param threshold - the threshold the measurement failed to reach.\n */\n constructor(luminance: number, threshold: number) {\n super(\"Image is too dark to analyse. Capture again in a brighter environment.\");\n this.name = \"LowLuminanceError\";\n this.luminance = luminance;\n this.threshold = threshold;\n }\n}\n"],"mappings":"AAgBA,IAAa,EAA4B,IAMzC,SAAS,EAAW,EAA4D,CAO5E,OANI,aAAkB,iBACX,CAAE,MAAO,EAAO,WAAY,OAAQ,EAAO,WAAY,EAE9D,aAAkB,kBACX,CAAE,MAAO,EAAO,MAAO,OAAQ,EAAO,MAAO,EAEjD,CACH,MAAO,EAAO,cAAgB,EAAO,MACrC,OAAQ,EAAO,eAAiB,EAAO,MAC3C,CACJ,CAmBA,SAAgB,EACZ,EACA,EACM,CACN,GAAM,CAAE,MAAO,EAAM,OAAQ,GAAS,EAAW,CAAM,EACvD,GAAI,IAAS,GAAK,IAAS,EAAG,MAAO,GAErC,IAAM,EAAQ,KAAK,IAAI,EAAA,IAA+B,KAAK,IAAI,EAAM,CAAI,CAAC,EACpE,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,CAAK,CAAC,EACxC,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,CAAK,CAAC,EAExC,EAAS,GAAkB,SAAS,cAAc,QAAQ,EAChE,EAAO,MAAQ,EACf,EAAO,OAAS,EAChB,IAAM,EAAM,EAAO,WAAW,KAAM,CAAE,mBAAoB,EAAK,CAAC,EAChE,GAAI,CAAC,EAAK,MAAO,GACjB,EAAI,UAAU,EAAQ,EAAG,EAAG,EAAG,CAAC,EAEhC,IAAM,EAAO,EAAI,aAAa,EAAG,EAAG,EAAG,CAAC,CAAC,CAAC,KACtC,EAAM,EACJ,EAAa,EAAI,EACvB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,GAAK,EAClC,GAAO,MAAS,EAAK,GAAK,MAAS,EAAK,EAAI,GAAK,MAAS,EAAK,EAAI,GAEvE,OAAO,EAAM,CACjB,CAcA,SAAgB,EAAsB,EAAmB,EAA4B,CACjF,OAAO,GAAa,CACxB,CAOA,IAAa,EAAb,cAAuC,KAAM,CAEzC,UAEA,UAMA,YAAY,EAAmB,EAAmB,CAC9C,MAAM,wEAAwE,EAC9E,KAAK,KAAO,oBACZ,KAAK,UAAY,EACjB,KAAK,UAAY,CACrB,CACJ"}
1
+ {"version":3,"file":"luminance.cjs","names":[],"sources":["../../src/vision/luminance.ts"],"sourcesContent":["/**\n * Frame-brightness helpers — measure the mean luminance of an already-decoded\n * frame (`<img>`, `<video>`, `<canvas>`, `ImageBitmap` or `OffscreenCanvas`) so\n * a UI can reject underexposed captures before paying the cost of downstream\n * inference.\n *\n * These are framework-agnostic pure functions; {@link useLiveLuminance} wires\n * {@link computeImageLuminance} into a React `requestAnimationFrame` loop for\n * live camera feedback.\n */\n\n/**\n * Longest edge (in pixels) the source is downsampled to before sampling.\n * Averaging over a small downsample is statistically equivalent for a\n * brightness threshold and orders of magnitude faster than reading every pixel\n * of a full-resolution camera frame.\n */\nexport const LUMINANCE_SAMPLE_MAX_EDGE = 256;\n\n/**\n * Drawable source we can sample luminance from.\n *\n * The list tracks what `CanvasRenderingContext2D.drawImage` accepts and we can\n * read a pixel size off, which is what the implementation actually needs.\n * `ImageBitmap` matters for the decode-downscaled path: `createImageBitmap(blob,\n * { resizeWidth })` is how a caller avoids materialising a full-resolution\n * phone photo, and the frame it hands back is the frame whose brightness has to\n * be checked.\n */\nexport type LuminanceSource =\n HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | OffscreenCanvas;\n\n/**\n * Natural pixel size of the source (`0`/`0` while it is still unloaded).\n *\n * `ImageBitmap` and `OffscreenCanvas` both expose plain `width`/`height`, so\n * they fall through to the same branch as a canvas — but they are named\n * explicitly rather than left to the `naturalWidth || width` fallback, which\n * only reads as intentional for an `<img>`.\n */\nfunction sourceSize(source: LuminanceSource): { width: number; height: number } {\n if (source instanceof HTMLVideoElement) {\n return { width: source.videoWidth, height: source.videoHeight };\n }\n if (source instanceof HTMLImageElement) {\n return {\n width: source.naturalWidth || source.width,\n height: source.naturalHeight || source.height,\n };\n }\n return { width: source.width, height: source.height };\n}\n\n/**\n * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded frame,\n * scaled to `0..255`. See {@link LuminanceSource} for what counts as one.\n *\n * The source is downsampled so its longest edge is at most\n * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is\n * created with `willReadFrequently` so repeated sampling (live feedback) stays\n * on the fast path.\n *\n * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot\n * loop; when omitted a one-shot detached canvas is created.\n *\n * @param source - the decoded frame to sample.\n * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.\n * @returns The mean luminance in `0..255`, or `0` when the source is unloaded\n * (zero-sized) or a 2D context is unavailable.\n */\nexport function computeImageLuminance(\n source: LuminanceSource,\n reusableCanvas?: HTMLCanvasElement,\n): number {\n const { width: srcW, height: srcH } = sourceSize(source);\n if (srcW === 0 || srcH === 0) return 0;\n\n const scale = Math.min(1, LUMINANCE_SAMPLE_MAX_EDGE / Math.max(srcW, srcH));\n const w = Math.max(1, Math.round(srcW * scale));\n const h = Math.max(1, Math.round(srcH * scale));\n\n const canvas = reusableCanvas ?? document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return 0;\n ctx.drawImage(source, 0, 0, w, h);\n\n const data = ctx.getImageData(0, 0, w, h).data;\n let sum = 0;\n const pixelCount = w * h;\n for (let i = 0; i < data.length; i += 4) {\n sum += 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];\n }\n return sum / pixelCount;\n}\n\n/**\n * Whether a measured luminance clears a brightness threshold.\n *\n * `threshold` is intentionally required — a sensible value is\n * application-specific (it depends on the model, the lighting the model was\n * trained on, and the acceptable false-reject rate), so the SDK does not bake\n * in a default.\n *\n * @param luminance - measured mean luminance in `0..255`.\n * @param threshold - minimum acceptable luminance in `0..255`.\n * @returns `true` when `luminance >= threshold`.\n */\nexport function isLuminanceAcceptable(luminance: number, threshold: number): boolean {\n return luminance >= threshold;\n}\n\n/**\n * Error raised when a captured frame is too dark to be analysed reliably.\n * Carries the measured luminance and the threshold it failed so callers can\n * surface actionable feedback.\n */\nexport class LowLuminanceError extends Error {\n /** Measured mean luminance, `0..255`. */\n readonly luminance: number;\n /** Threshold that was checked against, `0..255`. */\n readonly threshold: number;\n\n /**\n * @param luminance - the measured mean luminance in `0..255`.\n * @param threshold - the threshold the measurement failed to reach.\n */\n constructor(luminance: number, threshold: number) {\n super(\"Image is too dark to analyse. Capture again in a brighter environment.\");\n this.name = \"LowLuminanceError\";\n this.luminance = luminance;\n this.threshold = threshold;\n }\n}\n"],"mappings":"AAiBA,IAAa,EAA4B,IAuBzC,SAAS,EAAW,EAA4D,CAU5E,OATI,aAAkB,iBACX,CAAE,MAAO,EAAO,WAAY,OAAQ,EAAO,WAAY,EAE9D,aAAkB,iBACX,CACH,MAAO,EAAO,cAAgB,EAAO,MACrC,OAAQ,EAAO,eAAiB,EAAO,MAC3C,EAEG,CAAE,MAAO,EAAO,MAAO,OAAQ,EAAO,MAAO,CACxD,CAmBA,SAAgB,EACZ,EACA,EACM,CACN,GAAM,CAAE,MAAO,EAAM,OAAQ,GAAS,EAAW,CAAM,EACvD,GAAI,IAAS,GAAK,IAAS,EAAG,MAAO,GAErC,IAAM,EAAQ,KAAK,IAAI,EAAA,IAA+B,KAAK,IAAI,EAAM,CAAI,CAAC,EACpE,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,CAAK,CAAC,EACxC,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,CAAK,CAAC,EAExC,EAAS,GAAkB,SAAS,cAAc,QAAQ,EAChE,EAAO,MAAQ,EACf,EAAO,OAAS,EAChB,IAAM,EAAM,EAAO,WAAW,KAAM,CAAE,mBAAoB,EAAK,CAAC,EAChE,GAAI,CAAC,EAAK,MAAO,GACjB,EAAI,UAAU,EAAQ,EAAG,EAAG,EAAG,CAAC,EAEhC,IAAM,EAAO,EAAI,aAAa,EAAG,EAAG,EAAG,CAAC,CAAC,CAAC,KACtC,EAAM,EACJ,EAAa,EAAI,EACvB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,GAAK,EAClC,GAAO,MAAS,EAAK,GAAK,MAAS,EAAK,EAAI,GAAK,MAAS,EAAK,EAAI,GAEvE,OAAO,EAAM,CACjB,CAcA,SAAgB,EAAsB,EAAmB,EAA4B,CACjF,OAAO,GAAa,CACxB,CAOA,IAAa,EAAb,cAAuC,KAAM,CAEzC,UAEA,UAMA,YAAY,EAAmB,EAAmB,CAC9C,MAAM,wEAAwE,EAC9E,KAAK,KAAO,oBACZ,KAAK,UAAY,EACjB,KAAK,UAAY,CACrB,CACJ"}
@@ -4,12 +4,12 @@ function t(e) {
4
4
  return e instanceof HTMLVideoElement ? {
5
5
  width: e.videoWidth,
6
6
  height: e.videoHeight
7
- } : e instanceof HTMLCanvasElement ? {
8
- width: e.width,
9
- height: e.height
10
- } : {
7
+ } : e instanceof HTMLImageElement ? {
11
8
  width: e.naturalWidth || e.width,
12
9
  height: e.naturalHeight || e.height
10
+ } : {
11
+ width: e.width,
12
+ height: e.height
13
13
  };
14
14
  }
15
15
  function n(e, n) {
@@ -1 +1 @@
1
- {"version":3,"file":"luminance.js","names":[],"sources":["../../src/vision/luminance.ts"],"sourcesContent":["/**\n * Frame-brightness helpers — measure the mean luminance of an already-decoded\n * `<img>`, `<video>` or `<canvas>` so a UI can reject underexposed captures\n * before paying the cost of downstream inference.\n *\n * These are framework-agnostic pure functions; {@link useLiveLuminance} wires\n * {@link computeImageLuminance} into a React `requestAnimationFrame` loop for\n * live camera feedback.\n */\n\n/**\n * Longest edge (in pixels) the source is downsampled to before sampling.\n * Averaging over a small downsample is statistically equivalent for a\n * brightness threshold and orders of magnitude faster than reading every pixel\n * of a full-resolution camera frame.\n */\nexport const LUMINANCE_SAMPLE_MAX_EDGE = 256;\n\n/** Drawable source we can sample luminance from image, video, or canvas. */\nexport type LuminanceSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;\n\n/** Natural pixel size of the source (`0`/`0` while it is still unloaded). */\nfunction sourceSize(source: LuminanceSource): { width: number; height: number } {\n if (source instanceof HTMLVideoElement) {\n return { width: source.videoWidth, height: source.videoHeight };\n }\n if (source instanceof HTMLCanvasElement) {\n return { width: source.width, height: source.height };\n }\n return {\n width: source.naturalWidth || source.width,\n height: source.naturalHeight || source.height,\n };\n}\n\n/**\n * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded\n * `<img>`, `<video>` or `<canvas>`, scaled to `0..255`.\n *\n * The source is downsampled so its longest edge is at most\n * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is\n * created with `willReadFrequently` so repeated sampling (live feedback) stays\n * on the fast path.\n *\n * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot\n * loop; when omitted a one-shot detached canvas is created.\n *\n * @param source - the image/video/canvas to sample.\n * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.\n * @returns The mean luminance in `0..255`, or `0` when the source is unloaded\n * (zero-sized) or a 2D context is unavailable.\n */\nexport function computeImageLuminance(\n source: LuminanceSource,\n reusableCanvas?: HTMLCanvasElement,\n): number {\n const { width: srcW, height: srcH } = sourceSize(source);\n if (srcW === 0 || srcH === 0) return 0;\n\n const scale = Math.min(1, LUMINANCE_SAMPLE_MAX_EDGE / Math.max(srcW, srcH));\n const w = Math.max(1, Math.round(srcW * scale));\n const h = Math.max(1, Math.round(srcH * scale));\n\n const canvas = reusableCanvas ?? document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return 0;\n ctx.drawImage(source, 0, 0, w, h);\n\n const data = ctx.getImageData(0, 0, w, h).data;\n let sum = 0;\n const pixelCount = w * h;\n for (let i = 0; i < data.length; i += 4) {\n sum += 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];\n }\n return sum / pixelCount;\n}\n\n/**\n * Whether a measured luminance clears a brightness threshold.\n *\n * `threshold` is intentionally required — a sensible value is\n * application-specific (it depends on the model, the lighting the model was\n * trained on, and the acceptable false-reject rate), so the SDK does not bake\n * in a default.\n *\n * @param luminance - measured mean luminance in `0..255`.\n * @param threshold - minimum acceptable luminance in `0..255`.\n * @returns `true` when `luminance >= threshold`.\n */\nexport function isLuminanceAcceptable(luminance: number, threshold: number): boolean {\n return luminance >= threshold;\n}\n\n/**\n * Error raised when a captured frame is too dark to be analysed reliably.\n * Carries the measured luminance and the threshold it failed so callers can\n * surface actionable feedback.\n */\nexport class LowLuminanceError extends Error {\n /** Measured mean luminance, `0..255`. */\n readonly luminance: number;\n /** Threshold that was checked against, `0..255`. */\n readonly threshold: number;\n\n /**\n * @param luminance - the measured mean luminance in `0..255`.\n * @param threshold - the threshold the measurement failed to reach.\n */\n constructor(luminance: number, threshold: number) {\n super(\"Image is too dark to analyse. Capture again in a brighter environment.\");\n this.name = \"LowLuminanceError\";\n this.luminance = luminance;\n this.threshold = threshold;\n }\n}\n"],"mappings":";AAgBA,IAAa,IAA4B;AAMzC,SAAS,EAAW,GAA4D;CAO5E,OANI,aAAkB,mBACX;EAAE,OAAO,EAAO;EAAY,QAAQ,EAAO;CAAY,IAE9D,aAAkB,oBACX;EAAE,OAAO,EAAO;EAAO,QAAQ,EAAO;CAAO,IAEjD;EACH,OAAO,EAAO,gBAAgB,EAAO;EACrC,QAAQ,EAAO,iBAAiB,EAAO;CAC3C;AACJ;AAmBA,SAAgB,EACZ,GACA,GACM;CACN,IAAM,EAAE,OAAO,GAAM,QAAQ,MAAS,EAAW,CAAM;CACvD,IAAI,MAAS,KAAK,MAAS,GAAG,OAAO;CAErC,IAAM,IAAQ,KAAK,IAAI,GAAA,MAA+B,KAAK,IAAI,GAAM,CAAI,CAAC,GACpE,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAO,CAAK,CAAC,GACxC,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAO,CAAK,CAAC,GAExC,IAAS,KAAkB,SAAS,cAAc,QAAQ;CAEhE,AADA,EAAO,QAAQ,GACf,EAAO,SAAS;CAChB,IAAM,IAAM,EAAO,WAAW,MAAM,EAAE,oBAAoB,GAAK,CAAC;CAChE,IAAI,CAAC,GAAK,OAAO;CACjB,EAAI,UAAU,GAAQ,GAAG,GAAG,GAAG,CAAC;CAEhC,IAAM,IAAO,EAAI,aAAa,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,MACtC,IAAM,GACJ,IAAa,IAAI;CACvB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK,GAClC,KAAO,QAAS,EAAK,KAAK,QAAS,EAAK,IAAI,KAAK,QAAS,EAAK,IAAI;CAEvE,OAAO,IAAM;AACjB;AAcA,SAAgB,EAAsB,GAAmB,GAA4B;CACjF,OAAO,KAAa;AACxB;AAOA,IAAa,IAAb,cAAuC,MAAM;CAEzC;CAEA;CAMA,YAAY,GAAmB,GAAmB;EAI9C,AAHA,MAAM,wEAAwE,GAC9E,KAAK,OAAO,qBACZ,KAAK,YAAY,GACjB,KAAK,YAAY;CACrB;AACJ"}
1
+ {"version":3,"file":"luminance.js","names":[],"sources":["../../src/vision/luminance.ts"],"sourcesContent":["/**\n * Frame-brightness helpers — measure the mean luminance of an already-decoded\n * frame (`<img>`, `<video>`, `<canvas>`, `ImageBitmap` or `OffscreenCanvas`) so\n * a UI can reject underexposed captures before paying the cost of downstream\n * inference.\n *\n * These are framework-agnostic pure functions; {@link useLiveLuminance} wires\n * {@link computeImageLuminance} into a React `requestAnimationFrame` loop for\n * live camera feedback.\n */\n\n/**\n * Longest edge (in pixels) the source is downsampled to before sampling.\n * Averaging over a small downsample is statistically equivalent for a\n * brightness threshold and orders of magnitude faster than reading every pixel\n * of a full-resolution camera frame.\n */\nexport const LUMINANCE_SAMPLE_MAX_EDGE = 256;\n\n/**\n * Drawable source we can sample luminance from.\n *\n * The list tracks what `CanvasRenderingContext2D.drawImage` accepts and we can\n * read a pixel size off, which is what the implementation actually needs.\n * `ImageBitmap` matters for the decode-downscaled path: `createImageBitmap(blob,\n * { resizeWidth })` is how a caller avoids materialising a full-resolution\n * phone photo, and the frame it hands back is the frame whose brightness has to\n * be checked.\n */\nexport type LuminanceSource =\n HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | OffscreenCanvas;\n\n/**\n * Natural pixel size of the source (`0`/`0` while it is still unloaded).\n *\n * `ImageBitmap` and `OffscreenCanvas` both expose plain `width`/`height`, so\n * they fall through to the same branch as a canvas — but they are named\n * explicitly rather than left to the `naturalWidth || width` fallback, which\n * only reads as intentional for an `<img>`.\n */\nfunction sourceSize(source: LuminanceSource): { width: number; height: number } {\n if (source instanceof HTMLVideoElement) {\n return { width: source.videoWidth, height: source.videoHeight };\n }\n if (source instanceof HTMLImageElement) {\n return {\n width: source.naturalWidth || source.width,\n height: source.naturalHeight || source.height,\n };\n }\n return { width: source.width, height: source.height };\n}\n\n/**\n * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded frame,\n * scaled to `0..255`. See {@link LuminanceSource} for what counts as one.\n *\n * The source is downsampled so its longest edge is at most\n * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is\n * created with `willReadFrequently` so repeated sampling (live feedback) stays\n * on the fast path.\n *\n * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot\n * loop; when omitted a one-shot detached canvas is created.\n *\n * @param source - the decoded frame to sample.\n * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.\n * @returns The mean luminance in `0..255`, or `0` when the source is unloaded\n * (zero-sized) or a 2D context is unavailable.\n */\nexport function computeImageLuminance(\n source: LuminanceSource,\n reusableCanvas?: HTMLCanvasElement,\n): number {\n const { width: srcW, height: srcH } = sourceSize(source);\n if (srcW === 0 || srcH === 0) return 0;\n\n const scale = Math.min(1, LUMINANCE_SAMPLE_MAX_EDGE / Math.max(srcW, srcH));\n const w = Math.max(1, Math.round(srcW * scale));\n const h = Math.max(1, Math.round(srcH * scale));\n\n const canvas = reusableCanvas ?? document.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return 0;\n ctx.drawImage(source, 0, 0, w, h);\n\n const data = ctx.getImageData(0, 0, w, h).data;\n let sum = 0;\n const pixelCount = w * h;\n for (let i = 0; i < data.length; i += 4) {\n sum += 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];\n }\n return sum / pixelCount;\n}\n\n/**\n * Whether a measured luminance clears a brightness threshold.\n *\n * `threshold` is intentionally required — a sensible value is\n * application-specific (it depends on the model, the lighting the model was\n * trained on, and the acceptable false-reject rate), so the SDK does not bake\n * in a default.\n *\n * @param luminance - measured mean luminance in `0..255`.\n * @param threshold - minimum acceptable luminance in `0..255`.\n * @returns `true` when `luminance >= threshold`.\n */\nexport function isLuminanceAcceptable(luminance: number, threshold: number): boolean {\n return luminance >= threshold;\n}\n\n/**\n * Error raised when a captured frame is too dark to be analysed reliably.\n * Carries the measured luminance and the threshold it failed so callers can\n * surface actionable feedback.\n */\nexport class LowLuminanceError extends Error {\n /** Measured mean luminance, `0..255`. */\n readonly luminance: number;\n /** Threshold that was checked against, `0..255`. */\n readonly threshold: number;\n\n /**\n * @param luminance - the measured mean luminance in `0..255`.\n * @param threshold - the threshold the measurement failed to reach.\n */\n constructor(luminance: number, threshold: number) {\n super(\"Image is too dark to analyse. Capture again in a brighter environment.\");\n this.name = \"LowLuminanceError\";\n this.luminance = luminance;\n this.threshold = threshold;\n }\n}\n"],"mappings":";AAiBA,IAAa,IAA4B;AAuBzC,SAAS,EAAW,GAA4D;CAU5E,OATI,aAAkB,mBACX;EAAE,OAAO,EAAO;EAAY,QAAQ,EAAO;CAAY,IAE9D,aAAkB,mBACX;EACH,OAAO,EAAO,gBAAgB,EAAO;EACrC,QAAQ,EAAO,iBAAiB,EAAO;CAC3C,IAEG;EAAE,OAAO,EAAO;EAAO,QAAQ,EAAO;CAAO;AACxD;AAmBA,SAAgB,EACZ,GACA,GACM;CACN,IAAM,EAAE,OAAO,GAAM,QAAQ,MAAS,EAAW,CAAM;CACvD,IAAI,MAAS,KAAK,MAAS,GAAG,OAAO;CAErC,IAAM,IAAQ,KAAK,IAAI,GAAA,MAA+B,KAAK,IAAI,GAAM,CAAI,CAAC,GACpE,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAO,CAAK,CAAC,GACxC,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAO,CAAK,CAAC,GAExC,IAAS,KAAkB,SAAS,cAAc,QAAQ;CAEhE,AADA,EAAO,QAAQ,GACf,EAAO,SAAS;CAChB,IAAM,IAAM,EAAO,WAAW,MAAM,EAAE,oBAAoB,GAAK,CAAC;CAChE,IAAI,CAAC,GAAK,OAAO;CACjB,EAAI,UAAU,GAAQ,GAAG,GAAG,GAAG,CAAC;CAEhC,IAAM,IAAO,EAAI,aAAa,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,MACtC,IAAM,GACJ,IAAa,IAAI;CACvB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK,GAClC,KAAO,QAAS,EAAK,KAAK,QAAS,EAAK,IAAI,KAAK,QAAS,EAAK,IAAI;CAEvE,OAAO,IAAM;AACjB;AAcA,SAAgB,EAAsB,GAAmB,GAA4B;CACjF,OAAO,KAAa;AACxB;AAOA,IAAa,IAAb,cAAuC,MAAM;CAEzC;CAEA;CAMA,YAAY,GAAmB,GAAmB;EAI9C,AAHA,MAAM,wEAAwE,GAC9E,KAAK,OAAO,qBACZ,KAAK,YAAY,GACjB,KAAK,YAAY;CACrB;AACJ"}
package/dist/vision.d.ts CHANGED
@@ -292,8 +292,8 @@ export declare interface ClassProbability {
292
292
  export declare const COCO_CLASSES: readonly string[];
293
293
 
294
294
  /**
295
- * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded
296
- * `<img>`, `<video>` or `<canvas>`, scaled to `0..255`.
295
+ * Mean BT.709 luminance (`0.2126*R + 0.7152*G + 0.0722*B`) of a decoded frame,
296
+ * scaled to `0..255`. See {@link LuminanceSource} for what counts as one.
297
297
  *
298
298
  * The source is downsampled so its longest edge is at most
299
299
  * {@link LUMINANCE_SAMPLE_MAX_EDGE} before pixels are read. The 2D context is
@@ -303,7 +303,7 @@ export declare const COCO_CLASSES: readonly string[];
303
303
  * Pass `reusableCanvas` to avoid allocating a fresh canvas every frame in a hot
304
304
  * loop; when omitted a one-shot detached canvas is created.
305
305
  *
306
- * @param source - the image/video/canvas to sample.
306
+ * @param source - the decoded frame to sample.
307
307
  * @param reusableCanvas - optional canvas reused across frames to avoid GC churn.
308
308
  * @returns The mean luminance in `0..255`, or `0` when the source is unloaded
309
309
  * (zero-sized) or a 2D context is unavailable.
@@ -761,8 +761,17 @@ export declare interface LetterboxResult {
761
761
  */
762
762
  export declare const LUMINANCE_SAMPLE_MAX_EDGE = 256;
763
763
 
764
- /** Drawable source we can sample luminance from — image, video, or canvas. */
765
- export declare type LuminanceSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;
764
+ /**
765
+ * Drawable source we can sample luminance from.
766
+ *
767
+ * The list tracks what `CanvasRenderingContext2D.drawImage` accepts and we can
768
+ * read a pixel size off, which is what the implementation actually needs.
769
+ * `ImageBitmap` matters for the decode-downscaled path: `createImageBitmap(blob,
770
+ * { resizeWidth })` is how a caller avoids materialising a full-resolution
771
+ * phone photo, and the frame it hands back is the frame whose brightness has to
772
+ * be checked.
773
+ */
774
+ export declare type LuminanceSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | OffscreenCanvas;
766
775
 
767
776
  /**
768
777
  * Single-channel binary or grayscale mask, laid out row-major.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tempest-react-sdk",
3
- "version": "0.38.1",
3
+ "version": "0.38.2",
4
4
  "description": "SDK público da Tempest com componentes, hooks e integrações para projetos React.",
5
5
  "type": "module",
6
6
  "license": "MIT",