杂记 › 技术笔记 › 位图进 SVG 只换了个盒子:232 字节容器常数、一个从不生效的「base64 嵌入」勾选,与四档缩放下纹丝不动的 142064 个字符

位图进 SVG 只换了个盒子:232 字节容器常数、一个从不生效的「base64 嵌入」勾选,与四档缩放下纹丝不动的 142064 个字符

这一页只做封装不做描摹:容器开销恒 232 字节、「base64 嵌入」勾选三态产物逐字节不变、四档缩放下 142064 个字符一动不动,再加上下载 URL 那层第二次膨胀,逐笔实测。

先把结论钉在字节上

这一页的产物里没有 <path>,只有 <image> 那一行把整条 data URL 原样抱住。全模板 grep canvas、drawImage、toDataURL、trace、quantiz、posterize 各 0 次,位图入口只有 readAsDataURL 的 1 次(L144)。28 张自造图加同批另外 3 张共 31 个文件,取回 base64 解码后与输入逐字节 31/31 全等。

被测的是图片转 SVG那页的模板,10270 字节,脚本段逐字摘进 node:vm 原样跑。

容器开销是一个常数

buildSvg(L157–L198)的固定部分是 15 段字面量相加:39+40+48+12+10+2+18+1+3+16+10+2+21+4+6 = 232 字节,含 7 枚换行、27 枚缩进空格。于是 svgB = 232 + 3*len(w) + 3*len(h) + prefixLen + b64Len:w、h 各写三遍,每个数字字符付 3 字节;prefixLen 只有 22 与 23。31 行容器恒等式表 resid 全 0,例 n=581743 的 jpg:775660 + 21 + 23 + 232 = 775936。

base64 只报对账结果

ceil(n/3)*4 命中 31/31;补位三档,余 0 尾下 0 枚(28 张里 8 张)、余 1 补 2 枚(12 张)、余 2 补 1 枚(8 张)。整除样本的 b64/n 正好 1.333333,偏离只在几十上百字节量级看得见:a_1x1.png 是 1.369863,到 100 KB 级只剩 0.000025。

从不生效的「base64 嵌入」

L21 那枚 checkbox 全文出现 1 次、出厂 checked,脚本块里按 id 取它 0 次。对 d_101x67.png 把勾选切成三态各构建一次,三次产物 sha 前 12 位都是 5d037f0d8a4b、长度都是 30249,取消勾选后输出逐字节不变。L22 那句「使用 base64 嵌入(生成独立 SVG 文件)」在本页没有落点,因为这一页唯一的嵌入方式就是 base64。

原图 B → base64 字符 → SVG B a_1x1.png 73 100 360 urlLen/svgB 1.6694 h_1200x900.png 1030404 1373872 1374147 整条 1.3336 1.1440 28 张合计 3808141 5085119 1.3353 下界 1.0552 属于 n_123x45.bmp

图 1:同一条链上的三层长度。

四档缩放只改三个声明数字

L159/L160 的 Math.round 只产出 6 个数字槽,L168 的 base64 与档位无关。那张 24 行的缩放表里,241×137 的 b64Len 恒 142064,声明依次 60×34、121×69、241×137、482×274;101×67 的 PNG 恒 29980、BMP 恒 27232。取整痕迹 120.5 → 121、60.25 → 60;1×1 选 25% 归零成 width="0" height="0" 与 image_0x0.svg。

档位声明 w×hsvgB界面「SVG 大小」
25%60×34142330139.0 KB
50%121×69142333139.0 KB
100%241×137142336139.0 KB
200%482×274142336139.0 KB

档间那 6 字节差只来自位数变化,位图数据一动不动。

标签会停在旧档位

出厂三处口径互不相同:L26 的 active 在 25%、L85 默认 imgSvgScale=100、档位标签出厂写 100%。上传后 L131–L134 重置 scale=100、active 移到下标 2,却不碰标签文本——全文给这个 id 赋值的只有 L152。实测先点 25% 再上传另一张,标签停在 "25%"、实际 imgSvgScale=100、声明与固有都是 241×137,即按 100% 出图而界面写着 25%。

下载 URL 的第二次膨胀

L171 的 encodeURIComponent 只动 base64 里的加号、斜杠、等号,每枚从 1 字符变 3 字符。合式 urlLen = 33 + svgB + 2*esc 在那张 18 行表上全 OK,骨架固定贡献 100 枚被转义字符。urlLen/svgB 从 1.6694 收敛到 1.0552,大文件稳定在 1.055 到 1.072;h_1200x900.png 因斜杠占 4.5669%、加号占 2.6251% 被推到 1.1440。预览与下载吃这一层,界面显示的是上一层。

显示口径与格式判定

formatSize(L226–L230)先判档再 toFixed(1),于是 1048575 显示成 1024.0 KB,h_1200x900.png 相邻两行一个 1006.3 KB、一个 1.3 MB——这是本页显示口径,不是文件系统差异。

L103 那个正则 /image\// 无锚点、无 i 标志,17 个 type 放行 11 条、拦截 6 条:拦下空串、text/plain、application/pdf、IMAGE/PNG、png、image,而 ximage/png、foo/image/bar、not/image/、text/html,image/png 全过,「格式」行显示成 XPNG、FOO/BAR、NOT/、TEXT/HTML,PNG。grep onerror 0 次,解码失败时整段不执行、面板不亮。

动图与文案对照

j_anim2.gif(900 字节、loop=0)两帧延迟 20cs 与 50cs,封装后解回字节重解帧结构逐字段相同、MIME 仍是 image/gif,svgB 1472。0 尺寸 SVG 的渲染、Chrome 同名追加 (1)、data URL 长度上限、6.4 MB 进 innerHTML 的代价连同逐帧播放都未实测,原因是 Node 无渲染与下载栈;JPG 与 WEBP 的字节流由 headless Chrome 代编码并回核过前缀与长度。文案按 config/tools.php 第 46 个条目判 17 句:一致 6、需限定与部分一致 4、冲突 7,其中 5 句指着同一处代码事实。

封装与描摹的分界,旧文位图转矢量写过,不复述;容器之间的搬运归 SVG 格式转换,本文对它没有测量。

常见问题

Q:取消「base64 嵌入」勾选,产物会变吗?

不会,三态产物的 sha 前 12 位与长度 30249 全同。

Q:选 25% 之后文件会小一点吗?

241×137 四档的 b64Len 恒 142064,svgB 只差 6 字节,界面都是 139.0 KB。

Q:GIF 动图封进去保得住吗?

字节与帧结构保得住,延迟 20cs 与 50cs 反解后逐字段相同;播放体验未实测。

📎 相关文章

拖到 4 和拖到 8,屏幕上都是 43890 个块:马赛克预览与导出的两套块网格、三档会崩与 6px 误触阈值 2026-11-10 转完悄悄少了 271 个字符:Markdown 转 HTML 的洞协议、64 轮回填与 20 条提示上限 2026-11-10 解码是四步连做:1194 条语料在 unicode-convert 页上只有 798 条能原样回来 2026-11-09 保留集缩成 66 个字符:这一页三档编码在 128 个码位上的逐字符实测与 9 格编解码矩阵 2026-11-09 八个框的界面顺序和代码执行顺序是反的:文本清理页硬编码八步顺序、逐对换序真值表与统计码元口径实测 2026-11-09