是否可以在显示图像并将原始图像加载到 RAM 之前缩小(实际上调整大小)图像?

Is it possible to downscale (actually resize) an image before displaying it and loading the original into RAM?

我正在构建一个 Electron 应用程序 (Chrome + Node.js),其目标是显示指定文件夹中的所有图像。

这是一个应用程序,所以所有的图像都已经在磁盘上,不需要下载任何东西。

问题:

我需要它将所有图像显示为 64x64 缩略图,但由于它们是作为 <img> 元素加载的,因此原始图像被加载到 RAM 中,只有在那之后 CSS "resizes" 它们到 width: 64px; height: 64px,但事实并非如此,它仍将原始图像保存在 RAM 中,因此显示 300 张图像(1mb-20mb)需要约 3.5 GB 的 RAM。

问题:

所以,我想知道是否有任何更简单的方法来获取图像的 64x64 缩略图并在网页上显示它而不是原始图像?

是否有可能让浏览器在显示它们之前(即在将它们加载到 RAM 之前)缩小尺寸(实际上将图像大小调整为 64x64)?

尝试过:

我尝试使用 <canvas> 而不是 <img>,但它会使应用程序在滚动时滞后,因为它的计算量非常大(~0.1 毫秒/图像)。我想将其发送给网络工作者,但做不到。

// 我在那里使用 vue.js

// THIS TAG IS INSIDE A V-FOR LOOP SO A CANVAS TAG IS CREATED FOR EACH ITEM IN THE LIST
<canvas :id="'item-' + props.index"> 
  {{drawThumbnails(props.item.path, props.index)}} 
</canvas> 

drawThumbnails (path, canvasId) {
  console.time('draw time')
  var image = new Image(); 
  image.onload = function() {
    var canvas = document.getElementById(canvasId);
    canvas.width = 64;
    canvas.height = 64;
    canvas.getContext("2d").drawImage(image, 0, 0, 64, 64);
  }
  image.src = path
  console.timeEnd('draw time')
}

我认为我可以做到这一点的另一种方法是使用 jimp 将图像调整为 64x64 并将它们保存到磁盘。它很慢,但我可以使用网络工作者将这项工作发送到另一个核心

不加载原始图像的唯一方法是将调整大小的缩略图也保存到磁盘并加载它。

这取决于这些图像的来源。

如果它们是由您创建并与应用程序预先打包的,您可以自己调整大小并打包每个图像的两个版本(例如 myimage_500x500.pngmyimage_64x64.png)。

如果图像是由应用程序创建的,即应用程序是 运行 在用户的 PC 上,从某个来源获取图像数据并将其写入磁盘,那么它也可以创建缩略图并保存它以及。一个很好的实用程序是 sharp:

const sharp = require('sharp');
const fs = require('fs');

const imageBuffer = getImage() // Data from some source

fs.writeFile('image.png', imageBuffer, (err) => {
  if (err) return callback(err)

  sharp(originalImageBuffer)
    .resize(64, 64)
    .toFile('image_64x64.png', callback);
});

如果图像在用户的硬盘驱动器上但应用程序并未将其放置在那里(即您只是访问现有文件夹),那么您也需要执行上述调整大小操作,但由其他事件触发.例如。当图像首次显示或您定期检查新图像时。


还有一种方法既不需要在磁盘上存储缩略图,也不需要在显示时加载大图像。 如果你添加 express 应用程序或类似的东西,你可以让你的 <img> 标签从 express 处理的路线请求他们的图像,然后从磁盘加载图像并动态调整大小。

一旦请求完成,大图像将被垃圾收集,前端只显示小缩略图。