图片马赛克(像素化)工具

把图片切成 n×n 的小块,每块压成一个颜色再按最近邻放大回去:canvas 读 imageData、按块聚合、写回画布,不是叠一层 CSS 滤镜。块大小 2 到 32 可调,取样方式可选均值或中值,透明区域可选按 alpha 加权。打开页面就先跑一张内置示例图。

块大小 8:每 64 个像素压成 1 个,信息损失 98.44 个百分点。
图片:内置示例图(未选择文件) 尺寸 320 × 160,51200 像素 块大小 8;取样 均值;alpha 加权 开 块数 800,每块 64 像素 -- 逐像素处理 -- 读取 imageData:51200 × 4 = 204800 字节 像素保留比例 1.56,信息损失 98.44 个百分点

原图

马赛克结果

块大小对照表共 20 行,默认显示 12 行。

打开就先跑一张内置示例图,选一张图片后点「马赛克」换成你的图。整页在浏览器本地处理,图片不会上传。

使用方法

  1. 打开页面就已经跑过一遍:左边是内置示例图(320 × 160 的渐变加色块,右下角有一块半透明区域),右边是块大小 8 的马赛克结果。
  2. 「选择图片」换成你自己的文件,再点「马赛克」。支持 PNG、JPEG、GIF、WebP,大小上限 20 MB;选了非图片文件会给出指明类型的提示。
  3. 「块大小 n」范围 2 到 32,步长 1,默认 8。数字越大块越大,保留的像素越少:n=8 时只剩 1.56,信息损失 98.44 个百分点。
  4. 取样方式二选一:均值把块内所有像素平均,中值取块内各通道的中位数。透明图建议先试试中值,硬边保得住。
  5. 「按 alpha 加权」默认打开。关掉之后透明边缘会出现灰黑边——这是马赛克最常见的 bug,页面把它做成开关就是为了让差别看得见。
  6. 结果区上面一行是结论,下面一段是明细:尺寸、像素数、块数与每块像素数、imageData 字节数、像素保留比例与信息损失。
  7. 「下载 PNG」把右边画布导出成文件;导出的就是马赛克后的像素本身,不是叠了一层滤镜的预览。
  8. 下面的块大小对照表共 20 行(n 从 2 到 40,步长 2),默认显示 12 行。点「加载更多」展开全部,点「导出 CSV」存成带字节序标记的文件。
  9. 块大小留空、写成小数、或超出 2 到 32 时,分别给出指明原因的提示,不会自动夹到边界值。

这个 Pixelate图片工具能解决什么问题

第一类是隐私遮挡。截图里的人脸、门牌、车牌、订单号、身份证号,盖一层马赛克之后再发出去。这里的关键是:马赛克把块内信息真的丢掉了,不是盖了一层可以撕掉的膜——把结果放大只会看到更大的方块,看不到原来的内容。

第二类是把位图做成像素风。照片缩小到块大小 8 到 16 再拿去当素材、做头像、做背景,出来的方块质感与直接缩放完全不同:直接缩放是平滑的,马赛克是硬边的。

第三类是给缩略图占位。批量生成列表缩略图时,用大块马赛克当占位图,文件小、加载快,视觉上又能看出主色调,比纯灰底占位好得多。

第四类是降噪预处理。扫描件上的网点、压缩产生的蚊式噪声,用中值取样压一遍能干净不少——中值对孤立的极端值不敏感,这正是它相对均值的优势。

计算原理与变量说明

整页只有一件事:遍历全图,把每个块内的像素聚合成一个值,再把这个值写回块内所有位置。规则表如下。

变量公式说明
像素保留比例100 / n²n 为块边长
信息损失100 − 100 / n²n=8 时为 98.44
均值取样v = Σ(vᵢ × aᵢ) / Σaᵢ按透明度加权
中值取样v = median(vᵢ)各通道取中位数
块内 alphaa = Σaᵢ / 块内像素数两种取样都用这个
块数ceil(W/n) × ceil(H/n)边角不足一块的按剩余算

信息损失是 n² 级别的,这是本页最硬的一条。把 n×n 的块压成一个值,像素数降到 1/n²:n=2 时剩 25.00,n=4 时剩 6.25,n=8 时只剩 1.56(也就是损失 98.44 个百分点),n=16 时剩 0.39,n=32 时只剩 0.10。这也是马赛克能用于隐私遮挡的真正原因——信息在聚合那一步就被丢掉了,无法从结果反推。影视剧里「把模糊的照片放大还原出车牌」在数学上不成立:块内 64 个像素只留下一个平均值,原值有无数组解。

均值与中值的差别在极端值上。块 [10,10,10,250] 的均值是 70、中值是 10,两者相差 60 级。均值会把一个亮点「晕开」成一片灰——噪声、噪点、孤立的高光都会被摊到整块上;中值能保住硬边,代价是渐变会被压成阶梯。打人脸轮廓用均值更糊、用中值更「块」,选哪个取决于要的是模糊还是块状。

alpha 必须先加权,否则透明边缘会出灰黑边。块里如果是一个完全透明的黑 (0,0,0,0) 和一个不透明的纯白 (255,255,255,255),直接对 RGB 求均值得到 (128,128,128,128):既不是白也不是透明,是一片灰。按 alpha 加权之后,颜色取 (255×255)/255 = 255、透明度取 (0+255)/2 = 127.5,得到的是半透明的纯白——这才是对的。透明像素的 RGB 值没有意义(往往是 0,也就是黑),不加权就等于让这些无效的黑参与平均。

与「缩放再放大」不是一回事。双线性缩放把图缩到 1/n 再放大回来,像素被插值平滑,边缘柔和、看起来像糊了;马赛克用最近邻放大,块内是同一个值,边缘是硬的方块,视觉上明确传递「已被处理」这件事。另外复杂度是 O(W×H) 且与块大小无关——只需遍历全图一次,把每个像素累加到它所属的那个块桶里,不是邻域运算,所以大图也很快、块大小随便调。

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

内置示例图是 320 × 160,共 51200 个像素、204800 字节的 imageData。块大小 8 时切成 40 × 20 = 800 块,每块 64 个像素,压完之后只剩 800 个不同的值。

均值被极端值拉偏的例子:块 [10,10,10,250] 均值 70、中值 10,差 60 级。切到「中值」再看同一张图,硬边明显更利落,渐变区域则出现阶梯。

alpha 加权的例子:右下角那块半透明区域,开着加权时贴近上层颜色,关掉加权立刻浮出一片灰——这就是 (128,128,128,128) 与 (255,255,255,127.5) 的差别。

信息损失那条:n=8 时 1.56 / 98.44;把 n 拉到 32 只剩 0.10,也就是全图只剩 500 个值,此时已经认不出原图是什么。

块大小与信息损失对照表

第一张表是本页的核心数字,「复制对照表」复制的就是它。

块大小 n每块像素像素保留信息损失说明
2425.0075.00只能看出轮廓
4166.2593.75轻度遮挡
8641.5698.44本页默认值
162560.3999.61常用打码档
3210240.1099.90几乎只剩色块
4016000.0699.94仅剩主色调

第二张表是取样方式的差别,用同一个小块举例。

块内像素均值中值相差
[10,10,10,250]701060
[10,10,10,10]10100
[0,255]1281280
[0,0,0,255]64064

第三张表是透明度加权,同一个两像素块的两种口径。

口径颜色alpha结果
不加权(128,128,128)128灰边
alpha 加权(255,255,255)127.5半透明白
块内两个像素(0,0,0,0) 与 (255,255,255,255)—透明黑 + 不透明白
加权公式Σ(v×a) / Σa127.5颜色取 255

读法:第一张看块大小与信息损失,第二张看取样方式,第三张看透明边缘为什么必须先加权。

结果边界、舍入与适用说明

常见问题

打码后的图还能还原吗?

不能。块内 64 个像素(n=8 时)只留下一个值,原值有无数组解。影视剧里放大还原车牌在数学上不成立,信息在聚合那一步就丢了。

为什么关掉 alpha 加权会出灰边?

因为透明像素的 RGB 往往是 0(黑),不加权就等于让这些无效的黑参与平均。块 [透明黑, 不透明白] 不加权得 (128,128,128,128),加权后得颜色 255、alpha 127.5。

均值和中值该选哪个?

要糊选均值,要硬边选中值。块 [10,10,10,250] 均值 70、中值 10,差 60 级;均值会把亮点晕开成一片灰,中值保得住边但会把渐变压成阶梯。

块大小多大合适?

遮人脸用 16 到 32;做像素风用 6 到 12;做缩略图占位用 8 到 16。n=8 时像素只剩 1.56,n=32 时只剩 0.10。

这和对图片缩放再放大一样吗?

不一样。缩放用插值,边缘柔和;马赛克用最近邻放大,块内是同一个值,是硬边方块,视觉上明确表示已被处理。

大图会不会很慢?

不会。只需遍历全图一次累加到块桶里,复杂度 O(W×H) 且与块大小无关,不是邻域运算,所以块大小随便调。

没有图片能不能用?

能。打开页面就先画一张 320 × 160 的内置示例(渐变、色块、半透明区域各一块)并直接跑一遍马赛克,选了文件再替换。

图片会上传到服务器吗?

不会。文件只在浏览器里解码、逐像素处理、导出,没有发起任何网络请求,也没有写入本地存储。

相关工具