通过HTML5文件阅读器在本地读取大图像缩略图 [英] Reading large images as thumbnails locally via HTML5 filereader
问题描述
我试图按照这里所述的缩略图的形式加载本地图片。我的代码如下。
这适用于小图片。但是,当您尝试加载较大的图像时(例如4mb),会有很大的滞后。有什么办法可以优化吗?
谢谢
Html
< input type =fileid =filesname =files []multiple />
< output id =list>< / output>
Javascript
<脚本>
函数handleFileSelect(evt){
var files = evt.target.files; // FileList对象
//循环FileList并以缩略图形式呈现图像文件。
for(var i = 0,f; f = files [i]; i ++){
//仅处理图像文件。
if(!f.type.match('image。*')){
continue;
}
var reader = new FileReader();
//关闭捕获文件信息。
reader.onload =(function(theFile){
return function(e){
// Render thumbnail。
var span = document.createElement('span');
span.innerHTML = ['< img class =thumbsrc =',e.target.result,
'title =',escape(theFile.name),'/> gt ;']。join('');
document.getElementById('list')。insertBefore(span,null);
};
})(f);
//将图像文件读入数据URL。
reader.readAsDataURL(f);
$ b $ document.getElementById('files')。addEventListener('change',handleFileSelect,false);
< / script>
主UI线程涉及在巨大的斑点中操纵非流数据。滞后不是来自读取数据,而是解码并在浏览器UI中显示图像,因为这涉及在CPU和GPU内存中推动大像素阵列的同步UI操作。这是因为< img>
在实际图像数据大小(宽度*高度)的块中分配和移动内存,这对于大图像是非常大的量,将它推到GPU上以便在屏幕上显示它(导致延迟几毫秒)。
您可以通过将图像缩小为可显示来优化您的用例大小,而阅读它
-
使用一个纯的Javascript JPEG解码器,其中主事件循环以文件块形式读取文件并将块文件粘贴到WebWorker背景线程解码。一个解码器库的例子 https://github.com/notmasteryet/jpgjs/blob/master /jpg.js
-
分配WebWorker发布的
< canvas>
元素逐步支持所得像素。此画布元素不需要与实际图像大小相匹配(请参见下文)。 您还可以在纯JavaScript中阅读WebWorker时缩小图像 http://www.grantgalitz.org/image_resize/ - 减少将像素推送到GPU的需求因为您无法将显示器上的大图像作为1:1像素映射放在第一位 -
WebWorker和主线程可以使用数据推送免拷版转让对象 https:// developer.mozilla.org/en-US/docs/DOM/Using_web_workers#Passing_data_by_transferring_.C2.A0ownership_%28transferable_objects%29
然而,尽管这里描述的解决方案接近完美,但要实现这一点,需要拥有先进的Javasc技巧和解决方案不会与传统兼容(阅读:微软)。
I am trying to load local images as thumbnails as explained here. My code is below.
This works fine for small images. However, when you try load larger images (e.g. 4mb) there is a huge lag. Is there any way to optimize this?
Thanks
Html
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
Javascript
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
There is always a lag when you run something in the main UI thread which involves manipulating non-streaming data in huge blobs. The lag does not come from reading he data, but decoding and displaying the image in the browser UI as this involves synchronous UI operations pushing the large pixel array around in CPU and GPU memory. This is because <img>
allocates and moves around memory in the blocks of actual image data size (width * height) which is very large amount for big images and unnecessary detailed to push it up to GPU for just showing it on the screen (causes the lag of several milliseconds).
You can most likely optimize your use case by shrinking the image to displayable size while reading it
Using a pure Javascript JPEG decoder where main event loop reads the file in chunks and posts chunks to WebWorker background thread for decoding. One example decoder library https://github.com/notmasteryet/jpgjs/blob/master/jpg.js
Allocate a
<canvas>
element where the WebWorker posts backs the resulting pixels progressively. This canvas element does not need to match the actual image size (see below)Also you can scale down the images in the WebWorker while reading them in pure Javascript http://www.grantgalitz.org/image_resize/ - lessening the need to push the pixels to GPU as you are not going to fit the big image on the monitor as 1:1 pixel mapping in the first place
WebWorker and main thread can push data around using copy-free Transferable objects https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers#Passing_data_by_transferring_.C2.A0ownership_%28transferable_objects%29
However, though the solution described here is near perfect, to implement this one needs to possess advanced Javascript skills and the solution is not going to be legacy compatible (read: Microsoft).
这篇关于通过HTML5文件阅读器在本地读取大图像缩略图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!