First post, so forgive me if something is not correct. I am trying to update the image data from a HTML canvas with a PNG file as part of an exercise. The function fetch_url_binary(url: String) returns the pixel information from the PNG.
#[wasm_bindgen]
pub async fn fetch_url_binary(url: String) -> Result<Uint8Array, JsValue>
{
let window = web_sys::window().unwrap(); // Browser window
let promise = JsFuture::from(window.fetch_with_str(&url)); // File fetch promise
let result = promise.await?; // Await fulfillment of fetch
let response: web_sys::Response = result.dyn_into().unwrap(); // Type casting
let image_data = JsFuture::from(response.array_buffer()?).await?; // Get text
Ok(Uint8Array::new(&image_data))
}
The function unred(url: String, canvas: String) sets the red channel to zero then updates the canvas with the image.
#[wasm_bindgen]
pub async fn unred(url: String, canvas: String) -> Result<(), JsValue>
{
let binary = fetch_url_binary(url).await.unwrap();
let mut altbuf: Vec<u8> = Vec::new();
for n in 0..binary.length() {
if n % 4 == 0 {
binary.set_index(n,0);
}
altbuf.push(binary.get_index(n));
}
let window = web_sys::window().unwrap();
let document = window.document().expect("Could not get document");
let canvas = document.get_element_by_id(&canvas).unwrap().dyn_into::<web_sys::HtmlCanvasElement>()?;
let context = canvas.get_context("2d")?.unwrap().dyn_into::<web_sys::CanvasRenderingContext2d>()?;
let image_data_temp = ImageData::new_with_u8_clamped_array(Clamped(&altbuf), altbuf.len().try_into().unwrap());
context.put_image_data(&image_data_temp.unwrap(), 0.0, 0.0);
Ok(())
}
The associated HTML code is here:
<!doctype html><html><body>
<canvas id="myCanvas" width="300" height="200" style="border:1px solid #d3d3d3;">
<script type="module">
import init, {unred, fetch_url_binary} from './pkg/hi_lib.js';
var result;
async function run()
{
await init(); // Initialize module
unred("myPng.png", "myCanvas");
}
run(); // Execute async wrapper
</script>
</body></html>
I then test the code in a python3 http server where I get the following error:
Uncaught (in promise) hi_lib_bg.wasm:0x5a79
RuntimeError: unreachable
at hi_lib_bg.wasm:0x5a79
at hi_lib_bg.wasm:0x663a
at hi_lib_bg.wasm:0x71ba
at hi_lib_bg.wasm:0x72c9
at hi_lib_bg.wasm:0x673c
at hi_lib_bg.wasm:0x20e7
at hi_lib_bg.wasm:0x3fea
at hi_lib_bg.wasm:0x7580
at __wbg_adapter_16 (hi_lib.js:202)
at real (hi_lib.js:187)
$func69 @ hi_lib_bg.wasm:0x5a79
$func86 @ hi_lib_bg.wasm:0x663a
$func120 @ hi_lib_bg.wasm:0x71ba
$func126 @ hi_lib_bg.wasm:0x72c9
$func88 @ hi_lib_bg.wasm:0x673c
$func37 @ hi_lib_bg.wasm:0x20e7
$func48 @ hi_lib_bg.wasm:0x3fea
$_dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h51eff7df35816d6c @ hi_lib_bg.wasm:0x7580
__wbg_adapter_16 @ hi_lib.js:202
real @ hi_lib.js:187
Promise.then (async)
imports.wbg.__wbg_then_2fcac196782070cc @ hi_lib.js:440
$func67 @ hi_lib_bg.wasm:0x584d
$func66 @ hi_lib_bg.wasm:0x5709
$func61 @ hi_lib_bg.wasm:0x52af
$func103 @ hi_lib_bg.wasm:0x6cbc
$_dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h51eff7df35816d6c @ hi_lib_bg.wasm:0x7580
__wbg_adapter_16 @ hi_lib.js:202
real @ hi_lib.js:187
Promise.then (async)
imports.wbg.__wbg_then_8c2d62e8ae5978f7 @ hi_lib.js:444
$func44 @ hi_lib_bg.wasm:0x3723
$func45 @ hi_lib_bg.wasm:0x399b
$func37 @ hi_lib_bg.wasm:0x1ad6
$func48 @ hi_lib_bg.wasm:0x3fea
$_dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h51eff7df35816d6c @ hi_lib_bg.wasm:0x7580
__wbg_adapter_16 @ hi_lib.js:202
real @ hi_lib.js:187
Promise.then (async)
imports.wbg.__wbg_then_2fcac196782070cc @ hi_lib.js:440
$func67 @ hi_lib_bg.wasm:0x584d
$func66 @ hi_lib_bg.wasm:0x5709
$func61 @ hi_lib_bg.wasm:0x52af
$func103 @ hi_lib_bg.wasm:0x6cbc
$_dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h51eff7df35816d6c @ hi_lib_bg.wasm:0x7580
__wbg_adapter_16 @ hi_lib.js:202
real @ hi_lib.js:187
Promise.then (async)
imports.wbg.__wbg_then_8c2d62e8ae5978f7 @ hi_lib.js:444
$func44 @ hi_lib_bg.wasm:0x3723
$func45 @ hi_lib_bg.wasm:0x3913
$func37 @ hi_lib_bg.wasm:0x1ad6
$func48 @ hi_lib_bg.wasm:0x3fea
$_dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h51eff7df35816d6c @ hi_lib_bg.wasm:0x7580
__wbg_adapter_16 @ hi_lib.js:202
real @ hi_lib.js:187
Promise.then (async)
imports.wbg.__wbg_then_2fcac196782070cc @ hi_lib.js:440
$func67 @ hi_lib_bg.wasm:0x584d
$func64 @ hi_lib_bg.wasm:0x5503
$func79 @ hi_lib_bg.wasm:0x6202
$wasm_bindgen__convert__closures__invoke2_mut__hc0a39dba83c8fc65 @ hi_lib_bg.wasm:0x7540
__wbg_adapter_55 @ hi_lib.js:296
cb0 @ hi_lib.js:424
imports.wbg.__wbg_new_b1d61b5687f5e73a @ hi_lib.js:429
$func183 @ hi_lib_bg.wasm:0x77e4
$unred @ hi_lib_bg.wasm:0x66a2
unred @ hi_lib.js:226
run @ rust_html.html:16
await in run (async)
(anonymous) @ rust_html.html:20
I assume it has something to do with the asynchronous code, but I do not have any idea on how to solve it. I am also trying to avoid altering the javascript directly as the exercise should be completable purely in Rust.
EDIT (1) After doing some review, I think the issue is that I convert the Uint8Array into a vector and then Clamp it. It seems like the function expects an clamped array instead.
EDIT (2) I noticed another error, this time with fetch_url_binary(). The Uint8Array does not match the PNG file. There are 44750 with 4 bytes of information (RGBA) associated with each one. The Uint8Array is sized at 6384.
EDIT (3) Request for the Cargo.toml file.
[package]
name = "hi_lib"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.78"
wasm-bindgen-futures = "0.4.28"
image = "0.23.14"
[dependencies.js-sys]
version = "0.3.4"
[dependencies.web-sys]
version = "0.3.55"
features = ['Response','Window', 'HtmlElement', 'HtmlCanvasElement', 'HtmlImageElement','CanvasRenderingContext2d','Document', 'Element', 'Attr', 'ImageData']
I would recommmend going with the Cargo.toml in the answer below. There is definitely a lot of bloat with my version.
CodePudding user response:
Now when building with wasm-pack build --target web
and then serving the crates' root directory with a http server, this is the output: