Skip to content

Desktop QR: official camera_windows 0.3.0+1, scan Windows frames in memory - #1485

Open
sneurlax wants to merge 3 commits into
stagingfrom
fix/windows-qr-camera
Open

sneurlax wants to merge 3 commits into
stagingfrom
fix/windows-qr-camera

Conversation

@sneurlax

@sneurlax sneurlax commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Tester report: QR scanning does not work on Windows for any coin. The log shows CameraException(camera_error, Failed to initialize video preview) from initializeCamera on every attempt.

Cause

Two Windows camera issues contribute to the failure:

  1. The app pinned a fork of camera_windows based on version 0.2.4. It lacks the upstream 0.3.0+1 fix for cameras that reject the preferred-stream selector. The app does not use the fork's Windows image-stream functionality.
  2. The dialog requested ResolutionPreset.low. camera_windows requires a compatible preview mode at 15 fps or higher, and some webcams do not provide one below the preset's 240-pixel cap.

Initialization failures were not shown in the dialog, leaving the user with a loading indicator and no useful recovery path.

There was also a privacy problem: the scanner polled takePicture, which always writes the capture to %USERPROFILE%\Pictures\PhotoCapture_*.jpeg. The app never removed those files, even though they may contain wallet addresses, seeds, FROST material, or node credentials and may be synchronized by services such as OneDrive. Deleting each file after reading it would still put it on disk, where sync, file recovery or the search indexer can pick it up, so this PR stops writing it at all.

Changes

Three commits:

  1. fix(desktop qr): open Windows cameras at a preset they support and show camera errors
    • Try non-IR cameras before likely IR cameras.
    • Try ResolutionPreset.medium, followed by ResolutionPreset.max, for each camera.
    • Dispose each failed camera attempt and handle the dialog closing while initialization is in progress.
    • Show camera initialization and repeated capture failures in the dialog while preserving the "Select file" fallback.
    • Throttle repeated capture-error logging and delay retries to prevent a tight failure loop.
    • Try HybridBinarizer before falling back to GlobalHistogramBinarizer when decoding live camera frames under uneven lighting.
    • Log detected Windows camera names and failed preset attempts to help diagnose hardware-specific failures.
  2. deps: use official camera_windows 0.3.0+1 from pub.dev
    • Replace the camera_windows fork with official camera_windows: ^0.3.0+1. camera_platform_interface resolves to 2.15.0.
  3. fix(desktop qr): scan Windows camera frames from the preview in memory
    • The Windows dialog shows the live preview texture and captures it in memory with RepaintBoundary.toImage(), at the camera's own resolution capped at 1280 px. takePicture is no longer called, so nothing is written to Pictures.
    • camera_windows mirrors its preview, so each capture is flipped back before decoding.
    • Errors are drawn over the preview rather than replacing it, so capture keeps running and the error clears when frames come back.
    • Blank captures (no frame drawn yet, or a covered lens) are logged once and skipped with the usual delay. A spinner shows until the first frame arrives.
    • New lib/utilities/camera_preview_frame.dart with unit tests, plus a widget test that runs a real toImage() capture of a mirrored QR code and decodes it.

Commit 1's message mentions deleting the takePicture JPEG; commit 3 replaces that path entirely.

Testing

On Windows 11 with a Depstech USB webcam, release build:

  • QR codes scan in the add-node view (Settings > Nodes > Monero > add node), including a dense one of about 260 characters.
  • No files are created or modified in Pictures during scanning.
  • Preview captures are 640x480 at the medium preset, about 4 ms each, with no blank frames.
  • A test harness pushing a QR code through a pixel-buffer texture, the same kind camera_windows uses, decoded 40/40 captures under both Impeller (the default) and Skia.

Scope

This PR does not include:

Those changes are stacked on this branch. On this PR alone, a Windows camera that opens but never delivers a frame shows the spinner with no error; #1488's 10-second timeout covers that case.

@sneurlax sneurlax added bug Something isn't working high priority labels Nov 1, 2026
@sneurlax
sneurlax added this pull request to stack #1487 November 1, 2026 21:00
@sneurlax
sneurlax force-pushed the fix/windows-qr-camera branch 3 times, most recently from 8e25aab to edfc787 Compare November 2, 2026 21:01
@sneurlax sneurlax changed the title Desktop QR: official camera_windows 0.3.0+1 Desktop QR: official camera_windows 0.3.0+1, scan Windows frames in memory Nov 2, 2026
…ow camera errors

ResolutionPreset.low caps the camera_windows preview at 240 px, so webcams
without a mode that small fail with "Failed to initialize video preview".
Try medium then max on each camera (IR cameras last), delete the JPEG that
takePicture leaves in Pictures, show init and capture failures instead of an
endless spinner, and decode with HybridBinarizer before the global one.
Replace the cypherstack/packages image-streaming fork (0.2.4, from
flutter/packages#7067, which upstream merged and later reverted). The app
only polls takePicture on Windows and never streams images. 0.3.0+1 falls
back to a physical stream when a multi-stream USB camera rejects the
preferred-stream selectors, which fixes "Failed to initialize video
preview" (flutter/flutter#140014). camera_platform_interface resolves to
2.15.0.
camera_windows' takePicture() always saves a JPEG in the user's Pictures
folder. Deleting it afterwards still puts a QR code, which may hold a seed
or private key, on disk, where OneDrive sync, file recovery or the indexer
can pick it up. Show the live preview texture instead and capture it in
memory with RepaintBoundary.toImage(), at the camera's own resolution
capped at 1280 px. camera_windows mirrors its preview, so the capture is
flipped back before decoding. Drop the capture cleanup code and its test.

Errors are drawn over the preview rather than replacing it, so capture
keeps running and the error clears when frames come back. Blank frames
(nothing drawn yet, or a covered lens) are logged once and skipped with
the usual delay, and a spinner shows until the first frame arrives.

Tested on Windows 11 with a USB webcam under Impeller and Skia: preview
captures are 640x480, two QR codes (one about 260 characters) scan in the
add-node view, and nothing is written to Pictures.

@julian-CStack julian-CStack left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setState probably doesn't need to be called as often on windows and the widget building helper functions could be extracted as stateless widgets. Performance gain would probably be negligible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working high priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants