Skip to content

wasm wrapper: add function to reader to scan multiple barcode #567

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

Merged
merged 6 commits into from
May 24, 2023

Conversation

Trim
Copy link
Contributor

@Trim Trim commented May 22, 2023

I wrote a new patch as discussed in #565 to update the wasm wrapper to allow to scan multiple barcodes with only one call.

This patch adds two new functions readBarcodesFromPixmap and readBarcodesFromPixmap. They return a new structure ReadResults. All found barcode are stored in the vector<ReadResult> results property (their error property is always empty). If an error occurs the results vector is empty and the std::string error property of ReadResults is filled with the exception message.

This patch is compatible with the two functions readBarcodeFromPixmap and readBarcodeFromPixmap which returned only one ReadResult with error inside it directly.

In #565 we discussed to add a default value for maxSymbols: I did not add it because it wasn't usable from the JavaScript side (an error was raised by the browser saying I had to give 5 arguments and only 4 were found).

About the JavaScript way to use the result: the register_vector emscripten function is creating a new interface and some JavaScript boilerplate code should be added to use the result.

See the binding.h emscripten file to view all methods available to interact with a vector: https://github.com/emscripten-core/emscripten/blob/98b618f09bc106d401c0045fa7252f1cd15bd3c0/system/include/emscripten/bind.h#L1894

User can either create C-like for loops with the .size() and .get(int i) methods or create a JavaScript Iterator to wrap the received result.

I've updated the demo_reader to show how to create and use the Iterator way.

The Iterator can be used with two different style: either directly loop on it (see showScanResults) or use it to create a native Javascript Array (see showImageWithResults).

If you prefer to not show this Iterator way, I can update the demo_reader to use only C-style for loops.

The demo_reader has been improved to show result in an ordered list in text and to add the result index on each barcode found in the image.

Copy link
Collaborator

@axxel axxel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

std::vector<ReadResult> results{};
std::string error{};
};

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the approach used here more. I mean to simply return a vector<ReadResult> instead of a new composite data type ReadResults. If there should be an exception, then adding a 1-element vector with the error message set, is a viable solution.

ReadResults readResults{};
readResults.results.reserve(results.size());

for ( auto& result : results) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If not too much of a hassle, please use clang-format to format your edits.

@@ -57,13 +68,49 @@ ReadResult readBarcodeFromImage(int bufferPtr, int bufferLength, bool tryHarder,
if (buffer == nullptr)
return {"", "", "Error loading image"};

return readBarcodeFromImageView({buffer.get(), width, height, ImageFormat::Lum}, tryHarder, format);
ReadResults results = readBarcodesFromImageView({buffer.get(), width, height, ImageFormat::Lum}, tryHarder, format, 1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to implement readBardcodeFromImage by calling readBardcodesFromImage and thereby not duplicating the stbi_load_... calls?

ctx.stroke();

// Example to use JavaScript Array created from an Iterator
const resultArray = Array.from(new ReaderResultVectorIterator(results));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating an array with a copy of the data here, only to then iterate over it in an indexed for loop, does not make much sense to me. Please either use the .size(), .get() API or the for( ... on ...) syntax.

@@ -12,6 +12,46 @@
zxing = instance; // this line is supposedly not required but with current emsdk it is :-/
});

/*
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This iterator seems a bit over the top, just to replace a for( int ... ) with a for( ... on ... ) loop in this simple demo, but I generally like abstractions and maybe someone learns something from it for a 'real' application. Keep it or leave it, as you prefer.

@Trim
Copy link
Contributor Author

Trim commented May 23, 2023

Thanks for the review. I've just added commits to:

  • use vector<ReaderResult> instead of a new structure
  • use the new functions to implement original ones
  • apply clang-format on BareCodeReader.cpp
  • update the demo_reader to just use .size() and .get()

Copy link
Collaborator

@axxel axxel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two one-line fixes remaining. Looking very good but I have not tested the code yet. I trust that you did ;).

{
using namespace ZXing;
auto results = readBarcodesFromImage(bufferPtr, bufferLength, tryHarder, format, 1);
return results.front();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail/throw/segfault if results is empty. A line like return results.empty() ? ReadResult() : results.front(); should work.

}

ReadResult readBarcodeFromPixmap(int bufferPtr, int imgWidth, int imgHeight, bool tryHarder, std::string format)
{
using namespace ZXing;
return readBarcodeFromImageView({reinterpret_cast<uint8_t*>(bufferPtr), imgWidth, imgHeight, ImageFormat::RGBX}, tryHarder, format);
auto results = readBarcodesFromPixmap(bufferPtr, imgWidth, imgHeight, tryHarder, format, 1);
return results.front();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@Trim
Copy link
Contributor Author

Trim commented May 24, 2023

Two one-line fixes remaining. Looking very good but I have not tested the code yet. I trust that you did ;).

Thanks for the review, I've just fixed it.

I've just tested manually with the old and new demo_reader page and images available in the test/samples/multi-1 folder :)

@axxel axxel merged commit 6c24d62 into zxing-cpp:master May 24, 2023
@axxel
Copy link
Collaborator

axxel commented May 24, 2023

Thanks a lot. I decided to squash the 6 commits into 1.

@axxel
Copy link
Collaborator

axxel commented May 24, 2023

It looks like immediately after I merged this, someone discovered an issue with the new code: #568. Could you maybe have a look at it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy