Camera selector, focus controls, and decode improvements

- Camera picker with auto-selection of main back camera (index 0)
- Manual/auto focus toggle button with focus distance slider
- Dual binarizer (Hybrid + GlobalHistogram) for blur tolerance
- Only vibrate on new unique scan result
- Band canvas to restrict decoding to aim line region
- Camera select overlaid in viewfinder corner

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-21 23:53:20 +00:00
parent 730cbf5b1b
commit 2fbe6f4334
2 changed files with 48 additions and 14 deletions

23
app.mjs
View File

@@ -11,7 +11,8 @@ const cam_info = document.getElementById('cam-info');
const focus_row = document.getElementById('focus-row');
const focus_slider = document.getElementById('focus-slider');
const focus_val_el = document.getElementById('focus-val');
const focus_auto = document.getElementById('focus-auto');
const focus_auto_btn = document.getElementById('focus-auto-btn');
let focus_auto = true;
// Canvases for ZXing decode pipeline
const strip_canvas = document.createElement('canvas');
const strip_ctx = strip_canvas.getContext('2d', { willReadFrequently: true });
@@ -76,11 +77,18 @@ async function start_camera(device_id = null) {
}
if (!has_continuous) {
focus_auto.checked = false;
focus_auto.disabled = true;
focus_auto = false;
focus_auto_btn.disabled = true;
} else {
focus_auto_btn.disabled = false;
}
focus_auto.onchange = () => apply_focus(track, has_continuous, has_distance);
focus_auto_btn.classList.toggle('active', focus_auto);
focus_auto_btn.onclick = async () => {
focus_auto = !focus_auto;
focus_auto_btn.classList.toggle('active', focus_auto);
focus_slider.disabled = focus_auto;
await apply_focus(active_track, has_continuous, has_distance);
};
await apply_focus(track, has_continuous, has_distance);
// Tap to focus (replace listener on camera switch)
@@ -98,8 +106,7 @@ async function start_camera(device_id = null) {
// --- Focus ---
async function apply_focus(track, has_continuous, has_distance) {
const auto = focus_auto.checked;
focus_slider.disabled = auto;
const auto = focus_auto;
try {
if (auto && has_continuous) {
await track.applyConstraints({ advanced: [{ focusMode: 'continuous' }] });
@@ -276,9 +283,7 @@ function attempt_decode() {
band_canvas.width = strip_canvas.width;
band_canvas.height = band_h;
}
band_ctx.filter = 'contrast(1.8) brightness(1.05)';
band_ctx.drawImage(strip_canvas, 0, band_y, strip_canvas.width, band_h, 0, 0, strip_canvas.width, band_h);
band_ctx.filter = 'none';
decode_attempts++;
const source = new ZXing.HTMLCanvasElementLuminanceSource(band_canvas);