icu_tool

Install v0.11.1

Published on Sep 18 2026 at 09:46 UTC
View all installation options
View all installation options

ICU icon

ICU

Image Converter Ultra

A Rust toolkit for inspecting, previewing, and converting images and fonts.

CI Crates.io version icu_lib version License: MIT Rust 1.85+

Installation · CLI · Viewer · Library

ICU image viewer

Image Converter Ultra (ICU) provides a native command-line interface, an egui desktop viewer, a WebAssembly viewer, and the reusable icu_lib crate.

Features

  • Decode, inspect, preview, and convert common raster image formats.
  • Read and write LVGL v8/v9 image data with configurable color format, stride, dithering, and compression.
  • Read and write MIRX flat images and inspect MIRX vector, indexed-image, and font chunks.
  • Import and export SVG scene data.
  • Inspect TTF, OTF, and TTC fonts and individual glyph outlines; WOFF and WOFF2 signatures are recognized for format detection.
  • Bake TTF/OTF glyphs into MIRX SDF or grayscale font atlases.
  • Merge multiple MIRX font files into one bundle.
  • Compare images and glyphs in the desktop and web viewer.
  • Generate shell completion scripts for Bash, Zsh, Fish, Elvish, and PowerShell.

Installation

Homebrew

brew install W-Mai/homebrew-cellar/icu_tool

Alternatively, add the tap first:

brew tap W-Mai/homebrew-cellar
brew install icu_tool

Shell installer

curl -fsSL https://i.to01.icu/install.sh | sh

PowerShell installer

powershell -c "irm https://github.com/W-Mai/icu/releases/latest/download/icu_tool-installer.ps1 | iex"

Windows MSI

Download the latest MSI installer from the releases page.

Cargo

cargo install icu_tool

The installed executable is named icu.

Command-line interface

Run icu --help or icu <command> --help for the complete, version-specific option list.

Command Purpose
icu info <FILE> Print detected file metadata as YAML.
icu show [FILES]... Open the native viewer. With no files, it opens an empty viewer.
icu convert <INPUTS>... -F <FORMAT> Convert files or a directory to another format.
icu encode-frames <INPUT> -O <OUTPUT> Encode an animated GIF, APNG, or WebP as a MIRX FRAMES timeline.
icu bake-font <TTF> Bake a TTF/OTF font into a MIRX SDF or grayscale atlas.
icu merge-fonts <INPUTS>... -O <OUTPUT> Merge MIRX font files into one multi-font bundle.

Increase log verbosity with -v, -vv, or -vvv before the subcommand.

Inspect and preview

ICU auto-detects supported input formats by default.

icu info res/img_0.png
icu show res/img_0.png res/img_0.bin

Use --input-format common or --input-format lvgl-v9 only when automatic detection is not appropriate.

Convert images

Convert one or more files:

icu convert res/img_0.png res/img_0.jpeg -F webp

Convert a directory recursively while preserving its relative directory structure:

icu convert res -O output -F jpeg -r

Important conversion options include:

  • -F, --output-format: png, apng, jpeg, bmp, gif, tiff, webp, ico, pbm, pgm, ppm, pam, lvgl, or mirx.
  • -O, --output-folder: write output under a different directory.
  • -r, --override-output: replace existing output files.
  • -C, --output-color-format: select an LVGL or MIRX pixel format.
  • -S, --output-stride-align: align output rows; the default is 1.
  • --dither: set indexed-color quantization from 1 to 30.
  • --output-compressed-method: select none, rle, or LVGL v9 raw-block lz4 compression.
  • --lvgl-version: select LVGL v8 or v9; the default is v9.
  • --png-mode: select rgba, rgb, preserve, indexed1, indexed2, indexed4, or indexed8; the default is rgba.
  • --png-compression: select fast, balanced, or best; the default is balanced.
  • --quality: set JPEG quality from 1 to 100; the default is 85.
  • --background: set the JPEG alpha-flattening color as #RRGGBB; the default is white.
  • --stdout: write one converted result to standard output.

LVGL output requires an explicit color format:

icu convert res/img_0.png -O output -F lvgl -C i8 --lvgl-version v9

Compress an LVGL v9 image with the raw-block LZ4 format used by LVGL:

icu convert res/img_0.png -O output -F lvgl -C i8 \
  --lvgl-version v9 --output-compressed-method lz4

LZ4 compression is available for LVGL v9. The payload uses an LVGL 12-byte compression header followed by a raw LZ4 block; LZ4 frame files are not used. ICU also decodes LVGL v9 LZ4 images produced by LVGL's image tooling.

MIRX flat-image output accepts rgb565, rgb565-swapped, rgb888, rgba8888, bgra8888, and xrgb8888 pixel formats:

icu convert res/img_0.png -O output -F mirx -C rgba8888

MIRX chunk-image output supports native pixel, RLE, LZ4, reversible frequency, and quantized frequency coding. Frequency coding accepts rgb888, rgba8888, bgra8888, and i8; quantized output keeps alpha and indexes exact. --mirx-quality is valid only with frequency-quantized and defaults to 75.

icu convert res/img_0.png -O output -F mirx -C rgba8888 --mirx-coding frequency-reversible
icu convert res/img_0.png -O output -F mirx -C rgba8888 --mirx-coding frequency-quantized --mirx-quality 75

Encode a complete animation timeline while retaining source frame timing:

icu encode-frames motion.webp -O motion.mirx --format rgba8888 --input-align 64

MIRX FRAMES output compares RAW, native pixel, RLE, LZ4, reversible frequency, frame residual, omitted-frame, and sparse-tile representations by their complete stored size. --quality 1..100 explicitly admits quantized frequency candidates; without it, every selected representation is lossless. --max-delta-frames bounds recovery work, --tile WIDTHxHEIGHT controls sparse regions, and --tile none disables them. --input-align aligns encoded DATA addresses independently from the runtime output stride and address requirements.

A zero source-frame duration uses --default-duration; positive durations are converted to --timebase ticks and remain at least one tick. --play-count 0 means unbounded repetition.

The Viewer imports animated WebP and exports multi-frame sources or workspace groups as lossless animated WebP. The same pure-Rust path is used on native and WebAssembly builds. CLI convert processes WebP inputs as static files, while encode-frames preserves an animated timeline.

--output-category c-array is reserved by the CLI but is not implemented.

Bake and merge fonts

Bake an SDF atlas from an inline character set:

icu bake-font path/to/font.ttf \
  --charset "Hello 世界" \
  --size 32 \
  --bit-depth 8 \
  --min-ppem 16 \
  --max-ppem 64 \
  --format sdf \
  -O output

Use --charset-file <FILE> to read the character set from a UTF-8 text file. SDF atlases use 8-bit samples; grayscale atlases accept 1, 2, 4, and 8. --min-ppem and --max-ppem define the representation's selection range.

Merge multiple baked font files:

icu merge-fonts output/latin_sdf_32.mirx output/cjk_sdf_32.mirx \
  -O output/fonts.mirx

Shell completion

Add the matching command to the shell startup file.

# Bash
source <(icu -I bash)

# Zsh
eval "$(icu -I zsh)"

# Fish
icu -I fish | source

PowerShell and Elvish are also supported; run icu -I <shell> to emit the completion script.

Viewer

The viewer is implemented with egui/eframe and runs as a native application or in a browser. It supports drag-and-drop and file selection, raster and animated-image preview, image diffing, MIRX scene inspection, indexed-image inspection, font atlas and glyph-grid views, glyph outline inspection, and font comparison.

Open the native viewer with:

icu show

The WebAssembly build starts the same viewer without the native CLI layer.

Viewer export uses two explicit actions:

  • Convert exports the selected logical source to one file. Native builds show an editable save-file dialog; WebAssembly starts one browser download.
  • Convert All expands selected entries, Groups, and animation frames. Native builds write into a selected output directory; WebAssembly downloads one ZIP archive while preserving relative paths.

Native file and folder inputs are recursively enumerated in stable path order. WebAssembly supports multi-file and directory selection, preserves browser-provided relative paths, and recursively reads dropped directories when the browser exposes a directory-entry or file-system-handle API. APNG output is available only for multi-frame sources; a static source is rejected instead of producing a still PNG with an .apng suffix.

Build from source

The repository pins its Rust toolchain in rust-toolchain.toml.

git clone https://github.com/W-Mai/icu.git
cd icu
cargo build --release

The native executable is written to target/release/icu on Unix-like systems or target/release/icu.exe on Windows.

WebAssembly

Install the target and Trunk, then build the web application:

rustup target add wasm32-unknown-unknown
cargo install trunk
trunk build --release

Use trunk serve for local development.

Library

Add the reusable library crate with:

cargo add icu_lib

The library converts external formats through the shared MiData model:

input bytes -> EnDecoder::decode -> MiData -> EnDecoder::encode -> output bytes

MiData represents RGBA images, grayscale images, vector scenes, fonts, and indexed images. Animation timelines use endecoder::common::animation; MIRX FRAMES authoring uses endecoder::mirui::frames. Format-specific implementations live under icu_lib/src/endecoder, while icu_lib/src/midata defines the static intermediate model. See icu_lib/README.md for library examples.

Repository layout

src/                    Native CLI and egui/eframe viewer
icu_lib/                Reusable encoders, decoders, and intermediate data
locales/                English and Simplified Chinese UI translations
assets/                 Fonts and web assets
res/                    Sample conversion inputs
.github/workflows/      Release, website, and WebAssembly automation

Development conventions and the required quality gate are documented in CONTRIBUTING.md.

License

ICU is available under the MIT License.