簡體   English   中英

如何在網絡工作者中獲取圖像的寬度和高度?

[英]How to get image width and height in a 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線程中工作正常,但顯然我無法在網絡工作者中訪問Image 具體錯誤是:

未捕獲的ReferenceError:未在FileReader.reader.onload中定義圖像(process-image.js:12)

有沒有其他方法可以獲取圖像的寬度和高度?

我希望支持盡可能多的文件類型,但是如果有某種可以執行此操作並且可以在網絡工作者中運行的庫,那么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 我將整個事情傳遞給網絡工作者,以便在那里進行所有處理。

我認為可能有一個更簡單的解決方案:

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})
});

通過遵循此規范,我設法獲得了大多數JPEG的寬度和高度。

self.addEventListener('message', ev => {
    const {id, file} = ev.data;

    const reader = new FileReader();
    reader.onload = ev => {
        const view = new DataView(reader.result);

        let offset = 0;
        let header = view.getUint16(offset, false);

        if(header !== 0xFFD8) {
            throw new Error(`Not a JPEG`);
        }
        offset += 2;

        for(; ;) {

            header = view.getUint16(offset, false);
            offset += 2;
            let length = view.getUint16(offset, false);

            if(header === 0xFFC0) break;
            offset += length;
        }

        const height = view.getUint16(offset + 3);
        const width = view.getUint16(offset + 5);

        const fit = makeFit({width, height});

        self.postMessage({
            id,
            file: {
                src: URL.createObjectURL(file),
                width: fit.width,
                height: fit.height,
            }
        })
    };

    reader.readAsArrayBuffer(file);
});

這段代碼簡直是千篇一律,但令人驚訝的是它可以工作。 我仍在尋找更強大的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM