2017-09-26 104 views
2

這裏是我的代碼:如何獲得網絡工作者的圖像寬度和高度?

// 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一個網絡工作者的內部訪問。具體的錯誤是:

Uncaught ReferenceError: Image is not defined at 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,並fileFile。我將整件事傳遞給網絡工作者,以便我可以在那裏完成所有的處理。

回答

3

我覺得可能是一個簡單的解決方案:

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

Awww yes! 'createImageBitmap'看起來像我正在尋找的。甚至可能幫助調整大小,這是我的下一個任務。請儘快試用,謝謝! – mpen

+0

對不起,複製粘貼真正快速發佈答案,將編輯,謝謝! – PiniH

1

我設法得到了大多數JPEG的寬度和高度,遵循this spec

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

這段代碼雖然很怪,但卻令人驚訝地發揮作用。我仍在尋找更強大的解決方案。

+1

'createImageBitmap'絕對是更容易,並且將支持瀏覽器支持的所有支持的圖像類型,但是如果您需要支持較舊的瀏覽器,我也會選擇wri te [這裏的東西](https://stackoverflow.com/questions/42540903/sort-by-image-resolution-in-gallery/42649964#42649964),您可以從中提取其他格式的代碼。 – Kaiido

相關問題