diff --git a/CHANGELOG.md b/CHANGELOG.md index e646298..14740e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.12.0 (2026-07-31) + +### 新增 +- 双三次缩放:`resize_bicubic(w, h)`,Catmull-Rom 4×4 核、中心对齐采样,同尺寸缩放为恒等 +- 感知哈希:`average_hash()` / `difference_hash()` 返回 64 位指纹,`hamming_distance(a, b)` 度量相似度;区域均值缩略图保证跨后端确定性 +- 确定性噪声:`add_gaussian_noise(seed, sigma)`(CLT 12 均匀和)与 `add_salt_pepper(seed, density)`,64 位 LCG 驱动,同 seed 逐字节可重现 + +### 变更 +- 单元测试从 147 个增加到 163 个(含反相恰好翻转全部 64 位、中值滤波清除 ≥75% 椒盐噪声等强断言) + ## 0.11.0 (2026-07-30) 代码审查驱动的加固(三视角审查后全量修复): diff --git a/README.en.md b/README.en.md index b3eea5a..00ec0a9 100644 --- a/README.en.md +++ b/README.en.md @@ -19,7 +19,7 @@ English | [简体中文](README.md) ## ✨ Features -- **26 filters & geometric transforms**: grayscale, invert, brightness, contrast, gaussian/box blur, sharpen, emboss, Laplacian/Sobel/Scharr/Canny edges, sepia, threshold, pixelate, median denoise, histogram equalization, posterize, gamma, vignette, saturate, hue rotate, horizontal/vertical flips — plus 90° rotation and nearest/bilinear resize. +- **26 filters & geometric transforms**: grayscale, invert, brightness, contrast, gaussian/box blur, sharpen, emboss, Laplacian/Sobel/Scharr/Canny edges, sepia, threshold, pixelate, median denoise, histogram equalization, posterize, gamma, vignette, saturate, hue rotate, horizontal/vertical flips — plus 90° rotation and nearest/bilinear/bicubic (Catmull-Rom) resize. - **Morphology**: 3×3 erode / dilate / open / close. - **Image codecs**: PNG (self-implemented full DEFLATE inflate with CRC-32/Adler-32 verification), GIF decoding (variable-width LZW, interlacing, transparency), QOI (complete spec, lossless round trip) and BMP (uncompressed 24/32-bit) — all in pure MoonBit. - **Affine transforms**: an `Affine` matrix type (rotate/translate/scale/shear + composition + inversion) rendered by inverse mapping with bilinear sampling; arbitrary-angle `rotate(degrees)`. @@ -28,7 +28,7 @@ English | [简体中文](README.md) - **Unsharp mask**: `unsharp_mask(radius, amount)` reuses the Gaussian to extract and re-add high-frequency detail, sharpening edges. - **Crop & pad**: `crop(x, y, w, h)` (clamped to bounds) and `pad(l, t, r, b, color)` (colored borders); `crop∘pad` round-trips losslessly. - **Bilateral filter**: `bilateral(radius, σs, σr)` edge-preserving smoothing — denoises flat regions while keeping strong edges sharp. -- **Image analysis**: Otsu automatic thresholding (between-class variance), Floyd–Steinberg error-diffusion dithering, 4-connected component labeling and counting, chamfer (3,4) distance transform. +- **Image analysis**: Otsu automatic thresholding (between-class variance), Floyd–Steinberg error-diffusion dithering, 4-connected component labeling and counting, chamfer (3,4) distance transform, perceptual hashes (aHash/dHash + Hamming distance). - **Integral image & O(1) box blur**: `integral_image()` builds a summed-area table (Int64, overflow-safe) that drives `box_blur(radius)` at O(1) per pixel for any radius. - **Flood fill**: `flood_fill(x, y, color, tolerance)` 4-connected seed fill with per-channel tolerance. - **Layer compositing**: `composite(top, mode)` — Porter-Duff source-over with 8 blend modes (multiply, screen, overlay, darken, lighten, difference, add), in rounded integer math. @@ -36,7 +36,8 @@ English | [简体中文](README.md) - **Color spaces**: exact round-trip RGB ↔ HSV and RGB ↔ YCbCr (BT.601) conversions. - **Generic convolution engine**: `Kernel` + `Image::convolve` for custom odd-sized kernels. - **Image statistics & tone**: `stats()` per-channel min/max/mean (Int64 accumulation), `auto_contrast()` automatic contrast stretch, `levels(black, white, gamma)` tonal remap. -- **Integer-first, deterministic**: filter math sticks to integers where possible (e.g. luma weights ×1000); results are reproducible and **all 147 unit tests are hand-verified** (including canonical CRC-32/Adler-32 check vectors and a hand-assembled DEFLATE bitstream). +- **Deterministic noise**: `add_gaussian_noise(seed, σ)` / `add_salt_pepper(seed, density)` driven by a 64-bit LCG — the same seed is byte-identical on every backend. +- **Integer-first, deterministic**: filter math sticks to integers where possible (e.g. luma weights ×1000); results are reproducible and **all 163 unit tests are hand-verified** (including canonical CRC-32/Adler-32 check vectors and a hand-assembled DEFLATE bitstream). - **Zero dependencies**: only `moonbitlang/core`, no third-party libraries. - **Multi-backend, zero-copy interop**: on the js backend a `FixedArray[Byte]` *is* a `Uint8Array`, so canvas `Uint8ClampedArray` buffers cross over without copies; the linear-memory wasm backend exports `memory` for bulk pixel access. - **Browser Playground**: drag & drop / paste / upload images, stackable filter pipeline, JS/WASM engine switch with benchmarks, an optional **Web Worker background thread** for large images, and PNG downloads produced by the library's **own `png_encode`**. @@ -62,6 +63,9 @@ pixelforge/ ├── floodfill.mbt # flood fill (4-connected seed fill) ├── distance.mbt # chamfer (3,4) distance transform ├── stats.mbt # statistics / auto-contrast / levels +├── bicubic.mbt # bicubic resize (Catmull-Rom) +├── phash.mbt # perceptual hashes (aHash/dHash + Hamming) +├── noise.mbt # deterministic noise (gaussian / salt-pepper) ├── bilateral.mbt # bilateral filter (edge-preserving) ├── otsu.mbt # Otsu automatic threshold ├── dither.mbt # Floyd–Steinberg error diffusion @@ -75,7 +79,7 @@ pixelforge/ ├── transform.mbt # flips, 90° rotation ├── resize.mbt # nearest/bilinear resize ├── dispatch.mbt # Image::apply_filter_id shared dispatch table -├── *_test.mbt # 147 deterministic tests (blackbox + whitebox) +├── *_test.mbt # 163 deterministic tests (blackbox + whitebox) ├── cmd/main/ # native CLI example (moon run cmd/main) ├── cmd/ppm/ # PPM output example (moon run cmd/ppm > edges.ppm) ├── cmd/showcase/ # capstone demo (drawing+text+filter+PNG round trip) @@ -94,7 +98,7 @@ pixelforge/ Install the [MoonBit toolchain](https://www.moonbitlang.com/download/) first. ```bash -moon test # run the 147 unit tests +moon test # run the 163 unit tests moon run cmd/main # native example (builds an image, runs filters, prints checksums) moon run cmd/ppm > edges.ppm # emit a Sobel edge-detected PPM image ``` @@ -164,7 +168,7 @@ let png_bytes = @pixelforge.png_encode(framed) | 21 | Otsu auto threshold | `otsu()` | — | | 22 | Floyd–Steinberg dither (mono) | `dither_mono()` | — | -> Size-changing transforms are library APIs rather than dispatch ids: `rotate90()`, `resize_nearest(w, h)`, `resize_bilinear(w, h)`. Likewise for multi-parameter APIs: `box_blur(radius)`, `flood_fill(x, y, color, tol)`, `distance_transform(t)`, `gaussian(radius)`, `unsharp_mask(radius, amount)`, `crop(x, y, w, h)`, `pad(l, t, r, b, color)`, `bilateral(radius, σs, σr)`, `dither_grayscale(levels)`/`dither_mono()`, `otsu_threshold()`, `label_components(t)`/`count_components(t)`, `composite(top, mode)`, `draw_text(...)`, `rotate(deg)`, `translate(dx, dy)`, `affine(t)`, the drawing primitives, `saturate(factor)`, `hue_rotate(deg)`, the morphology operators, `png_encode`/`png_decode`, `gif_decode`, `qoi_encode`/`qoi_decode`, `bmp_encode`/`bmp_decode` and the color-space functions. +> Size-changing transforms are library APIs rather than dispatch ids: `rotate90()`, `resize_nearest(w, h)`, `resize_bilinear(w, h)`, `resize_bicubic(w, h)`. Likewise for multi-parameter APIs: `average_hash()`/`difference_hash()`/`hamming_distance`, `add_gaussian_noise`/`add_salt_pepper`, `box_blur(radius)`, `flood_fill(x, y, color, tol)`, `distance_transform(t)`, `gaussian(radius)`, `unsharp_mask(radius, amount)`, `crop(x, y, w, h)`, `pad(l, t, r, b, color)`, `bilateral(radius, σs, σr)`, `dither_grayscale(levels)`/`dither_mono()`, `otsu_threshold()`, `label_components(t)`/`count_components(t)`, `composite(top, mode)`, `draw_text(...)`, `rotate(deg)`, `translate(dx, dy)`, `affine(t)`, the drawing primitives, `saturate(factor)`, `hue_rotate(deg)`, the morphology operators, `png_encode`/`png_decode`, `gif_decode`, `qoi_encode`/`qoi_decode`, `bmp_encode`/`bmp_decode` and the color-space functions. ## 🏗️ Architecture & backends @@ -182,7 +186,7 @@ moon test # default backend (wasm-gc) moon test --target js # js backend ``` -147 tests cover every filter, transform, drawing primitive, blend mode, the font, the analysis algorithms and all four codecs. Every expected value is derived by hand — impulse responses, flat-field invariance, known edges, histogram remapping, exact encoded byte lengths, lossless round trips, canonical CRC-32/Adler-32 check vectors and hand-assembled DEFLATE and GIF LZW bitstreams — and passes on both the wasm-gc and js backends, with GitHub Actions CI. +163 tests cover every filter, transform, drawing primitive, blend mode, the font, the analysis algorithms and all four codecs. Every expected value is derived by hand — impulse responses, flat-field invariance, known edges, histogram remapping, exact encoded byte lengths, lossless round trips, canonical CRC-32/Adler-32 check vectors and hand-assembled DEFLATE and GIF LZW bitstreams — and passes on both the wasm-gc and js backends, with GitHub Actions CI. ## 📮 Published on mooncakes.io diff --git a/README.md b/README.md index af0f891..046b297 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ ## ✨ 特性 -- **26 种滤镜与几何变换**:灰度、反色、亮度、对比度、高斯/盒式模糊、锐化、浮雕、拉普拉斯/Sobel/Scharr/Canny 边缘、棕褐色、二值化、像素化、中值降噪、直方图均衡、色调分离、伽马校正、暗角、饱和度、色相旋转、水平/垂直翻转;另有 90° 旋转与最近邻/双线性缩放。 +- **26 种滤镜与几何变换**:灰度、反色、亮度、对比度、高斯/盒式模糊、锐化、浮雕、拉普拉斯/Sobel/Scharr/Canny 边缘、棕褐色、二值化、像素化、中值降噪、直方图均衡、色调分离、伽马校正、暗角、饱和度、色相旋转、水平/垂直翻转;另有 90° 旋转与最近邻/双线性/双三次 (Catmull-Rom) 缩放。 - **形态学运算**:3×3 腐蚀 / 膨胀 / 开运算 / 闭运算。 - **图像编解码**:PNG(自实现完整 DEFLATE inflate + CRC-32/Adler-32 校验)、GIF 解码(变长 LZW、交错、透明索引)、QOI(完整规范,无损往返)与 BMP(无压缩 24/32 位)纯 MoonBit 实现。 - **仿射变换**:`Affine` 矩阵(旋转/平移/缩放/错切 + 复合 + 求逆),逆映射双线性采样;任意角度 `rotate(degrees)`。 @@ -28,7 +28,7 @@ - **锐化蒙版**:`unsharp_mask(radius, amount)` 复用高斯模糊提取高频细节并回叠,锐化边缘。 - **裁剪与填充**:`crop(x, y, w, h)`(自动限幅)与 `pad(l, t, r, b, color)`(颜色边框),`crop∘pad` 可无损往返。 - **双边滤波**:`bilateral(radius, σs, σr)` 保边平滑——平坦区域降噪,强边缘保持锐利。 -- **图像分析**:Otsu 自动阈值(类间方差最大化)、Floyd–Steinberg 误差扩散抖动、四连通连通域标记与计数、chamfer (3,4) 距离变换。 +- **图像分析**:Otsu 自动阈值(类间方差最大化)、Floyd–Steinberg 误差扩散抖动、四连通连通域标记与计数、chamfer (3,4) 距离变换、感知哈希(aHash/dHash + 汉明距离)。 - **积分图与 O(1) 盒式模糊**:`integral_image()` 求和面积表(Int64 防溢出)驱动 `box_blur(radius)`,任意半径每像素 O(1)。 - **泛洪填充**:`flood_fill(x, y, color, tolerance)` 四连通种子填充,逐通道容差。 - **图层合成**:`composite(top, mode)` Porter-Duff source-over + 8 种混合模式(正片叠底/滤色/叠加/变暗/变亮/差值/线性减淡等),纯整数舍入运算。 @@ -36,7 +36,8 @@ - **色彩空间**:RGB ↔ HSV、RGB ↔ YCbCr (BT.601) 精确往返转换。 - **通用卷积引擎**:`Kernel` + `Image::convolve`,可自定义任意奇数尺寸卷积核。 - **图像统计与色调**:`stats()` 逐通道 min/max/mean(Int64 累加)、`auto_contrast()` 自动对比度拉伸、`levels(black, white, gamma)` 色阶重映射。 -- **纯整数、确定性**:滤镜数学尽量用整数(如亮度权重 ×1000),结果可复现、**147 个单元测试全部手算验证**(含 CRC-32/Adler-32 公开参考向量与手工汇编的 DEFLATE 位流)。 +- **确定性噪声**:`add_gaussian_noise(seed, σ)` / `add_salt_pepper(seed, density)`,64 位 LCG 驱动,同 seed 跨后端逐字节一致。 +- **纯整数、确定性**:滤镜数学尽量用整数(如亮度权重 ×1000),结果可复现、**163 个单元测试全部手算验证**(含 CRC-32/Adler-32 公开参考向量与手工汇编的 DEFLATE 位流)。 - **零依赖**:只用 `moonbitlang/core`,不引入任何第三方库。 - **多后端 + 零拷贝互操作**:js 后端下 `FixedArray[Byte]` 就是 `Uint8Array`,与 canvas 的 `Uint8ClampedArray` 零拷贝互通;线性内存 wasm 后端导出 `memory`,宿主直接批量读写像素。 - **浏览器 Playground**:拖拽 / 粘贴 / 上传图片,滤镜可叠加成管线,JS/WASM 引擎切换与性能对比,可切换到 **Web Worker 后台线程**处理大图不卡 UI,处理结果用**自家 `png_encode`** 一键下载 PNG。 @@ -62,6 +63,9 @@ pixelforge/ ├── floodfill.mbt # 泛洪填充(四连通种子填充) ├── distance.mbt # chamfer (3,4) 距离变换 ├── stats.mbt # 图像统计 / 自动对比度 / 色阶 +├── bicubic.mbt # 双三次缩放(Catmull-Rom) +├── phash.mbt # 感知哈希(aHash/dHash + 汉明距离) +├── noise.mbt # 确定性噪声(高斯 / 椒盐,LCG) ├── bilateral.mbt # 双边滤波(保边平滑) ├── otsu.mbt # Otsu 自动阈值(类间方差最大化) ├── dither.mbt # Floyd–Steinberg 误差扩散抖动 @@ -75,7 +79,7 @@ pixelforge/ ├── transform.mbt # 水平/垂直翻转、90° 旋转 ├── resize.mbt # 最近邻/双线性缩放 ├── dispatch.mbt # Image::apply_filter_id 统一派发(各绑定共用) -├── *_test.mbt # 147 个确定性测试(黑盒 + 白盒) +├── *_test.mbt # 163 个确定性测试(黑盒 + 白盒) ├── cmd/main/ # 原生 CLI 示例(moon run cmd/main) ├── cmd/ppm/ # PPM 图像输出示例(moon run cmd/ppm > edges.ppm) ├── cmd/showcase/ # 综合展示(绘图+文字+滤镜+PNG 往返自检) @@ -93,7 +97,7 @@ pixelforge/ 先安装 [MoonBit 工具链](https://www.moonbitlang.cn/download/)。 ```bash -moon test # 运行 147 个单元测试 +moon test # 运行 163 个单元测试 moon run cmd/main # 运行原生示例(生成图像并跑滤镜,打印校验和) moon run cmd/showcase > showcase.ppm # 综合展示:绘图+文字+滤镜+PNG 往返自检 moon run cmd/ppm > edges.ppm # 生成一张 Sobel 边缘检测的 PPM 图片 @@ -162,7 +166,7 @@ let bytes = out.data // FixedArray[Byte],长度 = width*height*4 | 21 | Otsu 自动阈值 | `otsu()` | — | | 22 | Floyd–Steinberg 抖动(二值) | `dither_mono()` | — | -> 会改变尺寸的变换不走 id 派发,直接调用库 API:`rotate90()`、`resize_nearest(w, h)`、`resize_bilinear(w, h)`。多参数 / 非图像→图像的 API 同理:`box_blur(radius)`、`flood_fill(x, y, color, tol)`、`distance_transform(t)`、`gaussian(radius)`、`unsharp_mask(radius, amount)`、`crop(x, y, w, h)`、`pad(l, t, r, b, color)`、`bilateral(radius, σs, σr)`、`dither_grayscale(levels)`/`dither_mono()`、`otsu_threshold()`、`label_components(t)`/`count_components(t)`、`composite(top, mode)`、`draw_text(...)`、`rotate(deg)`、`translate(dx, dy)`、`affine(t)`、`draw_line`/`draw_rect`/`draw_circle` 等绘图原语、`saturate(factor)`、`hue_rotate(deg)`、`erode()`/`dilate()`/`morph_open()`/`morph_close()`、`png_encode`/`png_decode`、`gif_decode`、`qoi_encode`/`qoi_decode`、`bmp_encode`/`bmp_decode`、`rgb_to_hsv` 等色彩空间函数。 +> 会改变尺寸的变换不走 id 派发,直接调用库 API:`rotate90()`、`resize_nearest(w, h)`、`resize_bilinear(w, h)`、`resize_bicubic(w, h)`。多参数 / 非图像→图像的 API 同理:`average_hash()`/`difference_hash()`/`hamming_distance`、`add_gaussian_noise`/`add_salt_pepper`、`box_blur(radius)`、`flood_fill(x, y, color, tol)`、`distance_transform(t)`、`gaussian(radius)`、`unsharp_mask(radius, amount)`、`crop(x, y, w, h)`、`pad(l, t, r, b, color)`、`bilateral(radius, σs, σr)`、`dither_grayscale(levels)`/`dither_mono()`、`otsu_threshold()`、`label_components(t)`/`count_components(t)`、`composite(top, mode)`、`draw_text(...)`、`rotate(deg)`、`translate(dx, dy)`、`affine(t)`、`draw_line`/`draw_rect`/`draw_circle` 等绘图原语、`saturate(factor)`、`hue_rotate(deg)`、`erode()`/`dilate()`/`morph_open()`/`morph_close()`、`png_encode`/`png_decode`、`gif_decode`、`qoi_encode`/`qoi_decode`、`bmp_encode`/`bmp_decode`、`rgb_to_hsv` 等色彩空间函数。 ## 🏗️ 架构与多后端 @@ -180,7 +184,7 @@ moon test # 默认后端(wasm-gc) moon test --target js # js 后端 ``` -147 个测试覆盖每个滤镜、变换、绘图原语、合成模式、字体、分析算法与编解码器,期望值均为手工推导(脉冲响应、平场不变性、已知边缘、直方图重映射、编码字节精确长度、无损往返、CRC-32/Adler-32 公开参考向量、手工汇编的 DEFLATE 与 GIF LZW 位流等),在 wasm-gc 与 js 后端下均通过;GitHub Actions 持续集成。 +163 个测试覆盖每个滤镜、变换、绘图原语、合成模式、字体、分析算法与编解码器,期望值均为手工推导(脉冲响应、平场不变性、已知边缘、直方图重映射、编码字节精确长度、无损往返、CRC-32/Adler-32 公开参考向量、手工汇编的 DEFLATE 与 GIF LZW 位流等),在 wasm-gc 与 js 后端下均通过;GitHub Actions 持续集成。 ## 📮 发布到 mooncakes.io diff --git a/moon.mod b/moon.mod index 37ab930..246e6a3 100644 --- a/moon.mod +++ b/moon.mod @@ -1,6 +1,6 @@ name = "0717lee/pixelforge" -version = "0.11.0" +version = "0.12.0" readme = "README.md"