Skip to content

fix(desktop qr): decode QR images of any PNG bit depth from Select file - #1486

Merged
julian-CStack merged 2 commits into
fix/windows-qr-camerafrom
fix/qr-image-file-decoding
Nov 3, 2026
Merged

julian-CStack merged 2 commits into
fix/windows-qr-camerafrom
fix/qr-image-file-decoding

Conversation

@sneurlax

@sneurlax sneurlax commented Nov 1, 2026

Copy link
Copy Markdown
Member

Base: fix/windows-qr-camera. Second of three stacked PRs on top of the Windows QR camera fix.

"Select file" in the desktop QR dialog reports "No QR code found in the image" for some valid QR images, on every desktop platform.

Cause

The dialog built zxing's RGBLuminanceSource from image.convert(numChannels: 4). convert() keeps the source bit depth unless told otherwise, so a 1-bit PNG (Python qrcode's default output) stays bit-packed, and a 16-bit PNG keeps two bytes per channel. The bytes handed to zxing then don't match width x height pixels, it throws a RangeError, and the dialog swallows that as "no QR code". A dark code on a transparent background also has no light background once the alpha channel is dropped.

Change

  • New lib/utilities/qr_image_decoder.dart:
    • decodeQrFromImage converts any decoded image to 8-bit RGBA (which also resolves palettes) before building the luminance source.
    • Transparent pixels are composited onto white.
    • It tries HybridBinarizer, then GlobalHistogramBinarizer, as the dialog already did.
    • decodeQrFromImageBytes decodes encoded bytes first and returns null for anything that isn't an image.
  • The dialog's _scanImage calls decodeQrFromImage, so camera frames and "Select file" share one decode path.
  • New test/utilities/qr_image_decoder_test.dart, covering:
    • 1-bit grayscale and palette PNGs
    • 8-bit grayscale and palette PNGs
    • 16-bit grayscale PNGs
    • RGB and RGBA PNGs
    • dark-on-transparent PNGs
    • JPEG
    • a blank image and non-image bytes, which return null

@sneurlax
sneurlax added this pull request to stack #1487 November 1, 2026 21:00
@sneurlax sneurlax added the bug Something isn't working label Nov 1, 2026
@sneurlax
sneurlax force-pushed the fix/qr-image-file-decoding branch from e1a39db to fd41638 Compare November 2, 2026 21:01
@julian-CStack
julian-CStack force-pushed the fix/qr-image-file-decoding branch from fd41638 to 0da4fca Compare November 2, 2026 21:13
@codecov

codecov Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.00000% with 1 line in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (fix/windows-qr-camera@cdb5aff). Learn more about missing BASE report.

Files with missing lines Patch % Lines
lib/widgets/desktop/qr_code_scanner_dialog.dart 0.00% 1 Missing ⚠️
Additional details and impacted files
@@                   Coverage Diff                    @@
##             fix/windows-qr-camera    #1486   +/-   ##
========================================================
  Coverage                         ?   11.66%           
========================================================
  Files                            ?     1136           
  Lines                            ?   114344           
  Branches                         ?        0           
========================================================
  Hits                             ?    13341           
  Misses                           ?   101003           
  Partials                         ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Image.convert(numChannels: 4) keeps the source format, so a 1-bit PNG
(Python qrcode's default output) stayed bit-packed and getBytes returned a
quarter of the bytes RGBLuminanceSource reads. It threw a RangeError, which
was swallowed and reported as "No QR code found". 16-bit PNGs failed the same
way. Convert to 8-bit RGBA, build 0xAARRGGBB pixels explicitly, and
composite transparency onto white. Move the decode into
utilities/qr_image_decoder.dart with tests for 1-bit, 8-bit gray, palette,
16-bit, RGB, RGBA, transparent and JPEG input.
@julian-CStack
julian-CStack force-pushed the fix/qr-image-file-decoding branch from 82ab0bf to c41b06e Compare November 3, 2026 19:49
@julian-CStack
julian-CStack merged commit cc99e01 into staging Nov 3, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants