Skip to content
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

The global thread pool has not been initialized.: ThreadPoolBuildError { kind: IOError(Error { kind: Unsupported, message: "operation not supported on this platform" }) } #1496

Open
insinfo opened this issue Jun 21, 2021 · 6 comments

Comments

@insinfo
Copy link

insinfo commented Jun 21, 2021

I'm trying to decode a JPEG image from a Vec u8, this Vec u8 comes from a javascript Uint8Array, as I'm trying to process an image in rust through WebAssembly, but I'm getting the following error:

panicked at 'The global thread pool has not been initialized.: ThreadPoolBuildError { kind: IOError(Error { kind: Unsupported, message: "operation not supported on this platform" }) }', C:\rust\cargo\registry\src\github.com-1ecc6299db9ec823\rayon-core-1.9.1\src\registry.rs:170:10

Stack:

Error
    at http://localhost:8000/photon_rs.js:4062:27
    at logError (http://localhost:8000/photon_rs.js:271:22)
    at imports.wbg.__wbg_new_59cb74e423758ede (http://localhost:8000/photon_rs.js:4061:20)
    at console_error_panic_hook::Error::new::hca09d9bc57ad3dd0 (http://localhost:8000/photon_rs_bg.wasm:wasm-function[16077]:0x65f468)
    at console_error_panic_hook::hook_impl::ha8bcc4998f07b33e (http://localhost:8000/photon_rs_bg.wasm:wasm-function[2698]:0x479ee0)
    at console_error_panic_hook::hook::hffcf27262a2014ba (http://localhost:8000/photon_rs_bg.wasm:wasm-function[17303]:0x670899)
    at core::ops::function::Fn::call::ha6f793f965b7e004 (http://localhost:8000/photon_rs_bg.wasm:wasm-function[15124]:0x6504dd)
    at std::panicking::rust_panic_with_hook::hbdbceb5cd158bf19 (http://localhost:8000/photon_rs_bg.wasm:wasm-function[5604]:0x546d8b)
    at std::panicking::begin_panic_handler::{{closure}}::h9995bb2f0de4bb38 (http://localhost:8000/photon_rs_bg.wasm:wasm-function[7694]:0x5a027c)
    at std::sys_common::backtrace::__rust_end_short_backtrace::hc7608161a467c002 (http://localhost:8000/photon_rs_bg.wasm:wasm-function[18481]:0x67f755)
use base64::{decode, encode};
use image::DynamicImage::ImageRgba8;
use image::{GenericImage, GenericImageView};

use image::io::Reader  as ImageReader; 
use image::ImageFormat;
use std::io::Cursor;

use js_sys::ArrayBuffer;
use js_sys::Uint8Array;
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use wasm_bindgen::Clamped;
use web_sys::{Blob, CanvasRenderingContext2d, HtmlCanvasElement, ImageData};

/// open image from a Uint8Array;
#[wasm_bindgen]
pub fn open_image_from_array_buffer(uint8array: Uint8Array) {
 
    console_log!("open_image_from_array_buffer {:?}", uint8array); //ok
 
    let raw_data: Vec<u8> = uint8array.to_vec(); //ok

    console_log!("open_image_from_array_buffer {:?}", raw_data); //ok  
    
    let image = ImageReader::with_format(Cursor::new(raw_data), ImageFormat::Jpeg).decode(); //error

    console_log!("open_image_from_array_buffer {:?}", image);  
   
}

https://github.com/insinfo/photon-test

image

@HeroicKatora
Copy link
Member

There is not multithreading in js/wasm but you can try disabling the rayon feature:

[dependencies.image]
version = "0.23.14"
default-features = "false"
features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld"]

@insinfo
Copy link
Author

insinfo commented Jun 21, 2021

@HeroicKatora

my toml file already had this setting, what solved the problem was removing these lines:

#[features]
#default = ["console_error_panic_hook", "rayon"]
#rayon = ["image/jpeg_rayon", "imageproc/rayon"]

any idea why this happens?

[package]
authors = ["Silvia O'Dwyer <silviaodwyerdev@gmail.com>"]
categories = ["wasm", "multimedia"]
description = "High-performance image processing library for native use and the web"
license = "Apache-2.0"
name = "photon-rs"
readme = "./README.md"
repository = "https://github.com/silvia-odwyer/photon"
version = "0.3.1"
edition = "2018"
exclude = [
    "pkg/*",
    "examples/input_images/*"
]
homepage = "https://silvia-odwyer.github.io/photon/"

[lib]
crate-type = ["cdylib", "rlib"]


[dependencies]
#image = { version = "0.23.12", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld"] }
palette="0.5.0"
rand="0.7.2"
num="0.3.1"
imageproc = { version = "0.22.0", default-features = false }
rusttype="0.9.2"
base64="0.13.0"
time="0.2.23"
wasm-bindgen = "0.2" #0.2.25
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
js-sys = "0.3.51"    # 0.3.45
node-sys = "0.4.2"
perlin2d = "0.2.6"


# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
#console_error_panic_hook = { version = "0.1.6", optional = true }
console_error_panic_hook = "0.1.6"

# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
wee_alloc = { version = "0.4.2", optional = true }

[dependencies.image]
version = "0.23.14"
default-features = false
features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld"]

[dev-dependencies]
time="0.2.1"
criterion = "0.3"

[[bench]]
name = "photon_benchmark"
harness = false

[package.metadata.wasm-pack.profile.release]
wasm-opt = ["-O3", "--enable-mutable-globals"]

[dependencies.web-sys]
version = "0.3"
features = [
  "Document",
  "Element",
 # "ArrayBuffer",
  "Blob",
  "HtmlElement",
  "Node",
  "Window",
  "CanvasRenderingContext2d",
  "ImageData",
  "HtmlCanvasElement",
  "HtmlImageElement",
  "console",
  'CssStyleDeclaration',
  'EventTarget',
]

#[features]
#default = ["console_error_panic_hook", "rayon"]
#rayon = ["image/jpeg_rayon", "imageproc/rayon"]

@HeroicKatora
Copy link
Member

HeroicKatora commented Jun 21, 2021

The default = [..] line tells cargo that the local crate should have some features on by default, and the rayon feature depends on image/jpeg_rayon which will also activate and depend on rayon.

@insinfo
Copy link
Author

insinfo commented Jun 22, 2021

@HeroicKatora
I noticed that the execution of this code is very slow especially the JPEG decoding. The execution of this code with this image https://i.imgur.com/LYVUrUf.jpg is taking approximately 4 seconds to complete. Is there any way to make this faster.

<!DOCTYPE html>
<html>
<head>
    <title>teste</title>
    <script id="script-photon" src="photon_rs.js"></script>
    <script>
        var downloadBlob, downloadURL;
        downloadBlob = function (data, fileName, mimeType) {
            var blob, url;
            blob = new Blob([data], {
                type: mimeType
            });
            url = window.URL.createObjectURL(blob);
            downloadURL(url, fileName);
            setTimeout(function () {
                return window.URL.revokeObjectURL(url);
            }, 1000);
        };
        downloadURL = function (data, fileName) {
            var a;
            a = document.createElement('a');
            a.href = data;
            a.download = fileName;
            document.body.appendChild(a);
            a.style = 'display: none';
            a.click();
            a.remove();
        };

        window.photon;
        async function initPhoton() {
            var scri = document.querySelector('#script-photon');
            var url = scri.src.replace(/\.js$/, '_bg.wasm');
            window.photon = await wasm_bindgen(url);
                let t1 = performance.now();                      
                let buf = await fetch("https://i.imgur.com/LYVUrUf.jpg", { referrer: "" }).then(r => r.arrayBuffer()); // huge jpg
                 console.log(performance.now() - t1);
                let array = photon.resize_image_from_uint8array(new Uint8Array(buf), 1024, 1024, 80);
                downloadBlob(array, 'some-file.jpg', 'image/jpeg');
                console.log(performance.now() - t1);
        }

        initPhoton();
             
        async function readFileAsArrayBuffer(file) {
            let result_base64 = await new Promise((resolve) => {
                let fileReader = new FileReader();
                fileReader.onload = (e) => resolve(fileReader.result);
                fileReader.readAsArrayBuffer(file);
            });
            return result_base64;
        }       
    </script>
</head>
<body>
    <h1>teste</h1>     
</body>
</html>
/// open image from a js Uint8Array and resize 
#[wasm_bindgen]
pub fn resize_image_from_uint8array(
    bytes: Vec<u8>,
    nwidth: u32,
    nheight: u32,
    quality: u8,
) -> Vec<u8> {
    console_error_panic_hook::set_once();   
    let img = image::load_from_memory(&bytes).unwrap();   
    let scaled = img.resize(nwidth, nheight, image::imageops::FilterType::Triangle);  
    let mut buf = Vec::new();

    scaled
        .write_to(&mut buf, image::ImageOutputFormat::Jpeg(quality))
        .unwrap();
   
    return buf;
}

https://github.com/insinfo/photon-lib

@HeroicKatora
Copy link
Member

HeroicKatora commented Jun 22, 2021

Sure, wasm isn't quite as fast as native code and most of the jpeg performance comes from vectorization which you don't have at all in wasm (for now). The most efficient way would not be using wasm to decode a jpeg but instead asking the browser to natively do it for you. Use an html canvas, getContext('2d').drawImage(…) and load the image via a <img> element. If you're concerned about runtime foremost you really should avoid using CPU image processing and certainly not in a wasm sandbox.

@RustyNixieTube
Copy link
Contributor

@HeroicKatora i think that there should be explanations about available features in README.md.
(I got the same panic, the first thing i have done is searching in README.md if there is an option to disable rayon)

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

No branches or pull requests

3 participants