From c598d54753c4d92ff1a0bfa50c91f7e2f861e38d Mon Sep 17 00:00:00 2001 From: Li Fengmin <2080291162@qq.com> Date: Fri, 31 Jul 2026 19:56:24 +0800 Subject: [PATCH] chore: release 0.13.0 - histogram API, HSL, playground histogram panel --- CHANGELOG.md | 11 +++++++++++ README.en.md | 15 +++++++++------ README.md | 15 +++++++++------ moon.mod | 2 +- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14740e9..9c8b833 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 0.13.0 (2026-07-31) + +### 新增 +- 直方图 API:`histogram_luma()`(复用 Otsu 的 256 桶 BT.601 分桶)与 `histogram_rgb()`(逐通道) +- HSL 色彩空间:`rgb_to_hsl` / `hsl_to_rgb`(与 HSV 风格一致、精确 8 位往返)与 `adjust_lightness(delta)`(保色相明暗调整) +- Playground:新增实时亮度直方图面板(经 `luma_histogram` js 绑定,每次渲染后更新) +- `cmd/showcase`:扩展“噪声 → 中值降噪 → 感知哈希”分析自检(受控平坦色块,median 必然降噪) + +### 变更 +- 单元测试从 163 个增加到 172 个 + ## 0.12.0 (2026-07-31) ### 新增 diff --git a/README.en.md b/README.en.md index 00ec0a9..4f7ba58 100644 --- a/README.en.md +++ b/README.en.md @@ -33,11 +33,12 @@ English | [简体中文](README.md) - **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. - **Bitmap text**: built-in 5×7 font (digits, uppercase letters, basic punctuation), `draw_text` with integer scaling and clipping. -- **Color spaces**: exact round-trip RGB ↔ HSV and RGB ↔ YCbCr (BT.601) conversions. +- **Color spaces**: exact round-trip RGB ↔ HSV, RGB ↔ HSL (with `adjust_lightness`) and RGB ↔ YCbCr (BT.601) conversions. +- **Histograms**: `histogram_luma()` / `histogram_rgb()` 256-bin counts; the playground has a live luma histogram panel. - **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. - **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). +- **Integer-first, deterministic**: filter math sticks to integers where possible (e.g. luma weights ×1000); results are reproducible and **all 172 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`**. @@ -66,6 +67,8 @@ pixelforge/ ├── bicubic.mbt # bicubic resize (Catmull-Rom) ├── phash.mbt # perceptual hashes (aHash/dHash + Hamming) ├── noise.mbt # deterministic noise (gaussian / salt-pepper) +├── hsl.mbt # HSL color space + lightness adjust +├── histogram.mbt # histogram API (luma / RGB) ├── bilateral.mbt # bilateral filter (edge-preserving) ├── otsu.mbt # Otsu automatic threshold ├── dither.mbt # Floyd–Steinberg error diffusion @@ -79,7 +82,7 @@ pixelforge/ ├── transform.mbt # flips, 90° rotation ├── resize.mbt # nearest/bilinear resize ├── dispatch.mbt # Image::apply_filter_id shared dispatch table -├── *_test.mbt # 163 deterministic tests (blackbox + whitebox) +├── *_test.mbt # 172 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) @@ -98,7 +101,7 @@ pixelforge/ Install the [MoonBit toolchain](https://www.moonbitlang.com/download/) first. ```bash -moon test # run the 163 unit tests +moon test # run the 172 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 ``` @@ -168,7 +171,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)`, `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. +> 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`, `histogram_luma()`/`histogram_rgb()`, `rgb_to_hsl`/`hsl_to_rgb`/`adjust_lightness`, `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 @@ -186,7 +189,7 @@ moon test # default backend (wasm-gc) moon test --target js # js backend ``` -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. +172 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 046b297..846aa39 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,12 @@ - **泛洪填充**:`flood_fill(x, y, color, tolerance)` 四连通种子填充,逐通道容差。 - **图层合成**:`composite(top, mode)` Porter-Duff source-over + 8 种混合模式(正片叠底/滤色/叠加/变暗/变亮/差值/线性减淡等),纯整数舍入运算。 - **位图文字**:内置 5×7 字体(数字/大写字母/基本标点),`draw_text` 整数倍缩放、自动裁剪。 -- **色彩空间**:RGB ↔ HSV、RGB ↔ YCbCr (BT.601) 精确往返转换。 +- **色彩空间**:RGB ↔ HSV、RGB ↔ HSL(含 `adjust_lightness`)、RGB ↔ YCbCr (BT.601) 精确往返转换。 +- **直方图**:`histogram_luma()` / `histogram_rgb()` 256 桶统计;Playground 内置实时亮度直方图面板。 - **通用卷积引擎**:`Kernel` + `Image::convolve`,可自定义任意奇数尺寸卷积核。 - **图像统计与色调**:`stats()` 逐通道 min/max/mean(Int64 累加)、`auto_contrast()` 自动对比度拉伸、`levels(black, white, gamma)` 色阶重映射。 - **确定性噪声**:`add_gaussian_noise(seed, σ)` / `add_salt_pepper(seed, density)`,64 位 LCG 驱动,同 seed 跨后端逐字节一致。 -- **纯整数、确定性**:滤镜数学尽量用整数(如亮度权重 ×1000),结果可复现、**163 个单元测试全部手算验证**(含 CRC-32/Adler-32 公开参考向量与手工汇编的 DEFLATE 位流)。 +- **纯整数、确定性**:滤镜数学尽量用整数(如亮度权重 ×1000),结果可复现、**172 个单元测试全部手算验证**(含 CRC-32/Adler-32 公开参考向量与手工汇编的 DEFLATE 位流)。 - **零依赖**:只用 `moonbitlang/core`,不引入任何第三方库。 - **多后端 + 零拷贝互操作**:js 后端下 `FixedArray[Byte]` 就是 `Uint8Array`,与 canvas 的 `Uint8ClampedArray` 零拷贝互通;线性内存 wasm 后端导出 `memory`,宿主直接批量读写像素。 - **浏览器 Playground**:拖拽 / 粘贴 / 上传图片,滤镜可叠加成管线,JS/WASM 引擎切换与性能对比,可切换到 **Web Worker 后台线程**处理大图不卡 UI,处理结果用**自家 `png_encode`** 一键下载 PNG。 @@ -66,6 +67,8 @@ pixelforge/ ├── bicubic.mbt # 双三次缩放(Catmull-Rom) ├── phash.mbt # 感知哈希(aHash/dHash + 汉明距离) ├── noise.mbt # 确定性噪声(高斯 / 椒盐,LCG) +├── hsl.mbt # HSL 色彩空间 + 亮度调整 +├── histogram.mbt # 直方图 API(亮度 / RGB) ├── bilateral.mbt # 双边滤波(保边平滑) ├── otsu.mbt # Otsu 自动阈值(类间方差最大化) ├── dither.mbt # Floyd–Steinberg 误差扩散抖动 @@ -79,7 +82,7 @@ pixelforge/ ├── transform.mbt # 水平/垂直翻转、90° 旋转 ├── resize.mbt # 最近邻/双线性缩放 ├── dispatch.mbt # Image::apply_filter_id 统一派发(各绑定共用) -├── *_test.mbt # 163 个确定性测试(黑盒 + 白盒) +├── *_test.mbt # 172 个确定性测试(黑盒 + 白盒) ├── cmd/main/ # 原生 CLI 示例(moon run cmd/main) ├── cmd/ppm/ # PPM 图像输出示例(moon run cmd/ppm > edges.ppm) ├── cmd/showcase/ # 综合展示(绘图+文字+滤镜+PNG 往返自检) @@ -97,7 +100,7 @@ pixelforge/ 先安装 [MoonBit 工具链](https://www.moonbitlang.cn/download/)。 ```bash -moon test # 运行 163 个单元测试 +moon test # 运行 172 个单元测试 moon run cmd/main # 运行原生示例(生成图像并跑滤镜,打印校验和) moon run cmd/showcase > showcase.ppm # 综合展示:绘图+文字+滤镜+PNG 往返自检 moon run cmd/ppm > edges.ppm # 生成一张 Sobel 边缘检测的 PPM 图片 @@ -166,7 +169,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)`、`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` 等色彩空间函数。 +> 会改变尺寸的变换不走 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`、`histogram_luma()`/`histogram_rgb()`、`rgb_to_hsl`/`hsl_to_rgb`/`adjust_lightness`、`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` 等色彩空间函数。 ## 🏗️ 架构与多后端 @@ -184,7 +187,7 @@ moon test # 默认后端(wasm-gc) moon test --target js # js 后端 ``` -163 个测试覆盖每个滤镜、变换、绘图原语、合成模式、字体、分析算法与编解码器,期望值均为手工推导(脉冲响应、平场不变性、已知边缘、直方图重映射、编码字节精确长度、无损往返、CRC-32/Adler-32 公开参考向量、手工汇编的 DEFLATE 与 GIF LZW 位流等),在 wasm-gc 与 js 后端下均通过;GitHub Actions 持续集成。 +172 个测试覆盖每个滤镜、变换、绘图原语、合成模式、字体、分析算法与编解码器,期望值均为手工推导(脉冲响应、平场不变性、已知边缘、直方图重映射、编码字节精确长度、无损往返、CRC-32/Adler-32 公开参考向量、手工汇编的 DEFLATE 与 GIF LZW 位流等),在 wasm-gc 与 js 后端下均通过;GitHub Actions 持续集成。 ## 📮 发布到 mooncakes.io diff --git a/moon.mod b/moon.mod index 246e6a3..149a4ab 100644 --- a/moon.mod +++ b/moon.mod @@ -1,6 +1,6 @@ name = "0717lee/pixelforge" -version = "0.12.0" +version = "0.13.0" readme = "README.md"