图片尺寸调整

在浏览器里把一张图整体缩放到指定像素:先读原始尺寸,改宽度或高度,按原比例走 canvas 重采样,最后导出 PNG、JPEG 或 WebP,整个过程不经过任何服务器。

原始尺寸未选择图片
目标尺寸1920×1080
目标像素2,073,600
RGBA 缓冲7.91 MiB

导出后这里会显示缩放结果预览;未选择图片前不会画任何东西。

提示:宽度和高度的输入框里按 Enter 可直接重算目标尺寸;图片只在本地解码,关闭标签页后不会留任何副本。

使用方法

  1. 点「选择本地图片」挑一张图,PNG、JPEG、WebP、GIF、BMP 都能读。图片只在你自己的浏览器里解码,没有任何上传请求。
  2. 载入后结果区会显示原始尺寸(来自图片自身的像素宽高),宽度框和高度框也会被自动填成原始值,方便你在原图基础上改。
  3. 目标宽度默认 1920、目标高度默认 1080,这就是本页的示例值。两个框都只接受 1~65535 的整数。
  4. 保持「锁定原始比例」勾选,你只改宽度,高度会按原图比例自动算出来;取消勾选后可以分别指定宽和高,此时画面会被拉伸或压扁。
  5. 在导出格式里选 JPEG、PNG 或 WebP。选 JPEG、WebP 时下面的画质滑块生效,默认 0.92;PNG 是无损格式,滑块对它不起作用。
  6. 点「按当前尺寸导出」,浏览器在本地重采样后直接触发下载,文件名会自动带上目标尺寸。

这个图片尺寸调整工具能解决什么问题

一是上传前的体积与边长限制。手机原图 4000×3000 是 1200 万像素,解码后光是 RGBA 缓冲就要 45.78 MiB;很多后台上传口限边长 1920、限体积 2 MiB。先缩到 1200×900,像素数降到 108 万,面积只有原来的 1/11.11,再配合 JPEG 0.92 的画质,绝大多数场景一次过限。

二是统一一批素材的基准宽度。商品图、封面图、文档插图混在一起时,尺寸参差不齐会让排版跳动。把宽度统一到 1600 或 1920,高度按比例跟随,版式立刻整齐。

三是给高分屏做 2 倍图。同一条视觉稿需要一倍图和两倍图两份时,先导一份 640 宽,再导一份 1280 宽即可,两份共用同一个构图,不需要重新设计。

四是控制浏览器的解码内存。一张 8K 全景 7680×4320 是 3317 万像素,RGBA 缓冲 126.56 MiB,在内存紧张的设备上会明显吃力;把它缩成 1920×1080,内存占用直接掉到 7.91 MiB。

本页的图片尺寸调整只改像素总数,不改画面构图:不会把边缘切掉,不做旋转、调色、加字,也不做批量队列。一次处理一张,用完即走。

缩放原理:drawImage 九参数重载与分步减半

重采样发生在 CanvasRenderingContext2D.drawImage() 的九参数重载里。这个重载的签名是 drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh):前四个参数 sx, sy, sw, sh 在源图上框出一个矩形,后四个 dx, dy, dw, dh 把这块矩形画到画布的目标矩形里。缩放的实现就是把 sw, sh 设成原图宽高、dw, dh 设成你要的目标像素。缩小时一个输出像素会盖住源图上好几个像素,浏览器必须把它们合成一个,这一步叫重采样,也是画质分野的真正战场。

第二个关键参数是 imageSmoothingQuality。它有 low、medium、high 三档,前提是 imageSmoothingEnabled 为 true(规范默认就是 true,但显式写出来更稳妥)。在 Chromium 里这三档对应三种插值核:low 是双线性插值(每个输出像素看源图 2×2 邻域),medium 是双三次插值(4×4 邻域),high 是接近 Lanczos 的多抽头插值。抽头越多边缘越干净、代价是耗时上升,单张图完全值得选 high。

为什么大幅缩小不能一次到位。浏览器的快速缩放路径里,采样窗是固定大小的。把 4000 宽一次缩到 500 宽(1/8),每个输出像素只从源图 2×2 的窗口取样,剩下六十多个被跨过的像素直接丢弃,高频细节就变成摩尔纹和锯齿。稳妥做法是分步减半:每次只缩一半,让采样窗始终覆盖全部输入像素;1/2 连做三次等价于 1/8,但抗锯齿效果差很远。本工具的判据是「当前边长还大于目标的两倍就再减半」,因此 4000×3000 缩到 1200×900 需要 2 次 drawImage(4000×3000 → 2000×1500 → 1200×900),缩到 400×300 需要 4 次,缩到 200×150 需要 5 次。

EXIF 方向是最容易被忽视的坑。相机和手机竖着拍的照片,像素数据往往是横的,靠 EXIF 里一个叫 Orientation 的字段记录「该转多少度」。这个字段共有 1~8 八种取值,覆盖正常、水平镜像、旋转 180°、垂直镜像,以及 90° / 270° 的旋转加镜像组合,手机竖拍最常见的是 6 和 8。用普通的 new Image() 加载再画到画布上,部分路径不会应用这个标记,导出的图就会躺倒。稳妥写法是 createImageBitmap(blob, { imageOrientation: 'from-image' }),让解码器在解码阶段把像素摆正,再交给 drawImage;本工具优先走这一条,旧浏览器才退回 Image 元素。

画布本身有硬上限,超了不会报错。Chromium 的画布单边最大 65535 像素,总面积上限是 2 的 28 次方 = 268435456 像素,约等于 16384×16384。传给 canvas.width / height 的乘积一旦越界,浏览器不抛异常,而是静默给出一张空白图——这是最容易被误判成「工具坏了」的一类问题。所以本页在算目标尺寸时会先做面积校验并给出明确提示。

最后是导出接口的取舍。toDataURL() 是同步的:它在主线程上跑完整编码器,再把二进制转成 base64 文本返回。base64 比原二进制大 4/3,也就是多出 33.33%,一张 500000 字节的 JPEG 会变成一个 666668 字符的字符串,大图时足以让页面卡住。toBlob(callback, type, quality) 是异步的,直接把 Blob 交回来,既省掉 base64 膨胀,也不会长时间占住主线程,所以本工具用它导出。

完整示例(数值仅作演示)

页面打开时的默认条件是:目标 1920×1080、导出格式 JPEG、画质 0.92、勾选「锁定原始比例」。图片尺寸调整的默认结果就是下面这一组数字,其中 1920×1080 同时也是对照表里的一行,两处一致。

再看一条边界示例:目标填成 20000×20000 时,面积是 400,000,000 像素,已经超过 268,435,456 的上限,超限约 49%,本页会直接拦下来并写清超了多少,而不是给你一张空白图。

输入范围、画布上限与分辨率对照表

下表把常见分辨率换算成像素数与 RGBA 缓冲体积。RGBA 缓冲 = 宽 × 高 × 4 字节,是图片被解码进内存后的真实占用量,和文件体积不是一回事——一张 500 KB 的 JPEG 解码后可能占好几十 MiB。

分辨率像素数RGBA 缓冲相对 1920×1080
640×360230,4000.88 MiB0.11 倍
800×600480,0001.83 MiB0.23 倍
1024×768786,4323.00 MiB0.38 倍
1280×720921,6003.52 MiB0.44 倍
1366×7681,049,0884.00 MiB0.51 倍
1440×9001,296,0004.94 MiB0.63 倍
1600×9001,440,0005.49 MiB0.69 倍
1920×1080(默认)2,073,6007.91 MiB1.00 倍
2048×15363,145,72812.00 MiB1.52 倍
2560×14403,686,40014.06 MiB1.78 倍
3840×21608,294,40031.64 MiB4.00 倍
4096×21608,847,36033.75 MiB4.27 倍

点「加载更多分辨率」会补上更大的一档,点「导出 CSV」把当前可见的整张表存成带 BOM 的 CSV(Excel 打开不乱码),点「复制对照表」复制成制表符分隔的文本,可以直接粘进表格软件。

边界与精度说明

常见问题

图片会上传到服务器吗?

不会。文件通过 File 对象交给 createImageBitmap 在本地解码,重采样在你的浏览器里用 canvas 完成,导出走 toBlob。想自己确认,打开开发者工具的网络面板,选一张图并导出,全程不会有任何新请求。

为什么一次缩小会出现锯齿?

因为浏览器的快速缩放路径里采样窗是固定大小的,一次缩到 1/8 时每个输出像素只看得到源图 2×2 邻域,被跨过的像素全部丢掉,细密的纹理就会出现摩尔纹。改成每次减半、分步执行,采样窗始终覆盖全部输入像素,边缘和纹理就干净很多。

竖着拍的照片导出来为什么躺倒了?

因为像素数据本身是横的,方向记录在 EXIF 的 Orientation 字段里,共 1~8 八种取值。某些加载路径不会应用这个标记。本工具优先使用 createImageBitmap(blob, { imageOrientation: 'from-image' }),让解码器直接输出摆正后的像素,所以竖拍照片不会躺倒。

为什么导出的图小了很多,画质却看不出差别?

因为像素数少了,但每个像素仍是 24 位真彩色,只是用来表达细节的像素变少。1920 宽的图在 1920 宽的屏幕上是一比一显示,不会放大,肉眼看不出损失;只有当你再把它放大,或者打印到 A3 以上,才会看出差距。

PNG 和 WebP 怎么选?

要保留透明通道又不想有损压缩,选 PNG;要体积最小、可以接受有损,选 WebP,同样画质下通常比 JPEG 再小两三成,Chromium、Firefox、Safari 14 以后都能打开。只有在意最广泛的兼容性时才回退到 JPEG。

能一次处理很多张吗?

不能。这个图片尺寸调整工具刻意做成一次一张:重采样是 CPU 密集操作,批量跑容易把标签页卡住,也容易在导出到一半时丢失命名对应关系。多张素材的批量需求建议用桌面端的图像处理软件。

目标尺寸填得很大时为什么提示超限?

因为画布有面积硬上限 268435456 像素(约 16384×16384)。超过之后浏览器不会报错,而是给你一张空白图,非常难排查。本页提前校验,会在提示里写清你填的乘积、上限是多少、超了多少,方便你直接改小。

缩放之后的图还能看到拍摄信息吗?

看不到。canvas 输出的是纯像素位图,EXIF 里的相机型号、镜头、光圈、快门、ISO、拍摄时间和 GPS 坐标都不会带过去。如果你需要保留这些信息,得用会写回 EXIF 的桌面软件处理。

相关工具