Javascript,如何从斑点中获取图像宽度和高度?

Mam*_*yev 5 javascript css jquery blob canvas

这是我的代码片段(删除了不必要的代码行):

let imgInput = document.getElementById('id_photo');
imgInput.addEventListener('change', function (e) {
    if (e.target.files) {
        for (let i = 0; i < e.target.files.length; i++) {

        let imageFile = e.target.files[i];
        var reader = new FileReader();

        reader.onload = function (e) {
            var img = document.getElementById(nevermindID);
            img.onload = function() {
                var shape = resizeImage(img) // resizing image for future canvas drawing, returns [width, height] (resized)
                
                var canvas = document.createElement("canvas")
                canvas.width = shape[0]
                canvas.height = shape[1]
                var ctx = canvas.getContext("2d")
                ctx.drawImage(img, 0, 0, shape[0], shape[1])
                // converting to base64 logic and the rest code
            }
            img.src = e.target.result;
        }
        reader.readAsDataURL(imageFile);

    }
}
});
Run Code Online (Sandbox Code Playgroud)

我想获取上传的原始图像的宽度和高度,以便我可以调整它的大小。我无法从imageFile执行此操作,因为它返回未定义,并且无法从img变量获取它,因为它最初取决于我的 css (在 css 中,标签<img>位于<div>非全屏标签中,假设它是 400 像素) 。因此,相应地,如果我上传 5000x5000 的图像,它将不是原始尺寸(希望您明白)。我的问题是,因为我的 css 调整了div和内部元素的大小,所以我无法获得原始图像的正常宽度和高度,所以我可以调整它的大小,然后用画布绘制,然后将其转换为 base64。

我尝试将此代码添加到img.onload

var blobURL = URL.createObjectURL(imageFile)
Run Code Online (Sandbox Code Playgroud)

在这里,我访问原始图像(即imageFile),为其创建 blob 并获取该 blob 链接。但我无法访问该 blob 链接图像的宽度和高度。有什么建议么?

注意:我认为问题出在img.onload本身。正如在这一行中我传递该img

ctx.drawImage(img, 0, 0, shape[0], shape[1])
Run Code Online (Sandbox Code Playgroud)

供参考。这就是我上传图像时的样子。这里大约是 90x90 像素。这会导致画布出现问题,因为 img.onload 采用这些尺寸 (90x90),而不是原始尺寸(大约 5000x5000) 在此输入图像描述

调整大小后的图像如下所示: 在此输入图像描述

编辑:

如果有人好奇,我可以将我解决的代码版本粘贴到此处,以便您进行调整。请在下面发表评论。

小智 8

您可以使用图像构造函数

const img = new Image();
img.src = imageDataUrl;
img.onload = () => {
   // img.width
   // img.height
 };
Run Code Online (Sandbox Code Playgroud)


Kai*_*ido 6

最好的方法是从此 Blob创建ImageBitmap 。

在某些实现中,这避免了在主线程上对图像进行解码并阻塞您的页面,并且无论如何都是比HTMLImageElement每个实现中的路径轻得多的路径(避免网络请求、创建 DOM 对象等)内部检查等)。
如果您只想获取图像的大小,这还允许您从浏览器内存中释放位图数据,这要归功于该.close()方法,而 HTMLImageElement 通常会尝试缓存其位图数据,即使原始 DOM 元素已被释放被毁了。
作为奖励,它甚至可以在 Web Workers 中使用。

(async () => {
  const imgBlob = await getImgBlob();
  const bmp = await createImageBitmap(imgBlob);
  const { width, height } = bmp;
  bmp.close(); // free memory
  console.log(width, height);
})();


// simple helper to get the Blob of an image
async function getImgBlob() {
  const resp = await fetch("https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png");
  return resp.ok ? resp.blob() : Promise.reject(resp.status);
}
Run Code Online (Sandbox Code Playgroud)

如果您需要针对较旧的浏览器,您可以使用我的这个polyfill

此方法的唯一缺点是它仅适用于位图图像,您无法从 SVG 图像的 Blob 创建 ImageBitmap,因为这种图像没有自己的内在尺寸。


由于您要在画布上绘制该图像,请注意,您显然也可以将此 ImageBitmap 传递给drawImage()(在关闭它之前),并且它甚至还允许您直接调整大小:

(async () => {
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  const imgBlob = await getImgBlob();
  const originalBmp = await createImageBitmap(imgBlob);
  const { width, height } = originalBmp;
  // we create the resized from the ImageBitmap for even faster processing
  // but we could obviously reuse the Blob here too
  const resizedBmp  = await createImageBitmap(originalBmp, { resizeWidth: 90, resizeHeight: 90 });
  originalBmp.close();
  canvas.width  = width;
  canvas.height = height;
  ctx.drawImage(resizedBmp, 0, 0, width, height);
  resizedBmp.close();
})().catch(console.error);

// simple helper to get the Blob of an image
async function getImgBlob() {
  const resp = await fetch("https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png");
  return resp.ok ? resp.blob() : Promise.reject(resp.status);
}
Run Code Online (Sandbox Code Playgroud)
<canvas></canvas>
Run Code Online (Sandbox Code Playgroud)