@moveris/shared 3.1.0 → 3.3.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/README.md CHANGED
@@ -530,26 +530,27 @@ const status = getStatusMessage('capturing', DEFAULT_LOCALE);
530
530
 
531
531
  #### Feedback Keys
532
532
 
533
- | Key | English | Description |
534
- | ------------------- | ------------------------------ | ---------------------------- |
535
- | `no_face` | "No face detected" | Face detection failed |
536
- | `face_not_centered` | "Center your face in the oval" | Face outside guide |
537
- | `too_close` | "Move back a little" | Face too close to camera |
538
- | `too_far` | "Move closer" | Face too far from camera |
539
- | `poor_lighting` | "Improve lighting" | Insufficient light |
540
- | `hold_still` | "Hold still" | Movement detected |
541
- | `capturing` | "Capturing..." | Frame capture in progress |
542
- | `processing` | "Processing..." | API verification in progress |
543
- | `success` | "Verification complete" | Successful completion |
544
- | `failed` | "Verification failed" | Failed verification |
545
- | `eyes_not_visible` | "Eyes not clearly visible" | Eye region featureless |
546
- | `eyes_shadowed` | "Eyes are in shadow…" | Eye region too dark |
547
- | `eyes_overexposed` | "Eye region overexposed…" | Eye region too bright |
548
- | `glasses_glare` | "Glare detected…" | Specular highlights on eyes |
549
- | `eye_quality_poor` | "Eye region quality is poor" | Generic eye quality failure |
550
- | `camera_angle_low` | "Raise camera to eye level" | Camera below face (Y < 0.3) |
551
- | `camera_angle_high` | "Lower camera to eye level" | Camera above face (Y > 0.7) |
552
- | `camera_tilted` | "Hold camera level" | Eye line deviates > 15° |
533
+ | Key | English | Description |
534
+ | ------------------- | ------------------------------ | --------------------------------------------------------------------------------- |
535
+ | `no_face` | "No face detected" | Face detection failed |
536
+ | `face_not_centered` | "Center your face in the oval" | Face outside guide |
537
+ | `too_close` | "Move back a little" | Face too close to camera |
538
+ | `too_far` | "Move closer" | Face too far from camera |
539
+ | `poor_lighting` | "Improve lighting" | Insufficient light |
540
+ | `hold_still` | "Hold still" | Movement detected |
541
+ | `capturing` | "Capturing..." | Frame capture in progress |
542
+ | `processing` | "Processing..." | API verification in progress |
543
+ | `success` | "Verification complete" | Successful completion |
544
+ | `failed` | "Verification failed" | Failed verification |
545
+ | `eyes_not_visible` | "Eyes not clearly visible" | Eye region featureless |
546
+ | `eyes_shadowed` | "Eyes are in shadow…" | Eye region too dark |
547
+ | `eyes_overexposed` | "Eye region overexposed…" | Eye region too bright |
548
+ | `glasses_glare` | "Glare detected…" | Specular highlights on eyes |
549
+ | `eye_quality_poor` | "Eye region quality is poor" | Generic eye quality failure |
550
+ | `camera_angle_low` | "Raise camera to eye level" | Camera below face (Y < 0.3) |
551
+ | `camera_angle_high` | "Lower camera to eye level" | Camera above face (Y > 0.7) |
552
+ | `camera_tilted` | "Hold camera level" | Device tilt > 15° (via transformation matrix, falls back to eye-corner landmarks) |
553
+ | `flat_lighting` | "Find better lighting" | Face-region dynamic range < 180 L-units — soft warning, capture continues |
553
554
 
554
555
  ---
555
556
 
@@ -641,6 +642,7 @@ import {
641
642
  isFaceInOval,
642
643
  calculateFaceCropRegion,
643
644
  detectFaceRoll,
645
+ detectFaceRollFromMatrix,
644
646
  detectCameraAngle,
645
647
  } from '@moveris/shared';
646
648
 
@@ -663,14 +665,26 @@ import { calculateAdaptiveCropMultiplier } from '@moveris/shared';
663
665
  const multiplier = calculateAdaptiveCropMultiplier(faceBox, frameWidth, frameHeight);
664
666
  // Returns 2.5–4.0x (matched to cognito-check for ~33% face coverage in 224×224 crop)
665
667
 
666
- // Detect face roll (device tilt) from eye-corner landmarks
667
- const rollResult = detectFaceRoll(landmarks); // requires ≥364 landmarks
668
- // { roll: number (degrees), tooTilted: boolean }
668
+ // Detect face roll (device tilt) prefer matrix when available (more accurate under glasses/occlusion)
669
+ if (facialTransformationMatrix) {
670
+ const rollResult = detectFaceRollFromMatrix(facialTransformationMatrix); // 16-element column-major 4×4
671
+ // { roll: number (degrees), tooTilted: boolean }
672
+ } else {
673
+ const rollResult = detectFaceRoll(landmarks); // fallback: eye-corner landmarks, requires ≥364 points
674
+ // { roll: number (degrees), tooTilted: boolean }
675
+ }
669
676
 
670
677
  // Detect camera vertical angle from forehead/nose/chin landmark ratio
671
678
  const angleResult = detectCameraAngle(landmarks); // requires ≥153 landmarks
672
679
  // { ratio: number, cameraAbove: boolean, cameraBelow: boolean }
673
680
  // ratio ~1.0 at eye level; >1.35 = camera above user; <0.75 = camera below user
681
+
682
+ // Analyse face-region dynamic range (flat lighting detection, MOV-1280)
683
+ // Pass pre-sampled face-region pixels — use sampleFaceRegionPixels() in @moveris/react
684
+ import { analyzeDynamicRange } from '@moveris/shared';
685
+ const drResult = analyzeDynamicRange(rgbaPixels);
686
+ // { range: number (max L* − min L*), isLow: boolean (< 180) }
687
+ // Soft warning — do not use as a hard capture gate
674
688
  ```
675
689
 
676
690
  #### Crop Constants (aligned with cognito-check)
package/dist/index.d.mts CHANGED
@@ -341,6 +341,14 @@ declare const MAX_FACE_RATIO = 0.7;
341
341
  declare const FACE_CROP_OUTPUT_SIZE = 224;
342
342
  declare const MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
343
343
  declare const TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
344
+ declare const DYNAMIC_RANGE_WARNING_THRESHOLD = 180;
345
+ interface DynamicRangeAnalysis {
346
+ range: number;
347
+ isLow: boolean;
348
+ }
349
+ declare function srgbToLinear(c: number): number;
350
+ declare function linearRgbToLabL(rLin: number, gLin: number, bLin: number): number;
351
+ declare function analyzeDynamicRange(rgbaPixels: Uint8ClampedArray | number[]): DynamicRangeAnalysis;
344
352
  declare function analyzeBlur(grayscalePixels: number[], width: number, height: number, threshold?: number): BlurAnalysis;
345
353
  declare function rgbaToGrayscale(rgbaPixels: Uint8ClampedArray | number[]): number[];
346
354
  declare function calculateBrightness(rgbaPixels: Uint8ClampedArray | number[]): number;
@@ -372,6 +380,7 @@ interface FaceRollResult {
372
380
  }
373
381
  declare const MAX_FACE_ROLL_DEGREES = 15;
374
382
  declare function detectFaceRoll(landmarks: FaceLandmarkPoint[]): FaceRollResult;
383
+ declare function detectFaceRollFromMatrix(matrix: number[]): FaceRollResult;
375
384
  interface CameraAngleResult {
376
385
  ratio: number;
377
386
  cameraAbove: boolean;
@@ -749,6 +758,7 @@ declare const FEEDBACK_MESSAGES: {
749
758
  readonly poor_lighting: "Improve lighting";
750
759
  readonly too_dark: "Low lighting - move to a brighter area";
751
760
  readonly backlit: "Backlit - try facing the light source";
761
+ readonly flat_lighting: "Find better lighting";
752
762
  readonly camera_angle_low: "Raise camera to eye level";
753
763
  readonly camera_angle_high: "Lower camera to eye level";
754
764
  readonly camera_tilted: "Hold camera level";
@@ -788,6 +798,7 @@ interface CaptureQualityState {
788
798
  cameraAngleHigh?: boolean;
789
799
  cameraTilted?: boolean;
790
800
  faceAreaLow?: boolean;
801
+ dynamicRangeLow?: boolean;
791
802
  }
792
803
  declare function getCaptureQualityFeedback(state: CaptureQualityState): string;
793
804
  declare function canCaptureFrame(state: Omit<CaptureQualityState, 'framesCaptured' | 'targetFrames' | 'isCapturing'>): boolean;
@@ -838,4 +849,4 @@ declare function analyzeEyeRegionContrast(pixels: Uint8Array | Uint8ClampedArray
838
849
  declare function detectSpecularHighlights(pixels: Uint8Array | Uint8ClampedArray, relativeFactor?: number, meanBrightness?: number): number;
839
850
  declare function checkEyeRegionQuality(pixels: Uint8Array | Uint8ClampedArray, thresholds?: EyeQualityThresholds): EyeRegionQuality;
840
851
 
841
- export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, CAMERA_ANGLE_HIGH_RATIO, CAMERA_ANGLE_LOW_RATIO, type CameraAngleResult, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, type DeprecationInfo, type DetectionResult, type DetectionSummary, type DetectorConfig, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CENTER_VERTICAL_OFFSET, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, IDEAL_CROP_MULTIPLIER, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_CROP_MULTIPLIER, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_CROP_MULTIPLIER, MIN_FACE_AREA_RATIO, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelVersion, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, VALID_FRAME_COUNTS, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateAdaptiveCropMultiplier, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, decodeBase64, detectCameraAngle, detectFaceRoll, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, retryWithBackoff, rgbaToGrayscale, sleep, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
852
+ export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, CAMERA_ANGLE_HIGH_RATIO, CAMERA_ANGLE_LOW_RATIO, type CameraAngleResult, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, DYNAMIC_RANGE_WARNING_THRESHOLD, type DeprecationInfo, type DetectionResult, type DetectionSummary, type DetectorConfig, type DynamicRangeAnalysis, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CENTER_VERTICAL_OFFSET, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, IDEAL_CROP_MULTIPLIER, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_CROP_MULTIPLIER, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_CROP_MULTIPLIER, MIN_FACE_AREA_RATIO, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelVersion, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, VALID_FRAME_COUNTS, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeDynamicRange, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateAdaptiveCropMultiplier, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, decodeBase64, detectCameraAngle, detectFaceRoll, detectFaceRollFromMatrix, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, linearRgbToLabL, retryWithBackoff, rgbaToGrayscale, sleep, srgbToLinear, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
package/dist/index.d.ts CHANGED
@@ -341,6 +341,14 @@ declare const MAX_FACE_RATIO = 0.7;
341
341
  declare const FACE_CROP_OUTPUT_SIZE = 224;
342
342
  declare const MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
343
343
  declare const TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
344
+ declare const DYNAMIC_RANGE_WARNING_THRESHOLD = 180;
345
+ interface DynamicRangeAnalysis {
346
+ range: number;
347
+ isLow: boolean;
348
+ }
349
+ declare function srgbToLinear(c: number): number;
350
+ declare function linearRgbToLabL(rLin: number, gLin: number, bLin: number): number;
351
+ declare function analyzeDynamicRange(rgbaPixels: Uint8ClampedArray | number[]): DynamicRangeAnalysis;
344
352
  declare function analyzeBlur(grayscalePixels: number[], width: number, height: number, threshold?: number): BlurAnalysis;
345
353
  declare function rgbaToGrayscale(rgbaPixels: Uint8ClampedArray | number[]): number[];
346
354
  declare function calculateBrightness(rgbaPixels: Uint8ClampedArray | number[]): number;
@@ -372,6 +380,7 @@ interface FaceRollResult {
372
380
  }
373
381
  declare const MAX_FACE_ROLL_DEGREES = 15;
374
382
  declare function detectFaceRoll(landmarks: FaceLandmarkPoint[]): FaceRollResult;
383
+ declare function detectFaceRollFromMatrix(matrix: number[]): FaceRollResult;
375
384
  interface CameraAngleResult {
376
385
  ratio: number;
377
386
  cameraAbove: boolean;
@@ -749,6 +758,7 @@ declare const FEEDBACK_MESSAGES: {
749
758
  readonly poor_lighting: "Improve lighting";
750
759
  readonly too_dark: "Low lighting - move to a brighter area";
751
760
  readonly backlit: "Backlit - try facing the light source";
761
+ readonly flat_lighting: "Find better lighting";
752
762
  readonly camera_angle_low: "Raise camera to eye level";
753
763
  readonly camera_angle_high: "Lower camera to eye level";
754
764
  readonly camera_tilted: "Hold camera level";
@@ -788,6 +798,7 @@ interface CaptureQualityState {
788
798
  cameraAngleHigh?: boolean;
789
799
  cameraTilted?: boolean;
790
800
  faceAreaLow?: boolean;
801
+ dynamicRangeLow?: boolean;
791
802
  }
792
803
  declare function getCaptureQualityFeedback(state: CaptureQualityState): string;
793
804
  declare function canCaptureFrame(state: Omit<CaptureQualityState, 'framesCaptured' | 'targetFrames' | 'isCapturing'>): boolean;
@@ -838,4 +849,4 @@ declare function analyzeEyeRegionContrast(pixels: Uint8Array | Uint8ClampedArray
838
849
  declare function detectSpecularHighlights(pixels: Uint8Array | Uint8ClampedArray, relativeFactor?: number, meanBrightness?: number): number;
839
850
  declare function checkEyeRegionQuality(pixels: Uint8Array | Uint8ClampedArray, thresholds?: EyeQualityThresholds): EyeRegionQuality;
840
851
 
841
- export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, CAMERA_ANGLE_HIGH_RATIO, CAMERA_ANGLE_LOW_RATIO, type CameraAngleResult, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, type DeprecationInfo, type DetectionResult, type DetectionSummary, type DetectorConfig, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CENTER_VERTICAL_OFFSET, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, IDEAL_CROP_MULTIPLIER, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_CROP_MULTIPLIER, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_CROP_MULTIPLIER, MIN_FACE_AREA_RATIO, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelVersion, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, VALID_FRAME_COUNTS, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateAdaptiveCropMultiplier, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, decodeBase64, detectCameraAngle, detectFaceRoll, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, retryWithBackoff, rgbaToGrayscale, sleep, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
852
+ export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, CAMERA_ANGLE_HIGH_RATIO, CAMERA_ANGLE_LOW_RATIO, type CameraAngleResult, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, DYNAMIC_RANGE_WARNING_THRESHOLD, type DeprecationInfo, type DetectionResult, type DetectionSummary, type DetectorConfig, type DynamicRangeAnalysis, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CENTER_VERTICAL_OFFSET, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, IDEAL_CROP_MULTIPLIER, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_CROP_MULTIPLIER, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_CROP_MULTIPLIER, MIN_FACE_AREA_RATIO, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelVersion, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, VALID_FRAME_COUNTS, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeDynamicRange, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateAdaptiveCropMultiplier, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, decodeBase64, detectCameraAngle, detectFaceRoll, detectFaceRollFromMatrix, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, linearRgbToLabL, retryWithBackoff, rgbaToGrayscale, sleep, srgbToLinear, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
package/dist/index.js CHANGED
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  DEFAULT_OVAL_REGION: () => DEFAULT_OVAL_REGION,
44
44
  DEFAULT_STABILIZER_CONFIG: () => DEFAULT_STABILIZER_CONFIG,
45
45
  DEFAULT_STATUS_MESSAGES: () => DEFAULT_STATUS_MESSAGES,
46
+ DYNAMIC_RANGE_WARNING_THRESHOLD: () => DYNAMIC_RANGE_WARNING_THRESHOLD,
46
47
  ERROR_MESSAGES: () => ERROR_MESSAGES,
47
48
  ERROR_MESSAGES_ES: () => ERROR_MESSAGES_ES,
48
49
  ES_LOCALE: () => ES_LOCALE,
@@ -88,6 +89,7 @@ __export(index_exports, {
88
89
  TARGET_FACE_PERCENTAGE_IN_CROP: () => TARGET_FACE_PERCENTAGE_IN_CROP,
89
90
  VALID_FRAME_COUNTS: () => VALID_FRAME_COUNTS,
90
91
  analyzeBlur: () => analyzeBlur,
92
+ analyzeDynamicRange: () => analyzeDynamicRange,
91
93
  analyzeEyeRegionBrightness: () => analyzeEyeRegionBrightness,
92
94
  analyzeEyeRegionContrast: () => analyzeEyeRegionContrast,
93
95
  analyzeLighting: () => analyzeLighting,
@@ -101,6 +103,7 @@ __export(index_exports, {
101
103
  decodeBase64: () => decodeBase64,
102
104
  detectCameraAngle: () => detectCameraAngle,
103
105
  detectFaceRoll: () => detectFaceRoll,
106
+ detectFaceRollFromMatrix: () => detectFaceRollFromMatrix,
104
107
  detectSpecularHighlights: () => detectSpecularHighlights,
105
108
  encodeBase64: () => encodeBase64,
106
109
  generateSessionId: () => generateSessionId,
@@ -118,9 +121,11 @@ __export(index_exports, {
118
121
  isFaceFullyVisible: () => isFaceFullyVisible,
119
122
  isFaceInOval: () => isFaceInOval,
120
123
  isRetryableError: () => isRetryableError,
124
+ linearRgbToLabL: () => linearRgbToLabL,
121
125
  retryWithBackoff: () => retryWithBackoff,
122
126
  rgbaToGrayscale: () => rgbaToGrayscale,
123
127
  sleep: () => sleep,
128
+ srgbToLinear: () => srgbToLinear,
124
129
  toFrameData: () => toFrameData,
125
130
  toHybridFrameData: () => toHybridFrameData,
126
131
  toLivenessResult: () => toLivenessResult,
@@ -1376,6 +1381,7 @@ var FEEDBACK_MESSAGES = {
1376
1381
  poor_lighting: "Improve lighting",
1377
1382
  too_dark: "Low lighting - move to a brighter area",
1378
1383
  backlit: "Backlit - try facing the light source",
1384
+ flat_lighting: "Find better lighting",
1379
1385
  // Camera angle (platform-agnostic)
1380
1386
  camera_angle_low: "Raise camera to eye level",
1381
1387
  camera_angle_high: "Lower camera to eye level",
@@ -1439,6 +1445,7 @@ var ES_LOCALE = {
1439
1445
  poor_lighting: "Mejora la iluminaci\xF3n",
1440
1446
  too_dark: "Poca luz - mu\xE9vete a un \xE1rea m\xE1s iluminada",
1441
1447
  backlit: "Contraluz - intenta mirar hacia la fuente de luz",
1448
+ flat_lighting: "Busca mejor iluminaci\xF3n",
1442
1449
  // Camera angle (platform-agnostic)
1443
1450
  camera_angle_low: "Levanta la c\xE1mara a la altura de los ojos",
1444
1451
  camera_angle_high: "Baja la c\xE1mara a la altura de los ojos",
@@ -1481,7 +1488,8 @@ function getCaptureQualityFeedback(state) {
1481
1488
  cameraAngleLow,
1482
1489
  cameraAngleHigh,
1483
1490
  cameraTilted,
1484
- faceAreaLow
1491
+ faceAreaLow,
1492
+ dynamicRangeLow
1485
1493
  } = state;
1486
1494
  if (!hasFace) {
1487
1495
  return FEEDBACK_MESSAGES.no_face;
@@ -1507,6 +1515,9 @@ function getCaptureQualityFeedback(state) {
1507
1515
  if (isBlurry) {
1508
1516
  return FEEDBACK_MESSAGES.blurry;
1509
1517
  }
1518
+ if (dynamicRangeLow) {
1519
+ return FEEDBACK_MESSAGES.flat_lighting;
1520
+ }
1510
1521
  if (tooFarFromIdeal) {
1511
1522
  return FEEDBACK_MESSAGES.move_closer_ideal;
1512
1523
  }
@@ -1631,6 +1642,33 @@ var MAX_FACE_RATIO = 0.7;
1631
1642
  var FACE_CROP_OUTPUT_SIZE = 224;
1632
1643
  var MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
1633
1644
  var TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
1645
+ var DYNAMIC_RANGE_WARNING_THRESHOLD = 180;
1646
+ function srgbToLinear(c) {
1647
+ const n = c / 255;
1648
+ return n <= 0.04045 ? n / 12.92 : Math.pow((n + 0.055) / 1.055, 2.4);
1649
+ }
1650
+ function linearRgbToLabL(rLin, gLin, bLin) {
1651
+ const Y = 0.2126 * rLin + 0.7152 * gLin + 0.0722 * bLin;
1652
+ const f = Y > 8856e-6 ? Math.cbrt(Y) : 7.787 * Y + 16 / 116;
1653
+ return 116 * f - 16;
1654
+ }
1655
+ function analyzeDynamicRange(rgbaPixels) {
1656
+ let minL = Infinity;
1657
+ let maxL = -Infinity;
1658
+ for (let i = 0; i < rgbaPixels.length; i += 4) {
1659
+ const r = rgbaPixels[i] ?? 0;
1660
+ const g = rgbaPixels[i + 1] ?? 0;
1661
+ const b = rgbaPixels[i + 2] ?? 0;
1662
+ const L = linearRgbToLabL(srgbToLinear(r), srgbToLinear(g), srgbToLinear(b));
1663
+ if (L < minL) minL = L;
1664
+ if (L > maxL) maxL = L;
1665
+ }
1666
+ if (!isFinite(minL) || !isFinite(maxL)) {
1667
+ return { range: 0, isLow: false };
1668
+ }
1669
+ const range = maxL - minL;
1670
+ return { range, isLow: range < DYNAMIC_RANGE_WARNING_THRESHOLD };
1671
+ }
1634
1672
  function analyzeBlur(grayscalePixels, width, height, threshold = DEFAULT_BLUR_THRESHOLD) {
1635
1673
  const laplacian = [];
1636
1674
  for (let y = 1; y < height - 1; y++) {
@@ -1911,6 +1949,21 @@ function detectFaceRoll(landmarks) {
1911
1949
  tooTilted: roll > MAX_FACE_ROLL_DEGREES
1912
1950
  };
1913
1951
  }
1952
+ function detectFaceRollFromMatrix(matrix) {
1953
+ if (matrix.length < 9) {
1954
+ return { roll: 0, tooTilted: false };
1955
+ }
1956
+ const m4 = matrix[4];
1957
+ const m5 = matrix[5];
1958
+ if (m4 === void 0 || m5 === void 0) {
1959
+ return { roll: 0, tooTilted: false };
1960
+ }
1961
+ const roll = Math.abs(Math.atan2(m4, m5) * (180 / Math.PI));
1962
+ return {
1963
+ roll,
1964
+ tooTilted: roll > MAX_FACE_ROLL_DEGREES
1965
+ };
1966
+ }
1914
1967
  var CAMERA_ANGLE_HIGH_RATIO = 1.35;
1915
1968
  var CAMERA_ANGLE_LOW_RATIO = 0.75;
1916
1969
  function detectCameraAngle(landmarks) {
@@ -2164,6 +2217,7 @@ function checkEyeRegionQuality(pixels, thresholds = EYE_QUALITY_THRESHOLDS) {
2164
2217
  DEFAULT_OVAL_REGION,
2165
2218
  DEFAULT_STABILIZER_CONFIG,
2166
2219
  DEFAULT_STATUS_MESSAGES,
2220
+ DYNAMIC_RANGE_WARNING_THRESHOLD,
2167
2221
  ERROR_MESSAGES,
2168
2222
  ERROR_MESSAGES_ES,
2169
2223
  ES_LOCALE,
@@ -2209,6 +2263,7 @@ function checkEyeRegionQuality(pixels, thresholds = EYE_QUALITY_THRESHOLDS) {
2209
2263
  TARGET_FACE_PERCENTAGE_IN_CROP,
2210
2264
  VALID_FRAME_COUNTS,
2211
2265
  analyzeBlur,
2266
+ analyzeDynamicRange,
2212
2267
  analyzeEyeRegionBrightness,
2213
2268
  analyzeEyeRegionContrast,
2214
2269
  analyzeLighting,
@@ -2222,6 +2277,7 @@ function checkEyeRegionQuality(pixels, thresholds = EYE_QUALITY_THRESHOLDS) {
2222
2277
  decodeBase64,
2223
2278
  detectCameraAngle,
2224
2279
  detectFaceRoll,
2280
+ detectFaceRollFromMatrix,
2225
2281
  detectSpecularHighlights,
2226
2282
  encodeBase64,
2227
2283
  generateSessionId,
@@ -2239,9 +2295,11 @@ function checkEyeRegionQuality(pixels, thresholds = EYE_QUALITY_THRESHOLDS) {
2239
2295
  isFaceFullyVisible,
2240
2296
  isFaceInOval,
2241
2297
  isRetryableError,
2298
+ linearRgbToLabL,
2242
2299
  retryWithBackoff,
2243
2300
  rgbaToGrayscale,
2244
2301
  sleep,
2302
+ srgbToLinear,
2245
2303
  toFrameData,
2246
2304
  toHybridFrameData,
2247
2305
  toLivenessResult,
package/dist/index.mjs CHANGED
@@ -1238,6 +1238,7 @@ var FEEDBACK_MESSAGES = {
1238
1238
  poor_lighting: "Improve lighting",
1239
1239
  too_dark: "Low lighting - move to a brighter area",
1240
1240
  backlit: "Backlit - try facing the light source",
1241
+ flat_lighting: "Find better lighting",
1241
1242
  // Camera angle (platform-agnostic)
1242
1243
  camera_angle_low: "Raise camera to eye level",
1243
1244
  camera_angle_high: "Lower camera to eye level",
@@ -1301,6 +1302,7 @@ var ES_LOCALE = {
1301
1302
  poor_lighting: "Mejora la iluminaci\xF3n",
1302
1303
  too_dark: "Poca luz - mu\xE9vete a un \xE1rea m\xE1s iluminada",
1303
1304
  backlit: "Contraluz - intenta mirar hacia la fuente de luz",
1305
+ flat_lighting: "Busca mejor iluminaci\xF3n",
1304
1306
  // Camera angle (platform-agnostic)
1305
1307
  camera_angle_low: "Levanta la c\xE1mara a la altura de los ojos",
1306
1308
  camera_angle_high: "Baja la c\xE1mara a la altura de los ojos",
@@ -1343,7 +1345,8 @@ function getCaptureQualityFeedback(state) {
1343
1345
  cameraAngleLow,
1344
1346
  cameraAngleHigh,
1345
1347
  cameraTilted,
1346
- faceAreaLow
1348
+ faceAreaLow,
1349
+ dynamicRangeLow
1347
1350
  } = state;
1348
1351
  if (!hasFace) {
1349
1352
  return FEEDBACK_MESSAGES.no_face;
@@ -1369,6 +1372,9 @@ function getCaptureQualityFeedback(state) {
1369
1372
  if (isBlurry) {
1370
1373
  return FEEDBACK_MESSAGES.blurry;
1371
1374
  }
1375
+ if (dynamicRangeLow) {
1376
+ return FEEDBACK_MESSAGES.flat_lighting;
1377
+ }
1372
1378
  if (tooFarFromIdeal) {
1373
1379
  return FEEDBACK_MESSAGES.move_closer_ideal;
1374
1380
  }
@@ -1493,6 +1499,33 @@ var MAX_FACE_RATIO = 0.7;
1493
1499
  var FACE_CROP_OUTPUT_SIZE = 224;
1494
1500
  var MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
1495
1501
  var TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
1502
+ var DYNAMIC_RANGE_WARNING_THRESHOLD = 180;
1503
+ function srgbToLinear(c) {
1504
+ const n = c / 255;
1505
+ return n <= 0.04045 ? n / 12.92 : Math.pow((n + 0.055) / 1.055, 2.4);
1506
+ }
1507
+ function linearRgbToLabL(rLin, gLin, bLin) {
1508
+ const Y = 0.2126 * rLin + 0.7152 * gLin + 0.0722 * bLin;
1509
+ const f = Y > 8856e-6 ? Math.cbrt(Y) : 7.787 * Y + 16 / 116;
1510
+ return 116 * f - 16;
1511
+ }
1512
+ function analyzeDynamicRange(rgbaPixels) {
1513
+ let minL = Infinity;
1514
+ let maxL = -Infinity;
1515
+ for (let i = 0; i < rgbaPixels.length; i += 4) {
1516
+ const r = rgbaPixels[i] ?? 0;
1517
+ const g = rgbaPixels[i + 1] ?? 0;
1518
+ const b = rgbaPixels[i + 2] ?? 0;
1519
+ const L = linearRgbToLabL(srgbToLinear(r), srgbToLinear(g), srgbToLinear(b));
1520
+ if (L < minL) minL = L;
1521
+ if (L > maxL) maxL = L;
1522
+ }
1523
+ if (!isFinite(minL) || !isFinite(maxL)) {
1524
+ return { range: 0, isLow: false };
1525
+ }
1526
+ const range = maxL - minL;
1527
+ return { range, isLow: range < DYNAMIC_RANGE_WARNING_THRESHOLD };
1528
+ }
1496
1529
  function analyzeBlur(grayscalePixels, width, height, threshold = DEFAULT_BLUR_THRESHOLD) {
1497
1530
  const laplacian = [];
1498
1531
  for (let y = 1; y < height - 1; y++) {
@@ -1773,6 +1806,21 @@ function detectFaceRoll(landmarks) {
1773
1806
  tooTilted: roll > MAX_FACE_ROLL_DEGREES
1774
1807
  };
1775
1808
  }
1809
+ function detectFaceRollFromMatrix(matrix) {
1810
+ if (matrix.length < 9) {
1811
+ return { roll: 0, tooTilted: false };
1812
+ }
1813
+ const m4 = matrix[4];
1814
+ const m5 = matrix[5];
1815
+ if (m4 === void 0 || m5 === void 0) {
1816
+ return { roll: 0, tooTilted: false };
1817
+ }
1818
+ const roll = Math.abs(Math.atan2(m4, m5) * (180 / Math.PI));
1819
+ return {
1820
+ roll,
1821
+ tooTilted: roll > MAX_FACE_ROLL_DEGREES
1822
+ };
1823
+ }
1776
1824
  var CAMERA_ANGLE_HIGH_RATIO = 1.35;
1777
1825
  var CAMERA_ANGLE_LOW_RATIO = 0.75;
1778
1826
  function detectCameraAngle(landmarks) {
@@ -2025,6 +2073,7 @@ export {
2025
2073
  DEFAULT_OVAL_REGION,
2026
2074
  DEFAULT_STABILIZER_CONFIG,
2027
2075
  DEFAULT_STATUS_MESSAGES,
2076
+ DYNAMIC_RANGE_WARNING_THRESHOLD,
2028
2077
  ERROR_MESSAGES,
2029
2078
  ERROR_MESSAGES_ES,
2030
2079
  ES_LOCALE,
@@ -2070,6 +2119,7 @@ export {
2070
2119
  TARGET_FACE_PERCENTAGE_IN_CROP,
2071
2120
  VALID_FRAME_COUNTS,
2072
2121
  analyzeBlur,
2122
+ analyzeDynamicRange,
2073
2123
  analyzeEyeRegionBrightness,
2074
2124
  analyzeEyeRegionContrast,
2075
2125
  analyzeLighting,
@@ -2083,6 +2133,7 @@ export {
2083
2133
  decodeBase64,
2084
2134
  detectCameraAngle,
2085
2135
  detectFaceRoll,
2136
+ detectFaceRollFromMatrix,
2086
2137
  detectSpecularHighlights,
2087
2138
  encodeBase64,
2088
2139
  generateSessionId,
@@ -2100,9 +2151,11 @@ export {
2100
2151
  isFaceFullyVisible,
2101
2152
  isFaceInOval,
2102
2153
  isRetryableError,
2154
+ linearRgbToLabL,
2103
2155
  retryWithBackoff,
2104
2156
  rgbaToGrayscale,
2105
2157
  sleep,
2158
+ srgbToLinear,
2106
2159
  toFrameData,
2107
2160
  toHybridFrameData,
2108
2161
  toLivenessResult,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moveris/shared",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "Core business logic for Moveris Live SDK",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",