javascript - 如何在网络 worker 中获取图像的宽度和高度?

标签 javascript web-worker

这是我的代码:

// process-image.js (web-worker)
self.addEventListener('message', ev => {
    const {id,file} = ev.data;

    const reader = new FileReader();
    reader.onload = ev => {
        const imageFile = new Image(); // <-- error is here
        imageFile.src = ev.target.result;

        imageFile.onload = () => {
            const fit = makeFit(imageFile);

            self.postMessage({
                id,
                file: {
                    src: ev.target.result,
                    width: fit.width,
                    height: fit.height,
                }
            })
        }
    };

    reader.readAsDataURL(file);
});

这在主 UI 线程中运行良好,但显然我无法访问网络 worker 内部的 Image。具体报错是:

Uncaught ReferenceError: Image is not defined at FileReader.reader.onload (process-image.js:12)

是否有其他方法获取图像的宽度和高度?

我想支持尽可能多的文件类型,但如果有某种类型的库可以做到这一点并且将在 web-worker 中运行,那么现在只需要 JPG 就足够了。


这是来自 UI 线程的相关部分:

// some-react-component.js
    componentDidMount() {
        this.worker = new ImageWorker();
        this.worker.addEventListener('message', ev => {
            const {id, file} = ev.data;

            this.setState(({files}) => {
                files = files.update(id, img => ({
                    ...img,
                    ...file,
                }))

                const withWidths = files.filter(f => f.width);
                const avgImgWidth = withWidths.reduce((acc, img) => acc + img.width, 0) / withWidths.size;

                return {files, avgImgWidth};
            });
        });
    }


    onDrop = ev => {
        ev.preventDefault();


        Array.prototype.forEach.call(ev.dataTransfer.files, file => {

            const id = shortid();
            this.worker.postMessage({id, file});

            const img = {
                id,
                width: null,
                height: null,
                src: null,
                name: file.name,
            }
            this.setState(({files}) => ({files: files.set(id, img)}));
        });
    }

这里唯一值得注意的是 id 只是一个随机的 UUID,而 file 是一个 File .我将整个事情传递给网络 worker ,以便我可以在那里进行所有处理。

最佳答案

我认为可能有一个更简单的解决方案:

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap

我根本不使用 FileReader 就设法获得了大小:

http://jsfiddle.net/hL1Ljkmv/2/

var response = `self.addEventListener('message', async ev => {
    const {id,file} = ev.data;
    console.log('received data');
    let image = await self.createImageBitmap(file);
    console.log(image);
});`;

const blob = new Blob([response], {type: 'application/javascript'});
const worker = new Worker(URL.createObjectURL(blob));

const input = document.querySelector('#file-input');
input.addEventListener('change', (e) => {
  worker.postMessage({file: input.files[0], id: 1})
});

关于javascript - 如何在网络 worker 中获取图像的宽度和高度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46419315/

相关文章:

javascript - Webworker 数据传输允许的格式

html - Web Worker 的局限性

javascript - 使用 CSP 在 Web Worker 中启用 'new Function'

javascript - 在 Angular 1.x 中调用方法/触发子组件上的操作

javascript - 如何从 Sinatra 中的特定页面重定向网页?

javascript - 如何限制 Dropbox Chooser 的文件类型

javascript - 避免 React 因之前的 props 更新而 overdraw

python - Gunicorn 不重新加载 worker

javascript - 防止反斜杠被 javascript 解析为字符串

javascript - 是否可以终止正在运行的网络 worker ?