Barcode detection in a Web Worker using Comlink

I’m a big fan of QRCodes, they are very simple and neat way to exchange data between the real world and the digital world. For a few years now I’ve had a little side project called QRSnapper — well it’s had a few names, but this is the one I’ve settled on — that uses the getUserMedia API to take live data from the user’s camera so that it can scan for QR Codes in near real time.


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan

<p>I'm a big fan of QRCodes, they are very simple and neat way to exchange data between the real world and the digital world. For a few years now I've had a little side project called <a href="https://qrsnapper.com">QRSnapper</a> — well it's had a few names, but this is the one I've settled on — that uses the <code>getUserMedia</code> API to take live data from the user's camera so that it can scan for QR Codes in near real time.</p> <p>The goal of the app was to maintain 60fps in the UI and near instant detection of the QR Code, this meant that I had to put the detection code in to a Web Worker (pretty standard stuff). In this post I just wanted to quickly share how I used <a href="https://github.com/GoogleChromeLabs/comlink">comlink</a> to massively simplify the logic in the Worker.</p> <h4 id="qrclientjs">qrclient.js</h4> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#66d9ef">import</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">Comlink</span> <span style="color:#a6e22e">from</span> <span style="color:#e6db74">'./comlink.js'</span>; <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">proxy</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">proxy</span>(<span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Worker</span>(<span style="color:#e6db74">'/scripts/qrworker.js'</span>)); <span style="color:#66d9ef">export</span> <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">decode</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">async</span> <span style="color:#66d9ef">function</span> (<span style="color:#a6e22e">context</span>) { <span style="color:#66d9ef">try</span> { <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">canvas</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">canvas</span>; <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">width</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">canvas</span>.<span style="color:#a6e22e">width</span>; <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">height</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">canvas</span>.<span style="color:#a6e22e">height</span>; <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">imageData</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">getImageData</span>(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">width</span>, <span style="color:#a6e22e">height</span>); <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">proxy</span>.<span style="color:#a6e22e">detectUrl</span>(<span style="color:#a6e22e">width</span>, <span style="color:#a6e22e">height</span>, <span style="color:#a6e22e">imageData</span>); } <span style="color:#66d9ef">catch</span> (<span style="color:#a6e22e">err</span>) { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">err</span>); } }; </code></pre></div><h4 id="qrworkerjs-web-worker">qrworker.js (web worker)</h4> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#66d9ef">import</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">as</span> <span style="color:#a6e22e">Comlink</span> <span style="color:#a6e22e">from</span> <span style="color:#e6db74">'./comlink.js'</span>; <span style="color:#66d9ef">import</span> {<span style="color:#a6e22e">qrcode</span>} <span style="color:#a6e22e">from</span> <span style="color:#e6db74">'./qrcode.js'</span>; <span style="color:#75715e">// Use the native API's </span><span style="color:#75715e"></span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">nativeDetector</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">async</span> (<span style="color:#a6e22e">width</span>, <span style="color:#a6e22e">height</span>, <span style="color:#a6e22e">imageData</span>) => { <span style="color:#66d9ef">try</span> { <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">barcodeDetector</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">BarcodeDetector</span>(); <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">barcodes</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">barcodeDetector</span>.<span style="color:#a6e22e">detect</span>(<span style="color:#a6e22e">imageData</span>); <span style="color:#75715e">// return the first barcode. </span><span style="color:#75715e"></span> <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">barcodes</span>.<span style="color:#a6e22e">length</span> <span style="color:#f92672">></span> <span style="color:#ae81ff">0</span>) { <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">barcodes</span>[<span style="color:#ae81ff">0</span>].<span style="color:#a6e22e">rawValue</span>; } } <span style="color:#66d9ef">catch</span>(<span style="color:#a6e22e">err</span>) { <span style="color:#a6e22e">detector</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">workerDetector</span>; } }; <span style="color:#75715e">// Use the polyfil </span><span style="color:#75715e"></span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">workerDetector</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">async</span> (<span style="color:#a6e22e">width</span>, <span style="color:#a6e22e">height</span>, <span style="color:#a6e22e">imageData</span>) => { <span style="color:#66d9ef">try</span> { <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">qrcode</span>.<span style="color:#a6e22e">decode</span>(<span style="color:#a6e22e">width</span>, <span style="color:#a6e22e">height</span>, <span style="color:#a6e22e">imageData</span>); } <span style="color:#66d9ef">catch</span> (<span style="color:#a6e22e">err</span>) { <span style="color:#75715e">// the library throws an excpetion when there are no qrcodes. </span><span style="color:#75715e"></span> <span style="color:#66d9ef">return</span>; } } <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">detectUrl</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">async</span> (<span style="color:#a6e22e">width</span>, <span style="color:#a6e22e">height</span>, <span style="color:#a6e22e">imageData</span>) => { <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">detector</span>(<span style="color:#a6e22e">width</span>, <span style="color:#a6e22e">height</span>, <span style="color:#a6e22e">imageData</span>); }; <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">detector</span> <span style="color:#f92672">=</span> (<span style="color:#e6db74">'BarcodeDetector'</span> <span style="color:#66d9ef">in</span> <span style="color:#a6e22e">self</span>) <span style="color:#f92672">?</span> <span style="color:#a6e22e">nativeDetector</span> <span style="color:#f92672">:</span> <span style="color:#a6e22e">workerDetector</span>; <span style="color:#75715e">// Expose the API to the client pages. </span><span style="color:#75715e"></span><span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">expose</span>({<span style="color:#a6e22e">detectUrl</span>}, <span style="color:#a6e22e">self</span>); </code></pre></div><p>I really love Comlink, I think it is a game changer of a library especially when it comes to creating idiomatic JavaScript that works across threads. Finally a neat thing here, is that the native Barcode detection API can be run inside a worker so all the logic is encapsulated away from the UI.</p> <p><a href="https://github.com/PaulKinlan/qrcode/blob/production/app/scripts/qrworker.js">Read full post</a>.</p>


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan


Print Share Comment Cite Upload Translate Updates
APA

Paul Kinlan | Sciencx (2018-10-02T21:05:31+00:00) Barcode detection in a Web Worker using Comlink. Retrieved from https://www.scien.cx/2018/10/02/barcode-detection-in-a-web-worker-using-comlink/

MLA
" » Barcode detection in a Web Worker using Comlink." Paul Kinlan | Sciencx - Tuesday October 2, 2018, https://www.scien.cx/2018/10/02/barcode-detection-in-a-web-worker-using-comlink/
HARVARD
Paul Kinlan | Sciencx Tuesday October 2, 2018 » Barcode detection in a Web Worker using Comlink., viewed ,<https://www.scien.cx/2018/10/02/barcode-detection-in-a-web-worker-using-comlink/>
VANCOUVER
Paul Kinlan | Sciencx - » Barcode detection in a Web Worker using Comlink. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2018/10/02/barcode-detection-in-a-web-worker-using-comlink/
CHICAGO
" » Barcode detection in a Web Worker using Comlink." Paul Kinlan | Sciencx - Accessed . https://www.scien.cx/2018/10/02/barcode-detection-in-a-web-worker-using-comlink/
IEEE
" » Barcode detection in a Web Worker using Comlink." Paul Kinlan | Sciencx [Online]. Available: https://www.scien.cx/2018/10/02/barcode-detection-in-a-web-worker-using-comlink/. [Accessed: ]
rf:citation
» Barcode detection in a Web Worker using Comlink | Paul Kinlan | Sciencx | https://www.scien.cx/2018/10/02/barcode-detection-in-a-web-worker-using-comlink/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.