A zero-FFI, cross-platform image-processing library for MoonBit.
Millow — M (for MoonBit) + illow (a nod to Python's Pillow).
| Input | to_grayscale | tint(100,150,200) | gaussian_blur(σ=2) |
|---|---|---|---|
| sharpen(1.0) | sobel | equalize_histogram | threshold_otsu |
|---|---|---|---|
| rotate_any(45°) | find_contours | pipeline |
|---|---|---|
moon run cmd/maincd examples
moon run .millow/
├── src/ # implementation package (megemini/millow/src)
├── millow.mbt # root facade: re-exports the public API (megemini/millow)
├── test/ # blackbox test package exercising the public API
├── test_alignment/ # alignment tests against Python (skimage/Pillow) reference
├── cmd/main/ # lightweight synthetic-image demo (millow-only)
└── examples/ # standalone full demo (PNG/JPEG I/O via mizchi/image)moon add megemini/millowimport {
"megemini/millow" @millow,
}///|
test "build, transform and inspect an image" {
// A 64×64 canvas with a filled rectangle drawn on it.
let base = Image::from_pixel(64, 64, 30, 60, 90, 255)
let canvas = draw_rect(base, 8, 8, 40, 40, 220, 40, 40, 255, true, 1)
// Grayscale → blur → edges.
let gray = to_grayscale(canvas)
let blurred = gaussian_blur(gray, 1.5)
let edges = sobel(blurred)
assert_eq(edges.shape(), (64, 64))
// Otsu adaptive threshold.
let (_, binary) = threshold_otsu(blurred)
assert_eq(binary.shape(), (64, 64))
// Downscale and serialize to PPM.
let thumb = resize(canvas, 16, 16, Nearest)
let ppm = to_ppm(thumb)
assert_eq(ppm[0], 'P'.to_int().to_byte())
}In the examples above the API is called unqualified because they run inside the millow package itself. From another module, prefix each name with the import alias, e.g. @millow.to_grayscale(img).
///|
test "augment_pipeline example" {
let img = Image::from_pixel(64, 64, 30, 60, 90, 255)
let out = augment_pipeline(img, [
FlipHorizontal,
Rotate(15.0),
Brightness(1.2),
Contrast(1.3),
NoiseGaussian(8.0),
])
assert_true(out.h > 0 && out.w > 0)
}///|
test "augment_random_choice example" {
let img = Image::from_pixel(64, 64, 30, 60, 90, 255)
let out = augment_random_choice(img, [
(0.4, FlipVertical),
(0.4, Gamma(0.8)),
(0.2, ColorJitter(0.2, 0.2, 0.0, 0.0)),
])
assert_eq(out.shape(), img.shape())
}x' = a*x + b*y + c
y' = d*x + e*y + fmoon test # run every test
moon test --target native # pick a backend
moon run cmd/main # run the synthetic demo (no external deps)
cd examples && moon run . # run the full demo with JPEG I/Osource $HOME/venv310/bin/activate
python test_alignment/generate_fixtures.py
moon testfn affine_transform(img : Image, matrix : Array[Double], dst_h : Int, dst_w : Int, interp : Interp, mode? : BorderMode) -> Imagefn clamp_byte(v : Int) -> Bytefn clampd(v : Double, lo : Double, hi : Double) -> Doublefn clampi(v : Int, lo : Int, hi : Int) -> Intfn resize_to_cover(img : Image, min_h : Int, min_w : Int, interp : Interp) -> Image raise ImageErrorfn round_byte(v : Double) -> ByteA zero-FFI, cross-platform image-processing library for MoonBit.