You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

图片尺寸异常求助:21600×10800经Canvas读取变10800×5400

问题原因与解决方法

核心原因

你遇到的问题本质是浏览器加载图片时,会根据图片的DPI设置或设备像素比自动调整Image对象的显示尺寸,导致THREE.ImageLoader加载后的image.width和image.height已经是原始文件像素的一半,后续Canvas操作自然沿用了这个缩小后的尺寸。

具体触发场景:

  • 图片DPI设置为192(是浏览器默认基准96DPI的2倍),浏览器为保证图片在屏幕上的实际显示大小符合DPI定义,会将Image元素的显示尺寸缩放为原始像素的1/2。
  • 高DPI屏幕下,浏览器自动适配设备像素比,对图片显示尺寸进行缩放,导致Image对象的宽高不等于文件原始像素。

解决方法

1. 调整图片DPI为标准值

用图像编辑工具(如Photoshop、GIMP)打开图片,导出时将DPI设置为96(浏览器默认基准),这样浏览器会直接以文件的原始像素作为Image对象的width/height,无需额外处理。

2. 读取图片真实像素尺寸

通过解析图片的EXIF信息获取原始像素尺寸,替代Image对象的width/height。示例代码(针对JPG的简易实现):

async function getImageRealSize(url) {
  const response = await fetch(url);
  const arrayBuffer = await response.arrayBuffer();
  const dataView = new DataView(arrayBuffer);
  
  // 查找JPG的SOF0标记,提取原始宽高
  let offset = 2;
  while (offset < dataView.byteLength) {
    const marker = dataView.getUint16(offset);
    if (marker === 0xFFC0) { // SOF0标记
      const height = dataView.getUint16(offset + 5);
      const width = dataView.getUint16(offset + 7);
      return { width, height };
    }
    offset += 2 + dataView.getUint16(offset + 2);
  }
  return null;
}

// 使用示例
const realSize = await getImageRealSize('./resources/image0.jpg');
const image = await new THREE.ImageLoader().loadAsync('./resources/image0.jpg');    
// 基于真实尺寸创建Canvas并绘制
let canvas = new OffscreenCanvas(realSize.width, realSize.height); 
let context = canvas.getContext('2d'); 
context.drawImage(image, 0, 0, realSize.width, realSize.height);           
const data = context.getImageData(0, 0, realSize.width, realSize.height);      

3. 手动修正缩放比例(仅适用于已知固定缩放场景)

如果确定图片的缩放比例固定为2(如本例),可直接将Image对象的宽高乘以2恢复原始尺寸:

const image = await new THREE.ImageLoader().loadAsync('./resources/image0.jpg');    
const realWidth = image.width * 2;
const realHeight = image.height * 2;

const map = {
  data: (() => {
    let canvas = new OffscreenCanvas(realWidth, realHeight); 
    let context = canvas.getContext('2d'); 
    context.drawImage(image, 0, 0, realWidth, realHeight);           
    return context.getImageData(0, 0, realWidth, realHeight);
  })(),
  width: realWidth,
  height: realHeight
};

内容的提问来源于stack exchange,提问作者Spiri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 19:25:28