Skip to content

Repository files navigation

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.

About

Image Converter Ultra

Topics

Resources

Contributing

Stars

18 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages