ilabs-flir 2.3.7 → 2.3.10
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/android/Flir/src/main/java/flir/android/FlirCommands.java +136 -136
- package/android/Flir/src/main/java/flir/android/FlirManager.kt +465 -521
- package/android/Flir/src/main/java/flir/android/FlirModule.kt +391 -375
- package/android/Flir/src/main/java/flir/android/FlirSdkManager.java +46 -30
- package/ios/Flir/src/FlirManager.swift +55 -103
- package/ios/Flir/src/FlirPreviewView.m +0 -3
- package/ios/Flir/src/FlirState.m +9 -3
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ import android.util.Log;
|
|
|
8
8
|
import com.flir.thermalsdk.ErrorCode;
|
|
9
9
|
import com.flir.thermalsdk.androidsdk.ThermalSdkAndroid;
|
|
10
10
|
import com.flir.thermalsdk.androidsdk.image.BitmapAndroid;
|
|
11
|
+
import com.flir.thermalsdk.image.ImageBuffer;
|
|
11
12
|
import com.flir.thermalsdk.image.Palette;
|
|
12
13
|
import com.flir.thermalsdk.image.PaletteManager;
|
|
13
14
|
import com.flir.thermalsdk.image.Point;
|
|
@@ -108,12 +109,9 @@ public class FlirSdkManager {
|
|
|
108
109
|
|
|
109
110
|
isInitialized = true;
|
|
110
111
|
Log.i(TAG, "FLIR SDK initialized successfully. Arch: " + System.getProperty("os.arch"));
|
|
112
|
+
Log.d(TAG, "SDK initialized");
|
|
111
113
|
} catch (Throwable e) {
|
|
112
114
|
Log.e(TAG, "Critical failure during FLIR SDK initialization", e);
|
|
113
|
-
}
|
|
114
|
-
Log.d(TAG, "SDK initialized");
|
|
115
|
-
} catch (Exception e) {
|
|
116
|
-
Log.e(TAG, "SDK init failed", e);
|
|
117
115
|
notifyError("SDK init failed: " + e.getMessage());
|
|
118
116
|
}
|
|
119
117
|
}
|
|
@@ -364,31 +362,38 @@ public class FlirSdkManager {
|
|
|
364
362
|
streamer.withThermalImage(thermalImage -> {
|
|
365
363
|
// 1. Apply Palette
|
|
366
364
|
if (paletteToApply != null) {
|
|
367
|
-
|
|
368
|
-
|
|
365
|
+
try {
|
|
366
|
+
List<Palette> sdkPalettes = PaletteManager.getDefaultPalettes();
|
|
369
367
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
368
|
+
if (paletteToApply.equalsIgnoreCase("Gray") || paletteToApply.equalsIgnoreCase("grayscale")) {
|
|
369
|
+
// User wants Gray - map to WhiteHot which is the SDK's standard grayscale
|
|
370
|
+
for (Palette p : sdkPalettes) {
|
|
371
|
+
if (p.name.equalsIgnoreCase("WhiteHot") || p.name.equalsIgnoreCase("White hot")) {
|
|
372
|
+
thermalImage.setPalette(p);
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
} else {
|
|
377
|
+
Palette palette = null;
|
|
378
|
+
for (Palette p : sdkPalettes) {
|
|
379
|
+
if (p.name.equalsIgnoreCase(paletteToApply)) {
|
|
380
|
+
palette = p;
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (palette != null) {
|
|
386
|
+
thermalImage.setPalette(palette);
|
|
387
|
+
} else if (paletteToApply.equalsIgnoreCase("Wheel")) {
|
|
388
|
+
// Fallback for Wheel if not found - some SDKs use different names
|
|
389
|
+
for (Palette p : sdkPalettes) {
|
|
390
|
+
if (p.name.contains("Wheel") || p.name.contains("ColorWheel") || p.name.contains("Rainbow")) {
|
|
391
|
+
thermalImage.setPalette(p);
|
|
392
|
+
break;
|
|
381
393
|
}
|
|
382
|
-
} catch (Throwable t) {
|
|
383
|
-
Log.w(TAG, "Dynamic palette lookup failed, using fallback mechanism");
|
|
384
394
|
}
|
|
385
|
-
break;
|
|
386
395
|
}
|
|
387
396
|
}
|
|
388
|
-
|
|
389
|
-
if (palette != null) {
|
|
390
|
-
thermalImage.setPalette(palette);
|
|
391
|
-
}
|
|
392
397
|
} catch (Throwable t) {
|
|
393
398
|
Log.e(TAG, "Failed to apply palette: " + paletteToApply, t);
|
|
394
399
|
}
|
|
@@ -397,8 +402,9 @@ public class FlirSdkManager {
|
|
|
397
402
|
// 2. Save Radiometric Snapshot if requested
|
|
398
403
|
if (snapshotPath != null) {
|
|
399
404
|
try {
|
|
405
|
+
Log.i(TAG, "[SNAPSHOT] Attempting to save radiometric snapshot: " + snapshotPath);
|
|
400
406
|
thermalImage.saveAs(snapshotPath);
|
|
401
|
-
Log.i(TAG, "Radiometric snapshot saved
|
|
407
|
+
Log.i(TAG, "[SNAPSHOT] ✅ Success: Radiometric snapshot saved");
|
|
402
408
|
if (snapshotCallback != null) {
|
|
403
409
|
snapshotCallback.onSnapshotSaved(snapshotPath);
|
|
404
410
|
}
|
|
@@ -411,12 +417,22 @@ public class FlirSdkManager {
|
|
|
411
417
|
}
|
|
412
418
|
|
|
413
419
|
// 3. Generate Bitmap for display
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
if (
|
|
418
|
-
|
|
420
|
+
// We use streamer.getImage() to get the rendered image with palette applied.
|
|
421
|
+
try {
|
|
422
|
+
Bitmap newBitmap = BitmapAndroid.createBitmap(streamer.getImage()).getBitMap();
|
|
423
|
+
if (newBitmap != null) {
|
|
424
|
+
Bitmap oldBitmap = latestBitmap;
|
|
425
|
+
latestBitmap = newBitmap;
|
|
426
|
+
if (listener != null) {
|
|
427
|
+
listener.onFrame(newBitmap);
|
|
428
|
+
}
|
|
429
|
+
// Recycle old bitmap to prevent memory leak
|
|
430
|
+
if (oldBitmap != null && oldBitmap != newBitmap) {
|
|
431
|
+
oldBitmap.recycle();
|
|
432
|
+
}
|
|
419
433
|
}
|
|
434
|
+
} catch (Exception e) {
|
|
435
|
+
Log.e(TAG, "Bitmap creation failed", e);
|
|
420
436
|
}
|
|
421
437
|
});
|
|
422
438
|
}
|
|
@@ -191,7 +191,8 @@ import ThermalSDK
|
|
|
191
191
|
NSLog("[FlirManager] Network camera detected — authenticating...")
|
|
192
192
|
|
|
193
193
|
// Use UUID-based persistent certificate name (matches FLIR sample).
|
|
194
|
-
// The camera has a bug where re-auth with a different name
|
|
194
|
+
// The camera has a bug where re-auth with a different name can conflict,
|
|
195
|
+
// so we generate a UUID once and persist it in UserDefaults.
|
|
195
196
|
let certName = self.getPersistentCertificateName()
|
|
196
197
|
NSLog("[FlirManager] Using certificate name: \(certName)")
|
|
197
198
|
|
|
@@ -435,7 +436,7 @@ import ThermalSDK
|
|
|
435
436
|
// Compiler says it is NOT optional here, so direct assignment.
|
|
436
437
|
let value = spot.getValue()
|
|
437
438
|
result = value.value
|
|
438
|
-
|
|
439
|
+
|
|
439
440
|
try? measurements.remove(spot)
|
|
440
441
|
}
|
|
441
442
|
}
|
|
@@ -445,8 +446,6 @@ import ThermalSDK
|
|
|
445
446
|
#endif
|
|
446
447
|
}
|
|
447
448
|
|
|
448
|
-
|
|
449
|
-
|
|
450
449
|
@objc public func getTemperatureAtNormalized(_ nx: Double, y: Double) -> Double {
|
|
451
450
|
#if FLIR_ENABLED
|
|
452
451
|
guard let streamer = streamer, _isStreaming else { return Double.nan }
|
|
@@ -458,10 +457,10 @@ import ThermalSDK
|
|
|
458
457
|
|
|
459
458
|
// Map normalized (0.0 - 1.0) to actual sensor pixels
|
|
460
459
|
let cx = max(0, min(Int(w) - 1, Int(nx * w)))
|
|
461
|
-
let
|
|
460
|
+
let cy_fixed = max(0, min(Int(h) - 1, Int(y * h)))
|
|
462
461
|
|
|
463
462
|
if let measurements = thermalImage.measurements,
|
|
464
|
-
let spot = try? measurements.addSpot(CGPoint(x: cx, y:
|
|
463
|
+
let spot = try? measurements.addSpot(CGPoint(x: cx, y: cy_fixed)) {
|
|
465
464
|
result = spot.getValue().value
|
|
466
465
|
try? measurements.remove(spot)
|
|
467
466
|
}
|
|
@@ -503,8 +502,6 @@ import ThermalSDK
|
|
|
503
502
|
|
|
504
503
|
// MARK: - Battery (stub - not needed per user)
|
|
505
504
|
|
|
506
|
-
// MARK: - Battery (stub - not needed per user)
|
|
507
|
-
|
|
508
505
|
@objc public func getBatteryLevel() -> Int { return -1 }
|
|
509
506
|
@objc public func isBatteryCharging() -> Bool { return false }
|
|
510
507
|
|
|
@@ -520,72 +517,29 @@ import ThermalSDK
|
|
|
520
517
|
}
|
|
521
518
|
|
|
522
519
|
@objc public func setPaletteFromAcol(_ acol: Float) {
|
|
523
|
-
// Map acol to dynamic palette names
|
|
524
520
|
let palettes = getAvailablePalettes()
|
|
525
521
|
let idx = Int(acol)
|
|
526
|
-
|
|
527
|
-
|
|
522
|
+
let maxEff = palettes.count
|
|
523
|
+
if maxEff > 0 {
|
|
524
|
+
let paletteIdx = idx % maxEff
|
|
525
|
+
let safeIdx = paletteIdx < 0 ? paletteIdx + maxEff : paletteIdx
|
|
526
|
+
setPalette(palettes[safeIdx])
|
|
528
527
|
}
|
|
529
528
|
}
|
|
530
529
|
|
|
531
530
|
@objc public func getAvailablePalettes() -> [String] {
|
|
532
|
-
|
|
533
|
-
if let streamer = streamer {
|
|
534
|
-
var names: [String] = []
|
|
535
|
-
streamer.withThermalImage { img in
|
|
536
|
-
var palettes = img.paletteManager.getDefaultPalettes().map { $0.name }
|
|
537
|
-
// Reorder: Move WhiteHot/Gray to the front
|
|
538
|
-
if let grayIdx = palettes.firstIndex(where: { $0.lowercased() == "whitehot" || $0.lowercased() == "gray" }) {
|
|
539
|
-
let gray = palettes.remove(at: grayIdx)
|
|
540
|
-
palettes.insert(gray, at: 0)
|
|
541
|
-
}
|
|
542
|
-
names = palettes
|
|
543
|
-
}
|
|
544
|
-
if !names.isEmpty { return names }
|
|
545
|
-
}
|
|
546
|
-
#endif
|
|
547
|
-
return ["WhiteHot", "iron", "rainbow", "arctic", "lava", "contrast", "hotcold", "medical"]
|
|
531
|
+
return ["WhiteHot", "Iron", "Rainbow", "Arctic", "Lava", "Coldest", "Hottest", "Wheel"]
|
|
548
532
|
}
|
|
549
533
|
|
|
550
534
|
@objc public func generatePaletteIcons() -> [[String: String]] {
|
|
535
|
+
let paletteNames = getAvailablePalettes()
|
|
551
536
|
var results: [[String: String]] = []
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
let paletteDir = cacheDir.appendingPathComponent("flir_palettes")
|
|
558
|
-
|
|
559
|
-
if !fileManager.fileExists(atPath: paletteDir.path) {
|
|
560
|
-
try? fileManager.createDirectory(at: paletteDir, withIntermediateDirectories: true)
|
|
537
|
+
for name in paletteNames {
|
|
538
|
+
results.append([
|
|
539
|
+
"name": name,
|
|
540
|
+
"uri": "" // No URI - rely on local assets if any
|
|
541
|
+
])
|
|
561
542
|
}
|
|
562
|
-
|
|
563
|
-
streamer.withThermalImage { thermalImage in
|
|
564
|
-
var palettes = thermalImage.paletteManager.getDefaultPalettes()
|
|
565
|
-
|
|
566
|
-
// Reorder: Move WhiteHot/Gray to the front
|
|
567
|
-
if let grayIdx = palettes.firstIndex(where: { $0.name.lowercased() == "whitehot" || $0.name.lowercased() == "gray" }) {
|
|
568
|
-
let gray = palettes.remove(at: grayIdx)
|
|
569
|
-
palettes.insert(gray, at: 0)
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
for palette in palettes {
|
|
573
|
-
let iconURL = paletteDir.appendingPathComponent("\(palette.name.lowercased()).png")
|
|
574
|
-
if !fileManager.fileExists(atPath: iconURL.path) {
|
|
575
|
-
// Assuming palette.icon exists (common in FLIR SDK)
|
|
576
|
-
if let icon = palette.icon {
|
|
577
|
-
if let data = icon.pngData() {
|
|
578
|
-
try? data.write(to: iconURL)
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
results.append([
|
|
583
|
-
"name": palette.name,
|
|
584
|
-
"uri": fileManager.fileExists(atPath: iconURL.path) ? iconURL.absoluteString : ""
|
|
585
|
-
])
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
#endif
|
|
589
543
|
return results
|
|
590
544
|
}
|
|
591
545
|
|
|
@@ -642,20 +596,15 @@ import ThermalSDK
|
|
|
642
596
|
return newName
|
|
643
597
|
}
|
|
644
598
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
if iface.contains(.lightning) { return "LIGHTNING" }
|
|
648
|
-
if iface.contains(.network) { return "NETWORK" }
|
|
649
|
-
if iface.contains(.flirOneWireless) { return "WIRELESS" }
|
|
650
|
-
if iface.contains(.emulator) { return "EMULATOR" }
|
|
599
|
+
private func interfaceName(_ iface: Int) -> String {
|
|
600
|
+
// Placeholder for interface name mapping
|
|
651
601
|
return "UNKNOWN"
|
|
652
602
|
}
|
|
653
|
-
#endif
|
|
654
603
|
}
|
|
655
604
|
|
|
605
|
+
#if FLIR_ENABLED
|
|
656
606
|
// MARK: - Discovery Delegate
|
|
657
607
|
|
|
658
|
-
#if FLIR_ENABLED
|
|
659
608
|
extension FlirManager: FLIRDiscoveryEventDelegate {
|
|
660
609
|
public func cameraDiscovered(_ camera: FLIRDiscoveredCamera) {
|
|
661
610
|
let identity = camera.identity
|
|
@@ -670,7 +619,7 @@ extension FlirManager: FLIRDiscoveryEventDelegate {
|
|
|
670
619
|
let deviceInfo = FlirDeviceInfo(
|
|
671
620
|
deviceId: deviceId,
|
|
672
621
|
name: camera.displayName ?? deviceId,
|
|
673
|
-
communicationType: interfaceName(identity.communicationInterface()),
|
|
622
|
+
communicationType: interfaceName(Int(identity.communicationInterface().rawValue)),
|
|
674
623
|
isEmulator: identity.communicationInterface() == .emulator
|
|
675
624
|
)
|
|
676
625
|
|
|
@@ -691,7 +640,7 @@ extension FlirManager: FLIRDiscoveryEventDelegate {
|
|
|
691
640
|
}
|
|
692
641
|
|
|
693
642
|
public func discoveryFinished(_ iface: FLIRCommunicationInterface) {
|
|
694
|
-
NSLog("[FlirManager] Discovery finished: \(iface)")
|
|
643
|
+
NSLog("[FlirManager] Discovery finished: \(iface.rawValue)")
|
|
695
644
|
}
|
|
696
645
|
|
|
697
646
|
public func cameraLost(_ cameraIdentity: FLIRIdentity) {
|
|
@@ -707,11 +656,9 @@ extension FlirManager: FLIRDiscoveryEventDelegate {
|
|
|
707
656
|
}
|
|
708
657
|
}
|
|
709
658
|
}
|
|
710
|
-
#endif
|
|
711
659
|
|
|
712
660
|
// MARK: - Camera Delegate
|
|
713
661
|
|
|
714
|
-
#if FLIR_ENABLED
|
|
715
662
|
extension FlirManager: FLIRDataReceivedDelegate {
|
|
716
663
|
public func onDisconnected(_ camera: FLIRCamera, withError error: Error?) {
|
|
717
664
|
NSLog("[FlirManager] Camera disconnected: \(error?.localizedDescription ?? "clean")")
|
|
@@ -728,11 +675,9 @@ extension FlirManager: FLIRDataReceivedDelegate {
|
|
|
728
675
|
}
|
|
729
676
|
}
|
|
730
677
|
}
|
|
731
|
-
#endif
|
|
732
678
|
|
|
733
679
|
// MARK: - Stream Delegate
|
|
734
680
|
|
|
735
|
-
#if FLIR_ENABLED
|
|
736
681
|
extension FlirManager: FLIRStreamDelegate {
|
|
737
682
|
public func onError(_ error: Error) {
|
|
738
683
|
NSLog("[FlirManager] Stream error: \(error)")
|
|
@@ -740,13 +685,10 @@ extension FlirManager: FLIRStreamDelegate {
|
|
|
740
685
|
}
|
|
741
686
|
|
|
742
687
|
public func onImageReceived() {
|
|
743
|
-
NSLog("[FLIR-TRACE 1️⃣] onImageReceived called on SDK thread")
|
|
744
|
-
|
|
745
688
|
// Process frame on dedicated render queue (matches sample app pattern)
|
|
746
689
|
// This prevents blocking the SDK callback thread and main thread
|
|
747
690
|
// Guard to skip frame if already processing (prevents backpressure/latency)
|
|
748
691
|
guard !_isProcessingFrame else {
|
|
749
|
-
NSLog("[FLIR-TRACE ⏩] Skipping frame (already processing)")
|
|
750
692
|
return
|
|
751
693
|
}
|
|
752
694
|
|
|
@@ -754,12 +696,9 @@ extension FlirManager: FLIRStreamDelegate {
|
|
|
754
696
|
renderQueue.async { [weak self] in
|
|
755
697
|
defer { self?._isProcessingFrame = false }
|
|
756
698
|
guard let self = self, self._isStreaming, let streamer = self.streamer else {
|
|
757
|
-
NSLog("[FLIR-TRACE ❌] No self, streamer or not streaming in renderQueue")
|
|
758
699
|
return
|
|
759
700
|
}
|
|
760
701
|
|
|
761
|
-
NSLog("[FLIR-TRACE 2️⃣] Processing on renderQueue")
|
|
762
|
-
|
|
763
702
|
objc_sync_enter(self.stateLock)
|
|
764
703
|
let currentStreamer = self.streamer
|
|
765
704
|
let streaming = self._isStreaming
|
|
@@ -778,7 +717,26 @@ extension FlirManager: FLIRStreamDelegate {
|
|
|
778
717
|
|
|
779
718
|
streamer.withThermalImage { thermalImage in
|
|
780
719
|
// 1. Apply Palette
|
|
781
|
-
|
|
720
|
+
let sdkPalettes = thermalImage.paletteManager.getDefaultPalettes()
|
|
721
|
+
var targetPalette: FLIRPalette? = nil
|
|
722
|
+
|
|
723
|
+
if paletteToApply.lowercased() == "gray" || paletteToApply.lowercased() == "grayscale" {
|
|
724
|
+
// Map Gray to WhiteHot (standard SDK name)
|
|
725
|
+
targetPalette = sdkPalettes.first(where: {
|
|
726
|
+
$0.name.lowercased() == "whitehot" || $0.name.lowercased() == "white hot"
|
|
727
|
+
})
|
|
728
|
+
} else {
|
|
729
|
+
targetPalette = sdkPalettes.first(where: { $0.name.lowercased() == paletteToApply.lowercased() })
|
|
730
|
+
|
|
731
|
+
// Fallback for Wheel
|
|
732
|
+
if targetPalette == nil && paletteToApply.lowercased() == "wheel" {
|
|
733
|
+
targetPalette = sdkPalettes.first(where: {
|
|
734
|
+
$0.name.contains("Wheel") || $0.name.contains("ColorWheel") || $0.name.contains("Rainbow")
|
|
735
|
+
})
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
if let palette = targetPalette {
|
|
782
740
|
thermalImage.palette = palette
|
|
783
741
|
}
|
|
784
742
|
|
|
@@ -791,29 +749,23 @@ extension FlirManager: FLIRStreamDelegate {
|
|
|
791
749
|
NSLog("[FlirManager] Failed to save radiometric snapshot: \(error)")
|
|
792
750
|
}
|
|
793
751
|
}
|
|
752
|
+
|
|
753
|
+
// 3. Generate UIImage for display
|
|
754
|
+
// Grab the image while the thermal image is locked to ensure settings are applied
|
|
755
|
+
if let image = streamer.getImage() {
|
|
756
|
+
self._latestImage = image
|
|
757
|
+
let width = Int(image.size.width)
|
|
758
|
+
let height = Int(image.size.height)
|
|
759
|
+
|
|
760
|
+
DispatchQueue.main.async { [weak self] in
|
|
761
|
+
self?.delegate?.onFrameReceived(image, width: width, height: height)
|
|
762
|
+
}
|
|
763
|
+
}
|
|
794
764
|
}
|
|
795
|
-
|
|
796
|
-
NSLog("[FLIR-TRACE 3️⃣] Streamer updated successfully")
|
|
797
765
|
} catch {
|
|
798
|
-
NSLog("[
|
|
799
|
-
return
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
guard let image = streamer.getImage() else {
|
|
803
|
-
NSLog("[FLIR-TRACE ❌] streamer.getImage() returned nil")
|
|
766
|
+
NSLog("[FlirManager] Streamer update failed: \(error)")
|
|
804
767
|
return
|
|
805
768
|
}
|
|
806
|
-
|
|
807
|
-
NSLog("[FLIR-TRACE 4️⃣] Got image from streamer: \(image.size.width)x\(image.size.height)")
|
|
808
|
-
|
|
809
|
-
self._latestImage = image
|
|
810
|
-
let width = Int(image.size.width)
|
|
811
|
-
let height = Int(image.size.height)
|
|
812
|
-
|
|
813
|
-
DispatchQueue.main.async { [weak self] in
|
|
814
|
-
NSLog("[FLIR-TRACE 5️⃣] Dispatching to delegate.onFrameReceived on main thread")
|
|
815
|
-
self?.delegate?.onFrameReceived(image, width: width, height: height)
|
|
816
|
-
}
|
|
817
769
|
}
|
|
818
770
|
}
|
|
819
771
|
}
|
package/ios/Flir/src/FlirState.m
CHANGED
|
@@ -89,9 +89,6 @@ static FlirState *_sharedState = nil;
|
|
|
89
89
|
|
|
90
90
|
- (void)updateFrame:(UIImage *)image
|
|
91
91
|
withTemperatureData:(NSArray<NSNumber *> *)tempData {
|
|
92
|
-
if (!image)
|
|
93
|
-
return;
|
|
94
|
-
|
|
95
92
|
dispatch_async(_accessQueue, ^{
|
|
96
93
|
self.latestImage = image;
|
|
97
94
|
|
|
@@ -157,6 +154,15 @@ static FlirState *_sharedState = nil;
|
|
|
157
154
|
self->_temperatureData = nil;
|
|
158
155
|
self->_imageWidth = 0;
|
|
159
156
|
self->_imageHeight = 0;
|
|
157
|
+
|
|
158
|
+
// Notify view to clear instantly
|
|
159
|
+
if (self.onTextureUpdate) {
|
|
160
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
161
|
+
if (self.onTextureUpdate) {
|
|
162
|
+
self.onTextureUpdate(nil, 7);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
160
166
|
});
|
|
161
167
|
}
|
|
162
168
|
|