杂记 › 技术笔记 › 锁是单向的、百分比是两把尺:pct 50 得 619×430,PNG 四档 quality 全 6971 B

锁是单向的、百分比是两把尺:pct 50 得 619×430,PNG 四档 quality 全 6971 B

宽高锁只读宽、只写高,手打的高会被打回;百分比是宽高各跑一次 Math.round,pct 50 得 619×430;同一张 PNG 四档 quality 全 6971 B,逐笔实测。

两个框为什么会在同一张图上互相打架

一张自造的 1237×859 纯色图(非照片)拖进去,锁着时把宽打 800,高框写回 "556";再把高框手打成 300,它又变回 "556"。滑杆那头:同一张 PNG 缩到 619×430,质量从 10 拖到 100,四轮结果行都是 "619 × 430 | 6.8 KB"。这页模板 12308 字节 / 265 行,脚本原样跑两路:node:vm 桩与 Chrome 154 真编码器。

被测的是图片尺寸调整,全页本地处理,grep fetch( 命中 0 处。

锁只读宽、只写高

onSizeInput(L188–L192)锁着时只读宽框、只算 Math.round(宽 / aspectRatio)、只写高框。aspectRatio 存的是 1237/859=1.440046565774156 这个浮点商,不是既约比,于是手打的高必被覆盖:宽 800 + 手打高 300 → 高框留 "556"。toggleLock(L181–L185)解锁后两框各走各的。

锁着时宽框高框除法原值
859597596.5084882780922

这把尺在原图上共扫 18 档(1237→"859"、400→"278"),宽打 1 时靠进位保住高 1。

百分比是两把独立的尺

onPercentInput(L195–L200)对宽高各跑一次 Math.round,完全不看 aspectLocked。pct=50 → 619×430,理想 618.5 × 429.5,两框之和 1049 对 1048、差 1。两轴同时以 .5 结尾的 p 有 10 档,Math.round 对正 .5 一律进位;pct 从 1 扫到 1000,120 档两条路的高不等。

同一张 1237×859,两条路的高 pct=1 → 12 × 9 锁尺 → 12 × 8 分歧:1.3333… 对 1.5 宽 309 / 619 / 928 / 1856 四档重合,属巧合档。

图 1:pct=1 那档两条路给出两种长宽比。

比例框从不回头读宽高框

switchMode(L172–L178)只改 currentMode 与两个面板的 display,没有任何一行代码回写 resize-percent。点 150% → 切回 pixel → 把宽手打 400(高被算成 278),比例框全程仍显示 "150";反推值 100*1856/1237=150.0404% 不等于框里的 150——框里存的是「点过的档」。再点一次 setPercent(150)(L203–L206)就把两框打回 1856×1289,刚手打的 400 蒸发。

滑杆在 PNG 上为什么一个字节都不动

本机 Chrome 154 只有三个真编码器,1×1 画布上 png / jpeg / webp 分别回 110 / 762 / 552 B。L229 把滑杆值除 100 交给 toBlob,PNG 编码器不吃这个参数;BMP 又叠一层——L228 把输出改写成 PNG,而 L152 只给 image/jpeg / image/webp 显示质量行,滑杆本身 display:none。

619×430 的 blobq10q50q90q100
PNG6971697169716971
JPEG2338234023413921
WEBP1092110210504684

JPEG 的 10→90 三档只差 3 B;WEBP 的 q90 比 q10 小(1050<1092),编码器不保证单调;BMP 源(3188662 B)六档全 6971 B。同族几页共用这一份模板,那几页的字节账不在本篇。

结果行那串字面怎么拼

L235 是 w + ' × ' + h + ' | ' + formatSize(blob.size),w/h 取 JS 里的整数而非画布属性," × " 是 3 码元/4 字节。formatSize(L165–L169)分三档:B 档原样整数、KB 档 toFixed(1)、MB 档 toFixed(2),阈值 1024 与 1048576,实测 1024→"1.0 KB"、1075→"1.0 KB" 而 1076→"1.1 KB"、1048576→"1.00 MB"。压字节走另一条通道,见图片压缩;那篇透传的实测量的是别一页。

三闸与它拦不住的那些

doResize(L209–L237)只三道闸:无图、parseInt 出 NaN 或 ≤0、w>10000 || h>10000;JS 不设下限校验,min="1" / max="10000" 只是控件属性:"10001" 浏览器不拦,走到 L216 才弹「尺寸不能超过 10000px」。最安静的是 "1e5":parseInt 遇 e 停读成 1,无 toast 真出图,结果行 "1 × 1 | 762 B",输入与产出差 5 个数量级。只有滑杆被浏览器硬夹(打 9 → "10"),L229 因此落在 10..100。

失败之后屏上留着的是上一张

出过 "1 × 1 | 762 B" 之后再打 w=619 / h=0,弹「请输入有效的宽高尺寸」,结果行仍读上一句。更实在的是不落地那格:先出 619×430 的 webp("619 × 430 | 1.0 KB"、1050 B),再打 10000×10000 的 webp:回调不来,画布属性却已被 L221–L222 同步改成 10000x10000,结果行仍是上一句、下载仍是上一档那 1050 B。resetAll(L253–L263)之后七个状态量逐字不变。

批量是实测出来的「没有」:files.length 0 处、for( 0 处、progress 0 处,两处 files[ 只取 [0];一次拖入 2 个文件只有第 1 张进 handleFile。重采样算法与 imageSmoothingQuality(页面从不读它,无像素级判据可反推核函数)、队列与耗时(无队列代码即无对象可测)、界面渲染像素(无渲染器判据),一律标未实测。

顺带对一眼文案

config/tools.php 的 image-resize 条目 16 条主张逐条判:[一致] 6、[部分一致] 7、[冲突] 3。冲突三条:「另一边」只对一半、「证件照」档锁着时输入 295 得 205 而不是 413(差 -208,要先解锁而文案未提)、「缩略图批量」零通道。

常见问题

Q:锁着时手打高度为什么被打回?

锁只在宽→高一个方向写,手打值在回写那一步被覆盖。

Q:pct 50 得 619×430,是等比吗?

它是宽高各过一次 Math.round:619/430=1.4395348837209303 对源比差 -0.0355%,1..1000 里 120 档与锁尺不等。

Q:滑杆拉满为什么字节没变?

PNG 与被 L228 改写成 PNG 的 BMP 不吃 quality,四轮同字面;只有 JPEG / WEBP 变字节。

📎 相关文章

星号段长写死:脱敏页五套掩码固定切出 4、3、11、12 枚星号,18 位串被手机档抢走、空框回落 * 2026-11-13 相对时间的「一个月」写死 30 天:时间戳页六档除数、13 位毫秒输入与 UTC+8/UTC-5 两档截断实测 2026-11-13 两 tab 各算一遍同一个 C(n,r):n=20 写满 40 个因子、n=21 一格不剩,300 位大数与 r=0 的两种读法 2026-11-13 8 个元素算得出 40320 条却只列 5000 行:排列计算器的两道互不相干的上限、重复元素按 3! 计数与 n≤20 的过程断点 2026-11-12 投放链接的装配顺序与大小写折叠:UTM 生成器六态标注、两道硬上限与五栏各用一把尺实测 2026-11-12