Skip to content

Add hex value to wasm result #584

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

Closed
wants to merge 1 commit into from
Closed

Conversation

JKamsker
Copy link

@JKamsker JKamsker commented Jul 5, 2023

The barcode may not always contain readable text data. Therefore the "hex" field contains a hexadecimal representation of the barcode "00 0a 0b..."

No idea how i could link raw bytes but i guess hex strings are okay

@axxel
Copy link
Collaborator

axxel commented Jul 6, 2023

Thanks for the effort to contribute. I don't think passing the bytes member as a hex string is the right way. What you'd like to have on the JS side is a Uint8Array. According to https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#built-in-type-conversions this should somehow be achievable via a simple std::string member, but I could not find an example. Searching for how to pass uint_8 arrays to JS mostly results in mentions of HEAPU8, which is not what I would be looking for either. If you find something, let me know.

@JKamsker
Copy link
Author

@axxel Trying to pass the binary data was my first attempt, but i failed and wasnt able to do it and i still am failing.

This pr exists out of pure necessarity, because i really need the binary, not the string data.

Maybe we can take this changes temporarily until someone manages to find a better solution (passing the bin directly)?

axxel added a commit that referenced this pull request Jul 11, 2023
This is supposed to implement #584 in a 'proper' way (still not what
I hoped it would be, see comment about `typed_memory_view`).
@axxel
Copy link
Collaborator

axxel commented Jul 11, 2023

Please have a look at my last commit. I tested it with a few binary samples. If this works for you, please close the PR.

@Sec-ant
Copy link
Contributor

Sec-ant commented Jul 12, 2023

@axxel Hey can you elaborate on your comments here:

the resulting array could contain 8 bytes of garbage

Because I just tried the memory views method and I didn't see any garbage bytes returned. Do you have any failing samples to share? I really think this should be the correct way to pass binaries to the JS side.

@axxel
Copy link
Collaborator

axxel commented Jul 12, 2023

@Sec-ant thanks for chiming in. I completely agree with you. To reproduce the problem, apply the patch below, then start emrun --serve_after_close demo_reader.html and first open the file test/samples/datamatrix-3/dm-a.jpg, then dm-c.jpg, then switch back and forth between Scan Format Any and DataMatrix. I sometimes see 44 45 41 03 16 2d 02 1e ed fd 00 ... (correct) and sometimes a8 41 04 00 a8 41 04 00 ed fd 00 ... (8 garbage bytes, the rest is correct). Observed this inside both Firefox and Chromium on Linux.

diff --git a/wrappers/wasm/BarcodeReader.cpp b/wrappers/wasm/BarcodeReader.cpp
index d749aec4..0a2da8ad 100644
--- a/wrappers/wasm/BarcodeReader.cpp
+++ b/wrappers/wasm/BarcodeReader.cpp
@@ -20,16 +20,16 @@ struct ReadResult
 {
 	std::string format{};
 	std::string text{};
-	std::string bytes{};
+//	std::string bytes{};
+	ByteArray bytes;
 	std::string error{};
 	Position position{};
 	std::string symbologyIdentifier{};
 
 //	The following seemed like the way to go, because the bytes member on the JS side would then automatically be a Uint8Array
 //	but unfortunatelly, I don't understand something about the memory management, because the resulting array could contain 8 bytes of garbage.
-//	ByteArray bytes;
-//	emscripten::val get_bytes() const { return emscripten::val(emscripten::typed_memory_view(bytes.size(), bytes.data())); }
-//	void set_bytes(emscripten::val) {} // dummy setter
+	emscripten::val get_bytes() const { return emscripten::val(emscripten::typed_memory_view(bytes.size(), bytes.data())); }
+	void set_bytes(emscripten::val) {} // dummy setter
 };
 
 std::vector<ReadResult> readBarcodes(ImageView iv, bool tryHarder, const std::string& format, int maxSymbols)
@@ -50,7 +50,7 @@ std::vector<ReadResult> readBarcodes(ImageView iv, bool tryHarder, const std::st
 		readResults.reserve(results.size());
 
 		for (auto&& result : results) {
-			readResults.push_back({ToString(result.format()), result.text(), std::string(result.bytes().asString()),
+			readResults.push_back({ToString(result.format()), result.text(), std::move(result.bytes()),
 								   ToString(result.error()), result.position(), result.symbologyIdentifier()});
 		}
 
@@ -97,7 +97,7 @@ EMSCRIPTEN_BINDINGS(BarcodeReader)
 	value_object<ReadResult>("ReadResult")
 		.field("format", &ReadResult::format)
 		.field("text", &ReadResult::text)
-		.field("bytes", &ReadResult::bytes)
+		.field("bytes", &ReadResult::get_bytes, &ReadResult::set_bytes)
 		.field("error", &ReadResult::error)
 		.field("position", &ReadResult::position)
 		.field("symbologyIdentifier", &ReadResult::symbologyIdentifier);
diff --git a/wrappers/wasm/demo_reader.html b/wrappers/wasm/demo_reader.html
index 99829f0a..86134626 100644
--- a/wrappers/wasm/demo_reader.html
+++ b/wrappers/wasm/demo_reader.html
@@ -97,7 +97,7 @@ function showResults(results) {
 			const { format, text, bytes, error } = results.get(i);
 			resultsDiv.innerHTML += "<li>Format: <strong>" + format + "</strong>"
 				+ "<pre>" + (escapeTags(text) || '<font color="red">Error: ' + error + '</font>') + "</pre>"
-				+ "<pre>" + u8a2hex(str2u8a(bytes)) + "</pre>"
+				+ "<pre>" + u8a2hex(bytes) + "</pre>"
 				+ "</li>";
 		}
 	}

@Sec-ant
Copy link
Contributor

Sec-ant commented Jul 12, 2023

@axxel OK I can reproduce this problem by simply calling the readBarcodes function for more than one times on a simple two letter QR code. I think this is related:

If this is the explanation, this seems to be the result of using memory views on stack data, not a bug in embind.

If "memory views on stack data" is the case, then I can only think of two ways to solve this:

  • If we want to do it with memory views, then we have to move the bytes to the heap and expose a clear memory function for JS to call.
  • Or just pass the binary as value, like what you did in the last commit, in string type.

I don't think barcodes can hold much raw binary data so I think what you did is the best option we have.

@Sec-ant
Copy link
Contributor

Sec-ant commented Jul 14, 2023

@axxel Most Cpp things are beyond my knowledge but what do you think of this writeup? Keeping the memory views binding while hiding memory management from the JS side would be great.

Edit: I changed the code accordingly and tested locally, I noticed no garbage bytes returned. I submitted a PR: #588, please check if there's any problem I'm not aware of. 😄

@axxel axxel closed this Jul 14, 2023
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.

3 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