color_quant :: NeuQuant编译为WebAssembly输出零值

时间:2018-05-27 14:15:01

标签: rust webassembly

我正在尝试在浏览器中加载图像并使用NewQuant算法通过WebAssembly在Rust中量化我的图像缓冲区。但是,NewQuant输出包含零值,无论我尝试向它提供什么PNG。

我向WASM公开了两个Rust方法:

  1. alloc用于分配字节缓冲区
  2. read_img将读取和处理img缓冲区
  3. 我知道我得到零值因为我导入了一个名为log_nr的JavaScript方法来记录简单的u8数字。缓冲区似乎包含有效的像素值。

    extern crate color_quant;
    extern crate image;
    
    use color_quant::NeuQuant;
    use image::{DynamicImage, GenericImage, Pixel, Rgb};
    
    use std::collections::BTreeMap;
    use std::mem;
    use std::os::raw::c_void;
    
    static NQ_SAMPLE_FACTION: i32 = 10;
    static NQ_PALETTE_SIZE: usize = 256;
    
    extern "C" {
        fn log(s: &str, len: usize);
        fn log_nr(nr: u8);
    }
    
    fn get_pixels(img: DynamicImage) -> Vec<u8> {
        let mut pixels = Vec::new();
    
        for (_, _, px) in img.pixels() {
            let rgba = px.to_rgba();
    
            for channel in px.channels() {
                pixels.push(*channel);
            }
        }
    
        pixels
    }
    
    #[no_mangle]
    pub extern "C" fn alloc(size: usize) -> *mut c_void {
        let mut buf = Vec::with_capacity(size);
        let ptr = buf.as_mut_ptr();
        mem::forget(buf);
    
        return ptr as *mut c_void;
    }
    
    fn process_img(img: DynamicImage) {
        let pixels: Vec<u8> = get_pixels(img);
        let quantized = NeuQuant::new(NQ_SAMPLE_FACTION, NQ_PALETTE_SIZE, &pixels);
    
        let q = quantized.color_map_rgb();
    
        for c in &q {
            unsafe {
                log_nr(*c);
            }
        }
    }
    
    #[no_mangle]
    pub extern "C" fn read_img(buff_ptr: *mut u8, buff_len: usize) {
        let mut img: Vec<u8> = unsafe { Vec::from_raw_parts(buff_ptr, buff_len, buff_len) };
    
        return match image::load_from_memory(&img) {
            Ok(img) => {
                process_img(img);
            }
            Err(err) => {
                let err_msg: String = err.to_string().to_owned();
                let mut ns: String = "[load_from_memory] ".to_owned();
    
                ns.push_str(&err_msg);
    
                unsafe {
                    log(&ns, ns.len());
                }
            }
        };
    }
    
    fn main() {
        println!("Hello from rust 2");
    }
    

    JavaScript代码如下:

    run('sample.png');
    
    function run(img) {
        return compile().then(m => {
            return loadImgIntoMem(img, m.instance.exports.memory, m.instance.exports.alloc).then(r => {
                return m.instance.exports.read_img(r.imgPtr, r.len);
            });
        })
    }
    
    function compile(wasmFile = 'distil_wasm.gc.wasm') {
        return fetch(wasmFile)
            .then(r => r.arrayBuffer())
            .then(r => {
                let module = new WebAssembly.Module(r);
                let importObject = {}
                for (let imp of WebAssembly.Module.imports(module)) {
                    if (typeof importObject[imp.module] === "undefined")
                        importObject[imp.module] = {};
                    switch (imp.kind) {
                    case "function": importObject[imp.module][imp.name] = () => {}; break;
                    case "table": importObject[imp.module][imp.name] = new WebAssembly.Table({ initial: 256, maximum: 256, element: "anyfunc" }); break;
                    case "memory": importObject[imp.module][imp.name] = new WebAssembly.Memory({ initial: 256 }); break;
                    case "global": importObject[imp.module][imp.name] = 0; break;
                    }
                }
    
                importObject.env = Object.assign({}, importObject.env, {
                    log: (ptr, len) => console.log(ptrToStr(ptr, len)),
                    log_nr: (nr) => console.log(nr),
                });
    
                return WebAssembly.instantiate(r, importObject);
            });
    }
    
    function loadImgIntoMemEmscripten(img) {
        return new Promise(resolve => {
            fetch(img)
                .then(r => r.arrayBuffer())
                .then(buff => {
                    const imgPtr = Module._malloc(buff.byteLength);
                    const imgHeap = new Uint8Array(Module.HEAPU8.buffer, imgPtr, buff.byteLength);
    
                    imgHeap.set(new Uint8Array(buff));
    
                    resolve({ imgPtr });
                });
        });
    }
    

0 个答案:

没有答案