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

如何在Deno中获取Base64图片的宽高?

在Deno边缘函数中从Base64提取图片宽高(无依赖方案)

问题背景

需要在Deno边缘函数中实现从Base64编码的图片里读取宽高的功能,Deno不支持浏览器的new Image()方法,且要尽可能减少依赖。之前尝试的两个方案都有问题:

  • skia_canvas:边缘环境不允许其所需的写入权限
  • ImageScript:不清楚对应的Deno导入地址

无依赖原生实现方案

可以直接解析Base64对应的二进制数据,读取图片文件头里的宽高信息,无需任何第三方依赖。以下是针对常见PNG、JPG格式的解析代码:

步骤1:Base64转Uint8Array

先把Base64字符串转换成二进制数组:

function base64ToUint8Array(base64: string): Uint8Array {
  const binaryString = atob(base64.replace(/^data:image\/(png|jpeg|jpg);base64,/, ''));
  const len = binaryString.length;
  const bytes = new Uint8Array(len);
  for (let i = 0; i < len; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  return bytes;
}

步骤2:解析PNG宽高

PNG的宽高存储在文件头后的IHDR块中,是4字节大端整数:

function getPngDimensions(bytes: Uint8Array): { width: number, height: number } | null {
  // 验证PNG签名(前8字节)
  const pngSignature = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
  if (!bytes.slice(0, 8).every((b, i) => b === pngSignature[i])) {
    return null;
  }
  // IHDR块从第16字节开始,宽高各占4字节(大端)
  const width = (bytes[16] << 24) | (bytes[17] << 16) | (bytes[18] << 8) | bytes[19];
  const height = (bytes[20] << 24) | (bytes[21] << 16) | (bytes[22] << 8) | bytes[23];
  return { width, height };
}

步骤3:解析JPG宽高

JPG采用分段结构,宽高存储在SOF0(0xC0)或SOF2(0xC2)段中:

function getJpgDimensions(bytes: Uint8Array): { width: number, height: number } | null {
  let i = 0;
  // 验证JPG签名(前2字节)
  if (bytes[i] !== 0xFF || bytes[i+1] !== 0xD8) {
    return null;
  }
  i += 2;
  // 遍历所有段
  while (i < bytes.length) {
    if (bytes[i] !== 0xFF) {
      return null; // 无效的JPG结构
    }
    const marker = bytes[i+1];
    // 跳过SOI(0xD8)和EOI(0xD9)以外的段
    if (marker === 0xC0 || marker === 0xC2) { // SOF0或SOF2段包含宽高
      // 段长度占2字节,跳过长度和其他字段(共5字节)
      i += 5;
      // 高度是2字节大端
      const height = (bytes[i] << 8) | bytes[i+1];
      // 宽度是2字节大端
      const width = (bytes[i+2] << 8) | bytes[i+3];
      return { width, height };
    } else {
      // 计算当前段的长度,跳过整个段
      const segmentLength = (bytes[i+2] << 8) | bytes[i+3];
      i += 2 + segmentLength;
    }
  }
  return null;
}

整合函数

把上面的函数整合,自动判断图片格式并返回宽高:

function getImageDimensionsFromBase64(base64: string): { width: number, height: number } | null {
  const bytes = base64ToUint8Array(base64);
  // 先尝试PNG解析
  const pngDim = getPngDimensions(bytes);
  if (pngDim) return pngDim;
  // 再尝试JPG解析
  const jpgDim = getJpgDimensions(bytes);
  if (jpgDim) return jpgDim;
  // 不支持的格式
  return null;
}

可选:使用ImageScript(如果环境允许)

ImageScript的Deno导入地址为https://deno.land/x/imagescript@1.2.15/mod.ts,示例代码如下:

import { Image } from "https://deno.land/x/imagescript@1.2.15/mod.ts";

async function getDimensionsWithImageScript(base64: string) {
  const binary = atob(base64.replace(/^data:image\/(png|jpeg|jpg);base64,/, ''));
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
  const image = await Image.decode(bytes);
  return { width: image.width, height: image.height };
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 23:06:04