JavaScript,如何从斑点获得图像宽度和高度?

发布于 2025-02-05 20:41:22 字数 2279 浏览 4 评论 0 原文

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

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

    }
}
});

我想获取上载的原始图像的宽度和高度,以便我可以调整它。我不能从 imagefile 返回 不确定的,并且无法从 img 变量中获取它,因为它最初取决于我的CSS (在CSS中,&lt; img&gt; 标签位于&lt; div; gt; 标签中,而不是全屏幕,可以说是400像素)。因此,相应地,如果我上传5000x5000映像,那将不是原始大小(希望您得到的)。我的问题是,因为我的CSS调整了 div 和内部元素,所以我无法获得原始图像的正常宽度和高度,因此我可以调整它,然后用 canvas 然后将其转换为base64。

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

var blobURL = URL.createObjectURL(imageFile)

在这里,我访问我的原始映像( ImageFile ),为其创建Blob并获得Blob链接。但是我无法访问Blob Link图像的宽度和高度。有什么建议吗?

注意:我认为问题在于 img.onload 本身。就像在这一行中,我通过了 img

ctx.drawImage(img, 0, 0, shape[0], shape[1])

fyi。这就是我上传图像时的外观。这里大约是90x90像素。这会导致画布问题,因为img.onload采用这些尺寸(90x90),而不是原始尺寸(约为5000x5000)

调整大小的图像看起来像:

编辑:

如果有人好奇,我可以在这里粘贴我的已解决的代码版本,以便您可以对其进行调整。在下面发表评论。

So this is my code snippet (unnecessary code lines are removed):

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

    }
}
});

I want to get the uploaded original image's width and height so I can resize it. I can't do it from imageFile as it returns undefined and can't get it from the img variable as it originally depends on my css (in css the <img> tag is in a <div> tag which is not fullscreen, let's say it is 400 pixels). So correspondingly, if I upload 5000x5000 image it will not be the original-sized (hope you got it). My problem is that because my css resizes that div and elements inside, I can't get normal width and height of my original image, so I can resize it then draw with canvas and then convert it to base64.

I try to add this code to img.onload:

var blobURL = URL.createObjectURL(imageFile)

Here I access my original image (which is imageFile), create blob for it and get that blob link. But I can't access that blob link image's width and height. Any suggestions?

Note: I think the problem is in img.onload itself. As in this line I pass that img:

ctx.drawImage(img, 0, 0, shape[0], shape[1])

FYI. This is how it looks when I upload my image. It is about 90x90 pixels here. And that causes the problem with canvas, as img.onload takes those dimensions (90x90) and not the original dimensions which is about 5000x5000
enter image description here

The resized image looks like:
enter image description here

Edited:

If anyone is curious, I can paste my solved code version here so you can adjust to it. Leave a comment below.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无人问我粥可暖 2025-02-12 20:41:22

您可以使用图像构造函数

const img = new Image();
img.src = imageDataUrl;
img.onload = () => {
   // img.width
   // img.height
 };

You can use the Image constructor

const img = new Image();
img.src = imageDataUrl;
img.onload = () => {
   // img.width
   // img.height
 };
酒中人 2025-02-12 20:41:22

最好的是创建一个 imageBitmapmap 来自这个blob。

在某些实现中,这避免了在主线程上制作的图像并阻止您的页面的解码,无论如何,与 htmlimageelement 在每个实现中相比,这是一个轻得多的路径(避免网络请求,避免使用网络请求,创建DOM对象,大量内部检查等)。
如果您只想获取图像的大小,这还允许您从浏览器的内存中释放位图数据,这要归功于 .close() 方法,而HTMLIMLIMAGEELEMENT通常也会尝试缓存其位图数据被摧毁。
作为奖励,它甚至可以在网络工作人员中工作。

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

如果您需要定位较旧的浏览器,则可以使用我的这个矿山

该方法的唯一缺点是它仅适用于位图映像,您无法从SVG图像的斑点创建一个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);
}
<canvas></canvas>

The best is to create an ImageBitmap from this Blob.

In some implementations this avoids having the decoding of the image being made on the main thread and blocking your page, and is anyway a much lighter path than the HTMLImageElement one in every implementation (avoids a network request, the creation of a DOM object, a lot of internal checks etc.).
If you only want to get the size of the image, this also allows you to release the bitmap data from the browser's memory, thanks to the .close() method, while the HTMLImageElement will generally try to cache its bitmap data even after the original DOM element has been destroyed.
And as a bonus, it even works in 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);
}

If you need to target older browsers, you can use this polyfill of mine.

The only drawback of this method is that it works only for bitmap images, you can't create an ImageBitmap from a Blob of an SVG image, because this kind of image can have no intrinsic dimensions of its own.


And since you are gonna draw that image on a canvas, note that you can also obviously pass this ImageBitmap to drawImage() (before you close it), and that it also even allows you to do the resizing directly:

(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);
}
<canvas></canvas>

清音悠歌 2025-02-12 20:41:22

clientHeight clientwidth OffSetheight OffsetWidth height> height width width < /代码>将为您提供相对尺寸。要获取原始尺寸,您必须使用 .naturalheight .naturalAlalWidth

htmlimageelement.naturalwidth
HTMLIMAGEELEMENT界面的仅读取天然宽属性返回CSS像素中图像的固有(天然),密度校正的宽度。

这是图像绘制的宽度,没有限制其宽度;如果您既没有为图像指定宽度,也没有将图像放入限制或明确指定图像宽度的容器中href =“ https://developer.mozilla.org/en-us/docs/web/api/htmlimageelement/naturalwidth” rel =“ noreferrer”>在这里

href =“ https://developer.mozilla.org/en-us/docs/web/api/htmlemageelement/naturalalwidth” rel =“ noreferrer /code>和 .naturalheight as

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('displayImage');
        img.onload = function() {
          debugger;
          var shape = resizeImage(img) // resizing image for future canvas drawing, returns [width, height] (resized)
          // or just
          // var shape = [image.naturalWidth, image.naturalHeight]
          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])
          
          document.body.appendChild(canvas); // added
          // converting to base64 logic and the rest code
        }
        img.src = e.target.result;
      }
      reader.readAsDataURL(imageFile);
      
    }
  }
});
function resizeImage(image){
  return [image.naturalWidth, image.naturalHeight]
}
img{
  width: 100px;
  heigh: 100px;
}
<img id='displayImage'/>
<input type='file' multiple id='id_photo'/>


另外,如果仅添加了一个图像以获取SRC,则可以尝试 new Image()而不是跳过创建额外的DOM元素。

let imgInput = document.getElementById('id_photo');
imgInput.addEventListener('change', function (e) {
  if (e.target.files) {
    Array.from(e.target.files).forEach(file=>{
      const fileReader = new FileReader();
      fileReader.readAsDataURL(file);
      fileReader.onload = (fe) => {
        const image = new Image();
        image.src = fe.currentTarget.result;
        image.onload = function(ie){
          console.log('Width: ' + this.naturalHeight);
          console.log('Height: ' + this.naturalWidth);
        }
      }
    })
  }
});
<input type='file' multiple id='id_photo'/>

clientHeight, clientWidth, offsetHeight, offsetWidth, height, width would give you relative dimensions. To get original dimensions you must use .naturalHeight and .naturalWidth.

HTMLImageElement.naturalWidth
The HTMLImageElement interface's read-only naturalWidth property returns the intrinsic (natural), density-corrected width of the image in CSS pixels.

This is the width the image is if drawn with nothing constraining its width; if you neither specify a width for the image nor place the image inside a container that limits or expressly specifies the image width, this is the number of CSS pixels wide the image will be.

You can read more here

You snippet can be updated with .naturalWidth and .naturalHeight as

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('displayImage');
        img.onload = function() {
          debugger;
          var shape = resizeImage(img) // resizing image for future canvas drawing, returns [width, height] (resized)
          // or just
          // var shape = [image.naturalWidth, image.naturalHeight]
          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])
          
          document.body.appendChild(canvas); // added
          // converting to base64 logic and the rest code
        }
        img.src = e.target.result;
      }
      reader.readAsDataURL(imageFile);
      
    }
  }
});
function resizeImage(image){
  return [image.naturalWidth, image.naturalHeight]
}
img{
  width: 100px;
  heigh: 100px;
}
<img id='displayImage'/>
<input type='file' multiple id='id_photo'/>


Also if you added an image just to get src you can try new Image() instead to skip creating an extra DOM element.

let imgInput = document.getElementById('id_photo');
imgInput.addEventListener('change', function (e) {
  if (e.target.files) {
    Array.from(e.target.files).forEach(file=>{
      const fileReader = new FileReader();
      fileReader.readAsDataURL(file);
      fileReader.onload = (fe) => {
        const image = new Image();
        image.src = fe.currentTarget.result;
        image.onload = function(ie){
          console.log('Width: ' + this.naturalHeight);
          console.log('Height: ' + this.naturalWidth);
        }
      }
    })
  }
});
<input type='file' multiple id='id_photo'/>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文