@@ -298,6 +298,37 @@ public void onDisplayRemoved(int displayId) { /* Empty. */ }
298298 private final Runnable handleFrameRunnable = () -> handleFrame ();
299299 Overlay .MinMaxAvg mma = new Overlay .MinMaxAvg ();
300300
301+ private boolean isFinite (float v ) {
302+ return !isNaN (v ) && !isInfinite (v );
303+ }
304+
305+ private void mmaDownsample (Overlay .MinMaxAvg out , float [] temp , int w , int h , int step ) {
306+ out .min = out .max = NaN ;
307+ out .avg = 0.0f ;
308+ out .min_x = out .min_y = out .max_x = out .max_y = 0 ;
309+ int n = 0 ;
310+ for (int y = 0 ; y < h ; y += step ) {
311+ int row = y * w ;
312+ for (int x = 0 ; x < w ; x += step ) {
313+ float t = temp [row + x ];
314+ if (t < out .min || isNaN (out .min )) {
315+ out .min = t ;
316+ out .min_x = x ;
317+ out .min_y = y ;
318+ }
319+ if (t > out .max || isNaN (out .max )) {
320+ out .max = t ;
321+ out .max_x = x ;
322+ out .max_y = y ;
323+ }
324+ out .avg += t ;
325+ ++n ;
326+ }
327+ }
328+ if (n > 0 )
329+ out .avg /= n ;
330+ }
331+
301332 @ Override
302333 public void onFrame (InfiCam .FrameInfo fi , float [] temp ) {
303334 synchronized (frameLock ) { /* Note this is called from another thread. */
@@ -360,6 +391,48 @@ public void onFrame(InfiCam.FrameInfo fi, float[] temp) {
360391 }
361392 }
362393
394+ /*
395+ * avoid passing NaN to native and fall back to computing min/max from the buffer when
396+ * the camera-provided range looks invalid (e.g. clamps everything to the minimum).
397+ */
398+ final boolean autoMin = isNaN (overlayData .rangeMin ) || isInfinite (overlayData .rangeMin );
399+ final boolean autoMax = isNaN (overlayData .rangeMax ) || isInfinite (overlayData .rangeMax );
400+ if (autoMin && !isFinite (rangeMin ))
401+ rangeMin = fi .min ;
402+ if (autoMax && !isFinite (rangeMax ))
403+ rangeMax = fi .max ;
404+
405+ boolean suspectRange = !isFinite (rangeMin ) || !isFinite (rangeMax ) || rangeMax <= rangeMin ;
406+ if (!suspectRange && (autoMin || autoMax ) && temp != null && temp .length >= fi .width * fi .height
407+ && fi .width > 0 && fi .height > 0 ) {
408+ int centerIdx = (fi .height / 2 ) * fi .width + (fi .width / 2 );
409+ float s0 = temp [0 ];
410+ float sc = temp [centerIdx ];
411+ float s1 = temp [temp .length - 1 ];
412+ float sampleMin = java .lang .Math .min (s0 , java .lang .Math .min (sc , s1 ));
413+ float sampleMax = java .lang .Math .max (s0 , java .lang .Math .max (sc , s1 ));
414+ /* If even a few samples fall entirely outside the palette range, it's likely wrong. */
415+ if (rangeMin > sampleMax || rangeMax < sampleMin )
416+ suspectRange = true ;
417+ }
418+
419+ if (suspectRange && (autoMin || autoMax ) && temp != null && fi .width > 0 && fi .height > 0 ) {
420+ /* Downsample to keep this cheap; good enough for palette scaling. */
421+ mmaDownsample (mma , temp , fi .width , fi .height , 4 );
422+ if (isFinite (mma .min ) && isFinite (mma .max ) && mma .max > mma .min ) {
423+ fi .min = mma .min ;
424+ fi .min_x = mma .min_x ;
425+ fi .min_y = mma .min_y ;
426+ fi .max = mma .max ;
427+ fi .max_x = mma .max_x ;
428+ fi .max_y = mma .max_y ;
429+ if (autoMin )
430+ rangeMin = mma .min ;
431+ if (autoMax )
432+ rangeMax = mma .max ;
433+ }
434+ }
435+
363436
364437 infiCam .applyPalette (rangeMin , rangeMax );
365438 handler .post (handleFrameRunnable );
@@ -670,7 +743,16 @@ protected void onStart() {
670743 DisplayManager displayManager = (DisplayManager ) getSystemService (Context .DISPLAY_SERVICE );
671744 displayManager .registerDisplayListener (displayListener , handler );
672745 IntentFilter batIFilter = new IntentFilter (Intent .ACTION_BATTERY_CHANGED );
673- Intent batteryStatus = registerReceiver (batteryRecevier , batIFilter );
746+ Intent batteryStatus ;
747+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
748+ batteryStatus = registerReceiver (
749+ batteryRecevier ,
750+ batIFilter ,
751+ Context .RECEIVER_NOT_EXPORTED
752+ );
753+ } else {
754+ batteryStatus = registerReceiver (batteryRecevier , batIFilter );
755+ }
674756 updateBatLevel (batteryStatus );
675757
676758 /* Beware that we can't call these in onResume as they'll ask permission with dialogs and
0 commit comments