Эффективное взаимодействие с canvas и ImageData от. NET WebAssembly - PullRequest
0 голосов
/ 11 апреля 2020

Я хотел бы получить данные изображения в. NET WebAssembly и затем нарисовать его на элементе html5 canvas.

Я нашел пример Rust, который взаимодействует с canvas и отображает данные изображения через его web_sys библиотека взаимодействия: https://rustwasm.github.io/wasm-bindgen/examples/julia.html

Интересно, что у Rust есть прозрачный доступ к html5 ImageData и CanvasRenderingContext2d объектам.

Соответствующий источник код:

index. js

import('./pkg')
    .then(wasm => {
        const canvas = document.getElementById('drawing');
        const ctx = canvas.getContext('2d');        
        wasm.draw(ctx, 600, 600);
    })
    .catch(console.error);

lib.rs

use web_sys::{CanvasRenderingContext2d, ImageData};

#[wasm_bindgen]
pub fn draw(
    ctx: &CanvasRenderingContext2d,
    width: u32,
    height: u32
) -> Result<(), JsValue> {
    let mut data = somefunction(width, height);
    let data = ImageData::new_with_u8_clamped_array_and_sh(Clamped(&mut data), width, height)?;
    ctx.put_image_data(&data, 0.0, 0.0)
}

Что бы соответствующий Blazor. NET WebAssembly?

Внедренный мной обходной путь использует json serializion, который является частью реализации. NET JSInterop, для передачи байтового массива из. NET WebAssembly в JavaScript. В результате получается строка в кодировке mime64 на стороне JavaScript, которая затем должна быть сначала декодирована, прежде чем ее можно преобразовать в объект ImageData.

Соответствующий код:

MyComponent.razor .cs

public partial class MyComponent : ComponentBase
{
   protected override async Task OnAfterRenderAsync(bool firstRender)
   {
       var bytearray = somefunction(600, 600);
       await jSRuntime.InvokeVoidAsync("draw", 600, 600, bytearray);
   }
}

blazorcanvasinterop.ts

draw(xw: number, yw: number, pixelsbase64: string): void {
    const canvas = document.getElementById('drawing');
    const ctx = canvas.getContext('2d');        
    const pixels = base64ToArrayBuffer(pixelsbase64); // some mime64 decoder function
    const imageData = ctx.createImageData(xw, yw);
    ctx.putImageData(imageData, 0, 0);
}

Это явно не очень эффективно. Он создает несколько копий байтового массива:

In. NET:

  1. Оригинальный bytearray байтовый массив в. NET

В JavaScript:

Mime64-кодированная pixelsbase64 строка pixels байтовый массив imageData Объект ImageData
...