// QR Processing Module for EmblemScanner // Self-contained WASM-based QR code processing var qrtool = null; var qrtool_ready = false; /** * Load qrtool WASM module */ function load_qrtool() { var m = require('./qrtool.wx.js'); m.onRuntimeInitialized = () => { console.log("QRTool runtime initialized"); qrtool_ready = true; qrtool = m; } } /** * Check if qrtool is ready for processing */ function is_qrtool_ready() { return qrtool_ready; } /** * Process camera frame for QR code detection */ function process_frame(width, height, image_data, camera_sensitivity) { if (!qrtool_ready) { console.log("qrtool not ready"); return null; } try { // Allocate buffer for image data var buf = qrtool._malloc(image_data.length * image_data.BYTES_PER_ELEMENT); qrtool.HEAPU8.set(image_data, buf); // Process QR code detection with angle var result_str = qrtool.ccall('qrtool_angle', 'string', ['number', 'number', 'number', 'number', 'number'], [buf, width, height, 0, camera_sensitivity || 1.0] ); // Clean up buffer qrtool._free(buf); // Parse result var result = JSON.parse(result_str); return { qrcode: result.qrcode || '', angle: result.angle || 0, ok: result.ok || false, err: result.err || '', valid_pattern: is_emblem_qr_pattern(result.qrcode || '') }; } catch (error) { console.error('QR processing error:', error); return null; } } /** * Process frame with dot area extraction (for debug visualization) */ function process_frame_with_debug(width, height, image_data, camera_sensitivity) { if (!qrtool_ready) { console.log("qrtool not ready"); return null; } try { // Allocate buffer for image data var buf = qrtool._malloc(image_data.length * image_data.BYTES_PER_ELEMENT); qrtool.HEAPU8.set(image_data, buf); // Allocate buffer for debug dot area const dot_area_size = 32; const da_len = dot_area_size * dot_area_size * image_data.BYTES_PER_ELEMENT * 4; var dot_area_buf = qrtool._malloc(da_len); // Process QR code detection with debug output var result_str = qrtool.ccall('qrtool_angle', 'string', ['number', 'number', 'number', 'number', 'number'], [buf, width, height, dot_area_buf, camera_sensitivity || 1.0] ); // Extract debug image var debug_view = qrtool.HEAPU8.subarray(dot_area_buf, dot_area_buf + da_len); var debug_data_url = data_url_from_frame(dot_area_size, dot_area_size, debug_view); // Clean up buffers qrtool._free(buf); qrtool._free(dot_area_buf); // Parse result var result = JSON.parse(result_str); return { qrcode: result.qrcode || '', angle: result.angle || 0, ok: result.ok || false, err: result.err || '', valid_pattern: is_emblem_qr_pattern(result.qrcode || ''), debug_data_url: debug_data_url }; } catch (error) { console.error('QR processing error:', error); return null; } } /** * Create offscreen canvas for debug image generation */ const offscreenCanvas = wx.createOffscreenCanvas({ type: '2d', width: 100, height: 100, }); /** * Convert raw frame data to data URL for debug visualization */ function data_url_from_frame(width, height, image_data) { offscreenCanvas.width = width; offscreenCanvas.height = height; var ctx = offscreenCanvas.getContext('2d'); var imgd = ctx.createImageData(width, height); imgd.data.set(image_data); ctx.putImageData(imgd, 0, 0); return offscreenCanvas.toDataURL("image/jpeg", 1.0); } /** * Check if QR code matches Emblem pattern */ function is_emblem_qr_pattern(p) { if (!p) return false; if (p.search(/code=[0-9a-zA-Z]+/) >= 0) return true; if (p.search(/id=[0-9a-zA-Z]+/) >= 0) return true; if (p.search(/c=[0-9a-zA-Z]+/) >= 0) return true; if (p.search(/https:\/\/xy\.ltd\/v\/[0-9a-zA-Z]+/) >= 0) return true; return false; } /** * Generate hint text based on QR processing result */ function make_hint_text(result) { if (!result) { return "查找二维码"; } if (result.qrcode && result.qrcode.length > 0) { if (!result.valid_pattern) { return "无效编码"; } if (result.ok) { return "识别成功"; } // Check specific error conditions var err = result.err || ""; if (err.includes("margin too small")) { return "对齐定位点"; } else if (err.includes("energy check failed") || err.includes("cannot detect angle")) { return "移近一点"; } } return "对齐定位点"; } module.exports = { load_qrtool, is_qrtool_ready, process_frame, process_frame_with_debug, data_url_from_frame, is_emblem_qr_pattern, make_hint_text };