Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)

### 新增
Expand Down
15 changes: 9 additions & 6 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`**.
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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
```
Expand Down Expand Up @@ -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

Expand All @@ -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

Expand Down
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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。
Expand Down Expand Up @@ -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 误差扩散抖动
Expand All @@ -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 往返自检)
Expand All @@ -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 图片
Expand Down Expand Up @@ -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` 等色彩空间函数。

## 🏗️ 架构与多后端

Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion moon.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "0717lee/pixelforge"

version = "0.12.0"
version = "0.13.0"

readme = "README.md"

Expand Down
Loading