grim-rs
Rust implementation of grim-rs screenshot utility for Wayland compositors.
⚠️ Breaking Changes in v0.1.3
Version 0.1.3 introduces breaking changes related to struct field encapsulation. See MIGRATION.md for upgrade guide.
Features
- Pure Rust implementation - no external dependencies on C libraries
- Native Wayland protocol support via
wayland-client - Multi-monitor support with automatic compositing across monitor boundaries
- Output transforms - full support for rotated/flipped displays (all 8 Wayland transform types)
- High-quality image scaling - 4-tier adaptive algorithm selection:
- Upscaling (>1.0): Triangle filter for smooth interpolation
- Mild downscaling (0.75-1.0): Triangle for fast, high-quality results
- Moderate downscaling (0.5-0.75): CatmullRom for sharp results with good performance
- Heavy downscaling (<0.5): Lanczos3 for best quality at extreme reduction
- Region-based screenshot capture with pixel-perfect accuracy
- Multiple output formats:
- PNG with configurable compression (0-9)
- JPEG with quality control (0-100)
- PPM (uncompressed)
- XDG Pictures directory support - automatic file placement in
~/Pictures - Y-invert flag handling - correct screenshot orientation on all compositors
- Cursor overlay support (compositor-dependent)
- Zero external tool dependencies
- Comprehensive API documentation with examples
Usage
As a Library
Add to your Cargo.toml:
[]
= "0.1.3"
Upgrading from 0.1.2? See MIGRATION.md for breaking changes.
Basic Capture Operations
use ;
Getting Output Information
use Grim;
Capture with Scaling
use ;
Multiple Output Capture
use ;
Saving to Different Formats
use Grim;
Converting to Bytes (without saving to file)
use Grim;
Writing to Stdout (for piping)
use Grim;
Reading Region from Stdin
use Grim;
Command Line Usage
The grim-rs binary supports the same functionality as the library API. By default, saves to ~/Pictures (XDG Pictures directory) with timestamped filenames.
Available Options:
Usage Examples:
# Build the binary first
# Capture entire screen (saves to ~/Pictures/<timestamp>.png)
# Capture with specific filename
# Capture specific region
# Capture with scaling (50% size, creates thumbnail)
# Capture specific output by name
# Capture with cursor included
# Save as JPEG with custom quality
# Save as PNG with maximum compression
# Save as PPM (uncompressed)
# Combine options: region + scaling + cursor
# Capture to stdout and pipe to another program
# Save to custom directory via environment variable
GRIM_DEFAULT_DIR=/tmp
# Read region from stdin
|
Using the installed binary:
After installation with cargo install grim-rs, you can use it directly:
# Capture entire screen
# All the same options work without 'cargo run'
|
Note: The binary is named grim-rs to avoid conflicts with the original C implementation of grim.
Supported Wayland Protocols
wl_shm- Shared memory bufferszwlr_screencopy_manager_v1- Screenshot capture (wlroots extension)wl_output- Output information
API Reference
Core Methods
Initialization
Grim::new()- Create new Grim instance and connect to Wayland compositor
Getting Display Information
get_outputs()- Get list of available outputs with their properties (name, geometry, scale)
Capture Methods
capture_all()- Capture entire screen (all outputs)capture_all_with_scale(scale: f64)- Capture entire screen with scalingcapture_output(output_name: &str)- Capture specific output by namecapture_output_with_scale(output_name: &str, scale: f64)- Capture output with scalingcapture_region(region: Box)- Capture specific rectangular regioncapture_region_with_scale(region: Box, scale: f64)- Capture region with scalingcapture_outputs(parameters: Vec<CaptureParameters>)- Capture multiple outputs with different parameterscapture_outputs_with_scale(parameters: Vec<CaptureParameters>, default_scale: f64)- Capture multiple outputs with scaling
Saving to Files
save_png(&data, width, height, path)- Save as PNG with default compression (level 6)save_png_with_compression(&data, width, height, path, compression: u8)- Save as PNG with custom compression (0-9)save_jpeg(&data, width, height, path)- Save as JPEG with default quality (80) [requiresjpegfeature]save_jpeg_with_quality(&data, width, height, path, quality: u8)- Save as JPEG with custom quality (0-100) [requiresjpegfeature]save_ppm(&data, width, height, path)- Save as PPM (uncompressed)
Converting to Bytes
to_png(&data, width, height)- Convert to PNG bytes with default compressionto_png_with_compression(&data, width, height, compression: u8)- Convert to PNG bytes with custom compressionto_jpeg(&data, width, height)- Convert to JPEG bytes with default quality [requiresjpegfeature]to_jpeg_with_quality(&data, width, height, quality: u8)- Convert to JPEG bytes with custom quality [requiresjpegfeature]to_ppm(&data, width, height)- Convert to PPM bytes
Writing to Stdout
write_png_to_stdout(&data, width, height)- Write PNG to stdout with default compressionwrite_png_to_stdout_with_compression(&data, width, height, compression: u8)- Write PNG to stdout with custom compressionwrite_jpeg_to_stdout(&data, width, height)- Write JPEG to stdout with default quality [requiresjpegfeature]write_jpeg_to_stdout_with_quality(&data, width, height, quality: u8)- Write JPEG to stdout with custom quality [requiresjpegfeature]write_ppm_to_stdout(&data, width, height)- Write PPM to stdout
Stdin Input
Grim::read_region_from_stdin()- Read region specification from stdin (format: "x,y widthxheight")
Data Structures
CaptureResult
Contains captured image data:
data: Vec<u8>- Raw RGBA image data (4 bytes per pixel)width: u32- Image width in pixelsheight: u32- Image height in pixels
CaptureParameters
Parameters for capturing specific outputs:
output_name: String- Name of the output to captureregion: Option<Box>- Optional region within the outputoverlay_cursor: bool- Whether to include cursor in capturescale: Option<f64>- Optional scale factor for the output
MultiOutputCaptureResult
Result of capturing multiple outputs:
outputs: HashMap<String, CaptureResult>- Map of output names to their capture results
Output
Information about a display output:
name: String- Output name (e.g., "eDP-1", "HDMI-A-1")geometry: Box- Output position and sizescale: i32- Scale factor (1 for normal DPI, 2 for HiDPI)description: Option<String>- Monitor model and manufacturer information
Box
Rectangular region:
x: i32- X coordinatey: i32- Y coordinatewidth: i32- Widthheight: i32- Height- Can be parsed from string: "x,y widthxheight"
Feature Flags
jpeg- Enable JPEG support (enabled by default)- Adds
save_jpeg*,to_jpeg*, andwrite_jpeg_to_stdout*methods
- Adds
To disable JPEG support:
[]
= { = "0.1.0", = false }
Full API Documentation
Comprehensive API documentation is available at docs.rs or can be generated locally:
Comparison with Original grim
| Feature | Original grim | grim-rs |
|---|---|---|
| Language | C | Rust |
| Dependencies | libpng, pixman, wayland, libjpeg | Pure Rust crates |
| Output formats | PNG, JPEG, PPM | PNG, JPEG, PPM |
| Installation | System package | Rust crate |
| Integration | External process | Library + Binary |
| Memory safety | Manual | Guaranteed by Rust |
| Output transforms | ✅ | ✅ |
| Y-invert handling | ✅ | ✅ |
| Multi-monitor compositing | ✅ | ✅ |
| Image scaling | Nearest-neighbor | 4-tier adaptive (Triangle/CatmullRom/Lanczos3) |
| XDG Pictures support | ✅ | ✅ |
| Output descriptions | ✅ | ✅ |
| Color accuracy | ✅ | ✅ |
| Real capture | ✅ | ✅ |
Architecture
┌─────────────────┐
│ Application │
├─────────────────┤
│ grim-rs │
├─────────────────┤
│ wayland-client │
├─────────────────┤
│ Wayland │
│ Compositor │
└─────────────────┘
Key Components
- Grim - Main interface for taking screenshots
- CaptureResult - Contains screenshot data and dimensions
- CaptureParameters - Parameters for multi-output capture
- Buffer - Shared memory buffer management
- Box - Region and coordinate handling
- Output - Monitor information with transform support
- Error - Comprehensive error handling
Image Processing Pipeline
Wayland Screencopy → Buffer → Output Transform → Y-invert → Scaling → Format Conversion → Save
↓ ↓ ↓
(rotation/flip) (vertical) (Bilinear/Lanczos3)
Scaling Quality
Adaptive 4-tier algorithm selection ensures optimal quality/performance balance:
-
Upscaling (scale > 1.0): Triangle filter
- Smooth interpolation for enlarging images
- Avoids pixelation when scaling up
- Example: 1920×1080 → 2560×1440 (1.33×)
-
Mild downscaling (0.75 ≤ scale ≤ 1.0): Triangle filter
- Fast, high-quality for small size reductions
- Perfect for minor adjustments: 1920×1080 → 1536×864 (0.8×)
-
Moderate downscaling (0.5 ≤ scale < 0.75): CatmullRom filter
- Sharper results than Triangle
- Better performance than Lanczos3
- Ideal for medium reduction: 1920×1080 → 1280×720 (0.67×)
-
Heavy downscaling (scale < 0.5): Lanczos3 convolution
- Best quality for significant reduction
- Ideal for thumbnails: 3840×2160 → 960×540 (0.25×)
- Superior detail preservation at extreme scales
Environment Variables
GRIM_DEFAULT_DIR- Override default screenshot directory (highest priority)XDG_PICTURES_DIR- XDG Pictures directory (from env or~/.config/user-dirs.dirs)
Priority order: GRIM_DEFAULT_DIR → XDG_PICTURES_DIR → current directory
Supported Compositors
- ✅ Hyprland
- ✅ Sway
- ✅ River
- ✅ Wayfire
- ✅ Any wlroots-based compositor with
zwlr_screencopy_manager_v1
Limitations
- Requires compositor with
zwlr_screencopy_manager_v1protocol support - Linux-only (due to shared memory implementation)
- Cursor overlay depends on compositor support
Building
Testing
# Run tests
# Run examples
Contributing
- Fork the repository
- Create a feature branch
- Make changes
- Add tests
- Submit a pull request
License
MIT License - see LICENSE file for details.