-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wasm? #1
Comments
I'll look into this. I'm not particularly familiar with wasm at this point, so a little research would be necessary. Off the top of my head I see a few potential issues:
I'll look into it. |
I've done a little experimentation, though a bit more is needed. The library compiles to wasm just fine, and I was able to get a simple barcode generator working without too much work. I'll play around with it and see if I can make a realistic wasm binding library for decode. |
Do you have a sample barcode you would want to decode? What sorts of formats are you looking at decoding, what input formats do you have available. My preliminary idea is to make a very simple npm package that provides methods for:
|
Single barcode is completely fine. I am looking for ECC implementations that can handle DMRE: https://www.e-d-c.info/en/projects/dmre-en.html This single-page example exposes image as a bytestream + dimensions, and I believe that's just RGB values interleaved. Converting to luminosity-only sounds reasonable
|
very early initial version (0.1.0) available on npm: https://www.npmjs.com/package/rxing-wasm the detection code for datamatrix behaves oddly when the images provided to it are small, so keep that in mind. I'd call it an early beta release. |
so far no success in detecting anything in js, likely doing something wrong I've tested on QR codes, in very rare cases it throws "Unreachable", which is probably equal to panic in rust. I've set equal dimensions to height and width (480x480) in case there is some mismatch in element ordering, but nothing changed. I use following functions (checked that output looks sane): function convertCanvasToGrayscale(canvas) {
let context = canvas.getContext('2d');
let height = canvas.height;
let width = canvas.width;
let imageData = context.getImageData(0, 0, width, height);
let data = imageData.data;
let array = new Uint8Array(data.length / 4);
// get only the red channel
for (let i = 0; i < array.length; i += 1) {
array[i] = data[i * 4];
}
return {array, width, height};
} function convertCanvasToUint32(canvas) {
let context = canvas.getContext('2d');
let height = canvas.height;
let width = canvas.width;
let imageData = context.getImageData(0, 0, width, height);
let data = imageData.data;
console.assert(data.length === width * height * 4);
let array = new Uint32Array(width * height);
for (let i = 0; i < array.length; i += 1) {
// unsure about the ordering
array[i] = data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24);
}
return {array, width, height};
} outputs are used like this: const {array, width, height} = convertCanvasToGrayscale(canvas);
let parsedBarcode = decode_barcode(array, width, height);
or
const {array, width, height} = convertCanvasToUint32(canvas);
let parsedBarcode = decode_barcode_rgb(array, width, height); |
encoding into ascii works without issues |
I generated the below qrcode and tested it with the rust luma8 decoder. It didn't have any issue decoding it, but I admit to not having tested that as extensively as the image decoder. You might try using it as the input. Here is the luma conversion that rxing (and zxing) use internally when an image is used as the source: Luma([((306 * (red as u64)
+ 601 * (green as u64)
+ 117 * (blue as u64)
+ 0x200)
>> 10) as u8]) You might try using that as your conversion. For rgb images the conversion from u32 uses the following bit shifts: for offset in 0..size {
//for (int offset = 0; offset < size; offset++) {
let pixel = pixels[offset];
let r = (pixel >> 16) & 0xff; // red
let g2 = (pixel >> 7) & 0x1fe; // 2 * green
let b = pixel & 0xff; // blue
// Calculate green-favouring average cheaply
luminances[offset] = ((r + g2 + b) / 4).try_into().unwrap();
} There are a lot of weird issues with the datamatrix decoder, most of which I think are present in the original java. It detects datamatrix codes perfectly, but then when it comes to grid sampling them it gives up some strange data. It's the same code used by both the qrcode and aztec components, which handle it fine, so I suspect it's an issue with how the datamatrix decoder handles the input. I'm still poking at it. If the barcodes are "pure" barcodes, that is, the image contains nothing but a barcode, then the decoder works perfectly (though that requires a bit of extra config for the decoder to know that they're "pure" barcodes). For a simpler (no wasm) interface you could also look at: https://github.com/zxing-js/library and https://github.com/LazarSoft/jsqrcode Sample qrcode (verified to decode with luma8) (verified in rust) Sample raw luma bytes, verified to decode with the luma8 source (80x80 image) (in rust) |
I also have a potential fix for datamatrix reading, but still implementing |
I've created a sample BW barcode too, it should be readable without doubt - but I get "unreachable" on every call, most likely this is the reason: |
Ah, didn't realize SystemTime was a no go. I'll get wasm feature added to Chrono and get system time out. |
https://www.npmjs.com/package/rxing-wasm should enable the correct features in chrono crate and remove the SystemTime calls |
it works now 🎉 ! Fast enough to run 10 times a second on 1024x768 (did not experiment much with sizes). Works nicely with QR, finicky with ECC200 DMRE |
I'm in the process of porting the c++ datamatrix detector. Apparently it's better in some situations. |
I just pushed v0.1.2 of the npm package. After a harrowing trip into c++, rxing now includes the c++ version of the datamatrix detector (https://github.com/zxing-cpp/zxing-cpp). From my initial testing it's much better at finding symbols, especially when those symbols are small, have very slim borders. It seems specifically more likely to work with DMRE codes, but I don't have a ton to test with. |
that's great news, thank you! I am about to test this in a lab, currently experiencing unrelated issues with deployment 😅 |
Yup rxing does a good job at detecting datamatrix, great work @hschimke! |
I pushed out v0.1.4 of the NPM package, which allows the use of DecodeHints. This might be helpful if you wanted to limit the types of barcodes being searched for. I haven't benchmarked, but my guess would be that it might speed up detection (possibly by a lot). It also adds a new method to convert the data from a 2dCanvas into luma8, which might be faster in wasm than javascript, but I'm honestly not sure. |
great, thanks for letting know. Will test this soon |
I have a couple fixes I'm backporting from c++ this weekend too (all datamatrix related). They will all be rolled up in the 0.1.5 realease on npm once I'm done. |
integrated both luma conversion and decode hints (I've left only two types: QR and datamatrix). Very crude estimate ~ approximately twice lower CPU load judging by profiler peaks. |
Watch out for versions 0.1.7 - 0.1.11. A change in some dependencies has caused some havoc I'm still sorting out. I suggest pinning to 0.1.6 |
This is resolved with npm version 0.1.12, apparently I didn't correctly pin the wasm_bindgen dependency in my deployment environment, so it worked fine in test and then deployed with an update that broke things, oops! |
I’m closing this for now, feel free to open a new issue if anything comes up! |
Hi Henry,
found this well-written implementation, great work.
Was looking for browser implementation of datagram scanner I could use in a lab.
So as an idea, maybe you'll be interested in compiling your library to web assembly. At least in theory, that should keep close-to-rust speed while allowing to use right from the browser.
Just an idea, feel free to close the issue.
The text was updated successfully, but these errors were encountered: