Skip to content

muhammad1438/pixelateR

Repository files navigation

PixelateR Logo PixelateR Logo

PixelateR

Rust License: MIT WebAssembly

A high-performance image and video pixelation tool written in Rust with WebAssembly support. Transform images and videos into pixel art with customizable palettes, dithering algorithms, and edge detection.

Example

Original (6000×4000) Pixelated (6000×4000) - Floyd-Steinberg, Pico8, Factor 4
Norway Original Norway Pixelated

📸 View Full Gallery - See more examples with different dithering algorithms

Features

🎨 Advanced Pixelation

  • Multiple Dithering Algorithms: Bayer (ordered), Floyd-Steinberg (error diffusion), Riemersma (Hilbert curve)
  • Color Palettes: Pico8 (16 colors), custom palettes, or automatic quantization
  • Edge Detection: Sobel-based downsampling for detail preservation
  • Configurable Parameters: Factor, depth, alpha blending, upscaling

🖼️ Image Processing

  • CLI tool with extensive options
  • Batch processing support
  • PNG output with transparency support
  • Adjustable brightness and contrast

🎬 Video Processing

  • Full video conversion to pixel art
  • FFmpeg integration for frame extraction and encoding
  • Progress tracking for long videos
  • H.264 output with configurable quality

🌐 Web Interface

  • Interactive browser-based editor
  • Real-time preview
  • Undo/redo history (up to 50 states)
  • Material Design 3 UI
  • WebAssembly-powered processing
  • Drag-and-drop image loading

Try it live: Start the web server and open http://localhost:8080

cd web-serve
npm install
npm start

See WEB_GUI_USAGE.md for detailed usage guide.

Installation

Prerequisites

For CLI Tool

  • Rust 1.70 or newer
  • Cargo (comes with Rust)

For Video Processing

  • FFmpeg (for video frame extraction and encoding)
# Ubuntu/Debian
sudo apt install ffmpeg

# macOS
brew install ffmpeg

# Windows
# Download from https://ffmpeg.org/download.html

For Web Interface

  • Node.js 16+ and npm
  • wasm-pack
# Install wasm-pack
cargo install wasm-pack

Build from Source

# Clone the repository
git clone https://github.com/muhammad1438/pixelateR.git
cd pixelateR

# Build CLI tool (release mode)
cargo build --release

# The binary will be at: ./target/release/pixelate_r

Build Web Interface

# Build WASM module
cd wasm
wasm-pack build --target web --release
cd ..

# Install and build web frontend
cd web
npm install
npm run build
cd ..

# Serve the web interface
cd web-serve
npm install
npm start
# Open http://localhost:8080

Usage

CLI Tool

Basic Image Pixelation

# Simple pixelation with Pico8 palette
./target/release/pixelate_r input.png output.png \
  --palette pico8 \
  --dither bayer \
  --factor 6

# Floyd-Steinberg dithering with upscaling
./target/release/pixelate_r input.png output.png \
  --palette pico8 \
  --dither floyd \
  --factor 6 \
  --upscale 6,6

# Custom settings with Sobel edge detection
./target/release/pixelate_r input.png output.png \
  --palette pico8 \
  --dither floyd \
  --factor 1 \
  --depth 1 \
  --sobel 2 \
  --alpha 0.65

Command-Line Options

Options:
  -p, --palette <PALETTE>      Color palette (pico8, or custom)
  -d, --dither <DITHER>        Dithering algorithm (bayer, floyd, riemersma)
  -f, --factor <FACTOR>        Downsampling factor (default: 6)
      --depth <DEPTH>          Downsampling iterations (default: 0)
      --sobel <SIZE>           Sobel kernel size for edge detection (2-5)
      --alpha <ALPHA>          Alpha blending (0.0-1.0, default: 0.5)
      --upscale <W,H>          Upscale dimensions (e.g., "6,6")
      --brightness <VALUE>     Brightness adjustment (-100 to 100)
      --contrast <VALUE>       Contrast adjustment (-100 to 100)
      --quiet                  Suppress progress output
  -h, --help                   Print help

Video Processing

# Extract frames from video
mkdir -p /tmp/pixelate-video
ffmpeg -i input.mp4 -vf "scale=640:360" /tmp/pixelate-video/frame_%05d.png

# Process all frames
mkdir -p /tmp/pixelate-output
for f in /tmp/pixelate-video/frame_*.png; do
  out="/tmp/pixelate-output/$(basename "$f")"
  ./target/release/pixelate_r "$f" "$out" \
    --palette pico8 \
    --dither floyd \
    --factor 6 \
    --upscale 6,6 \
    --depth 0 \
    --quiet
done

# Reassemble video
ffmpeg -framerate 24 -i /tmp/pixelate-output/frame_%05d.png \
  -c:v libx264 -preset medium -crf 18 -pix_fmt yuv420p \
  output-pixelated.mp4

See docs/VIDEO_PROCESSING_APPROACH.md for detailed video processing guide.

Web Interface

  1. Start the web server:
cd web-serve
npm start
  1. Open http://localhost:8080 in your browser

  2. Drag and drop an image or use the file picker

  3. Adjust settings:

    • Palette: Choose Pico8 or other palettes
    • Dither: Select dithering algorithm
    • Factor: Adjust pixelation level
    • Sobel: Enable edge detection
    • Brightness/Contrast: Fine-tune appearance
  4. Click "Transform" to apply changes

  5. Use undo/redo buttons to navigate history

  6. Right-click the canvas and "Save image as..." to download

Examples

Example Outputs

Original Bayer Dithering Floyd-Steinberg
Original Bayer Floyd

Video Examples

Sample videos are available in examples/output/:

  • big-buck-bunny-pixelated-full.mp4 - Bayer dithering, 636×360
  • big-buck-bunny-floyd-pico8.mp4 - Floyd-Steinberg, 636×360
  • big-buck-bunny-custom.mp4 - Custom settings, 320×180

Note: These files are large (122-245MB) and excluded from git via .gitignore.

Technical Details

Architecture

%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#7C3AED','primaryTextColor':'#fff','primaryBorderColor':'#5B21B6','lineColor':'#6B7280','secondaryColor':'#10B981','tertiaryColor':'#F59E0B'}}}%%
graph TB
    subgraph "Input Layer"
        IMG[Image File]
        VID[Video File]
        WEB[Web Upload]
    end

    subgraph "CLI Tool"
        CLI[CLI Parser<br/>src/cli/]
        LOAD[Image Loader<br/>src/image/]
    end

    subgraph "Core Processing"
        DOWN[Sobel Downsampling<br/>src/filter/sobel.rs]
        PAL[Palette Selection<br/>src/color/palette.rs]
        QUANT[Color Quantization<br/>src/color/quantize.rs]
        DITH[Dithering<br/>src/dither/]
        FILT[Filters<br/>src/filter/]
    end

    subgraph "Output Layer"
        SAVE[Save Image<br/>PNG/JPG]
        VIDEO[FFmpeg Encode<br/>MP4]
        CANVAS[Canvas Display]
    end

    subgraph "Web Interface"
        WASM[WASM Bindings<br/>wasm/src/lib.rs]
        TS[TypeScript UI<br/>web/src/main.ts]
    end

    IMG --> CLI
    VID --> CLI
    WEB --> TS

    CLI --> LOAD
    TS --> WASM

    LOAD --> DOWN
    WASM --> DOWN

    DOWN --> PAL
    PAL --> QUANT
    QUANT --> DITH
    DITH --> FILT

    FILT --> SAVE
    FILT --> VIDEO
    FILT --> CANVAS

    style DOWN fill:#7C3AED,stroke:#5B21B6,stroke-width:2px,color:#fff
    style DITH fill:#7C3AED,stroke:#5B21B6,stroke-width:2px,color:#fff
    style WASM fill:#10B981,stroke:#059669,stroke-width:2px,color:#fff
    style TS fill:#10B981,stroke:#059669,stroke-width:2px,color:#fff
Loading

Processing Pipeline

sequenceDiagram
    participant User
    participant CLI
    participant Loader
    participant Sobel
    participant Palette
    participant Dither
    participant Output

    User->>CLI: pixelate_r input.png --palette pico8 --dither floyd
    CLI->>Loader: Load image
    Loader-->>CLI: RGB/RGBA ImageData

    CLI->>Sobel: Downsample with edge detection
    Note over Sobel: factor=6, depth=0<br/>sobel kernel=3x3
    Sobel-->>CLI: Downsampled image

    CLI->>Palette: Select Pico8 palette (16 colors)
    Palette-->>CLI: Color palette

    CLI->>Dither: Apply Floyd-Steinberg
    Note over Dither: Error diffusion:<br/>7/16, 3/16, 5/16, 1/16
    Dither-->>CLI: Dithered image

    CLI->>Output: Upscale & Save
    Note over Output: Nearest-neighbor<br/>upscale=6x6
    Output-->>User: output.png (636×360)
Loading

Video Processing Workflow

%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#7C3AED','primaryTextColor':'#fff','primaryBorderColor':'#5B21B6','lineColor':'#6B7280','secondaryColor':'#10B981','tertiaryColor':'#F59E0B'}}}%%
flowchart LR
    A[Input Video<br/>1280×720 MP4] --> B[FFmpeg Extract]
    B --> C[Frame 00001.png<br/>Frame 00002.png<br/>...<br/>Frame 14315.png]
    C --> D{Process Each Frame}

    D --> E[Downsample<br/>Sobel + Factor]
    E --> F[Palette<br/>Pico8 16 colors]
    F --> G[Dither<br/>Floyd-Steinberg]
    G --> H[Upscale<br/>6×6 Nearest]

    H --> I[Processed Frames<br/>636×360]
    I --> J[FFmpeg Encode<br/>H.264 CRF 18]
    J --> K[Output Video<br/>636×360 MP4]

    style D fill:#F59E0B,stroke:#D97706,stroke-width:2px,color:#000
    style G fill:#7C3AED,stroke:#5B21B6,stroke-width:2px,color:#fff
    style J fill:#10B981,stroke:#059669,stroke-width:2px,color:#fff
Loading

WASM Integration

%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#7C3AED','primaryTextColor':'#fff','primaryBorderColor':'#5B21B6','lineColor':'#6B7280','secondaryColor':'#10B981','tertiaryColor':'#F59E0B'}}}%%
graph LR
    subgraph Browser
        UI[HTML Canvas<br/>web/index.html]
        TS[TypeScript<br/>main.ts]
        ID[ImageData<br/>RGBA Buffer]
    end

    subgraph "WebAssembly"
        WASM[WASM Module<br/>wasm/pkg/]
        RUST[Rust Core<br/>lib.rs]
    end

    subgraph "Processing"
        PROC[PixelateR<br/>Processing Pipeline]
    end

    UI -->|User Upload| TS
    TS -->|getImageData| ID
    ID -->|Uint8Array| WASM
    WASM -->|transform| RUST
    RUST -->|Process| PROC
    PROC -->|RGBA Buffer| RUST
    RUST -->|Vec u8| WASM
    WASM -->|Uint8Array| TS
    TS -->|putImageData| UI

    style WASM fill:#10B981,stroke:#059669,stroke-width:2px,color:#fff
    style PROC fill:#7C3AED,stroke:#5B21B6,stroke-width:2px,color:#fff
Loading

Project Structure

PixelateR/
├── src/           # Rust CLI implementation
│   ├── cli/       # Command-line interface
│   ├── color/     # Color quantization and palettes
│   ├── dither/    # Dithering algorithms (Bayer, Floyd-Steinberg, Riemersma)
│   ├── filter/    # Brightness, contrast, halftone
│   └── video/     # FFmpeg wrapper (future)
├── wasm/          # WebAssembly bindings
├── web/           # TypeScript/Vite frontend
│   ├── src/
│   │   └── main.ts    # Main application logic
│   └── index.html     # Web interface
├── web-serve/     # Development server
└── examples/      # Sample media and outputs

Dithering Algorithms

Bayer (Ordered Dithering)

  • Uses 4×4 Bayer matrix
  • Fast and consistent patterns
  • Good for retro pixel art aesthetic

Floyd-Steinberg (Error Diffusion)

  • Distributes quantization error to neighboring pixels
  • Higher quality, more natural gradients
  • Larger file sizes due to detail

Riemersma (Hilbert Curve)

  • Space-filling curve traversal
  • Unique texture, good for artistic effects
  • Available via halftone filter

Color Palettes

Pico8

  • 16-color fantasy console palette
  • Vibrant, retro aesthetic
  • Default palette for quick results

Custom Palettes

  • Define your own color sets
  • Euclidean distance matching in RGB space

WebAssembly Integration

The web interface uses Rust compiled to WebAssembly for high-performance image processing in the browser:

  1. Image loaded via Canvas API
  2. ImageData (RGBA) sent to WASM
  3. Rust processes with selected settings
  4. RGBA buffer returned to JavaScript
  5. Canvas updated with result

See docs/WEB_GUI_USAGE.md for implementation details.

Performance

Benchmarks

Processing a 1920×1080 image:

Algorithm Time Settings
Bayer ~80ms factor=6, upscale=6×6
Floyd-Steinberg ~250ms factor=6, upscale=6×6
Riemersma ~400ms factor=6

Benchmarks on AMD Ryzen 5 3600, single-threaded

Video Processing

Processing Big Buck Bunny (9:56, 1280×720, 24fps, 14,315 frames):

  • Frame extraction: ~2 minutes
  • Processing (Floyd-Steinberg): ~45 minutes
  • Video encoding: ~3 minutes
  • Total: ~50 minutes

Roadmap

  • GPU acceleration via wgpu
  • Additional color palettes (Gameboy, NES, C64)
  • Pure Rust video encoding (rav1e integration)
  • Multithreaded batch processing
  • Web interface: video upload support
  • Web interface: palette editor
  • Advanced filters (CRT scan lines, bloom)
  • Python bindings via PyO3

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Development Setup

# Run tests
cargo test

# Run benchmarks
cargo bench

# Format code
cargo fmt

# Lint
cargo clippy

# Build docs
cargo doc --no-deps --open

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

Related Projects

Support

For questions, issues, or feature requests, please open an issue.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors