Repository navigation
Commit 9fbb0a0
committed
fix(scanner): meter exposure on the centre of the frame
Scanning failed outright when a bright screen washed the code out, and the
reason is that auto-exposure is effectively part of the detector.
Candidate finding in scanner.cpp runs entirely on one binary image:
threshold(greyscale, whitish, 170, 255, THRESH_BINARY);
Every contour, ellipse and code the scanner ever finds comes out of that. The
cutoff is an absolute luminance, not a local or adaptive one, so the detector
never asks whether the code has contrast -- it asks whether the light ink lands
above 170 and the dark ink below it. Measured on a Solana Seeker, decoding
survives up to a black level of exactly 170 and dies at 180; from the other
side it survives down to a white level of 175 and dies at 165. Squeezed around
a mid-grey it decodes an 85-to-171 span and fails at 90-to-166 -- a code that
is still plainly legible, and completely invisible to the scanner, purely for
sitting on the wrong side of a constant.
So a clipped code is not a degraded input, it is a uniform white slab with no
contours to find. Nothing downstream can recover it.
Android left metering to the camera's whole-frame default and never requested
AE at all, not at bind and not on tap, where the existing action carried
FLAG_AF alone. Pointed at a code on a phone screen in a dim room, whole-frame
metering exposes for the room and drives the screen into clipping. iOS has
pinned exposurePointOfInterest to the centre since the session was written;
this closes that gap rather than inventing a new behaviour.
Request AE on the centre of the frame and keep it there, and add FLAG_AE to
tap-to-focus so a tap fixes exposure too -- on a washed-out code the exposure
is the half that is actually broken. Because auto-cancel drops all 3A regions
rather than only the ones the tap set, the tap re-arms the baseline afterwards
instead of silently costing it.
Two details that are load-bearing and do not read as such:
- AE only, no AF. Adding FLAG_AF to a request with auto-cancel disabled would
fire a one-shot autofocus and leave focus locked wherever it landed, which is
the opposite of what a scanner wants.
- Applied when the preview stream is actually running, not when bind returns.
startFocusAndMetering is refused with "Camera is not active" until the camera
has opened, and it refuses silently -- the first cut of this fix asked at
bind time and was cancelled every time while looking, from the source, like
it worked.
The 170 constant itself is the deeper problem, but scanner.cpp is maintained in
parallel on iOS and changing the threshold trades against false positives in a
way synthetic frames cannot measure. That is a cross-platform decision, not a
drive-by.1 parent efbd16c commit 9fbb0a0
2 files changed
Lines changed: 61 additions & 4 deletions
File tree
- ui/scanner/src/main/kotlin/com/getcode/ui/scanner
- internal
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
225 | 225 | | |
226 | 226 | | |
227 | 227 | | |
228 | | - | |
| 228 | + | |
229 | 229 | | |
230 | 230 | | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
231 | 241 | | |
232 | 242 | | |
233 | 243 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
88 | 89 | | |
89 | 90 | | |
90 | 91 | | |
91 | | - | |
92 | | - | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
93 | 99 | | |
94 | 100 | | |
95 | 101 | | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
96 | 110 | | |
97 | 111 | | |
98 | 112 | | |
| |||
114 | 128 | | |
115 | 129 | | |
116 | 130 | | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
117 | 160 | | |
118 | 161 | | |
119 | 162 | | |
| |||
156 | 199 | | |
157 | 200 | | |
158 | 201 | | |
159 | | - | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
0 commit comments