An open API service indexing awesome lists of open source software.

https://github.com/dmtrkovalenko/odiff-cross


https://github.com/dmtrkovalenko/odiff-cross

Last synced: 9 months ago
JSON representation

Awesome Lists containing this project

README

          

# zdiff

A fast pixel-by-pixel image comparison tool written in Zig. This is a faithful port of [odiff](https://github.com/dmtrKovalenko/odiff) from OCaml to Zig, maintaining full compatibility with the original API while leveraging Zig's performance and safety features.

## Features

- **Fast pixel-by-pixel image comparison** using perceptually accurate color difference algorithms
- **Antialiasing detection** to ignore antialiased pixels in comparisons
- **Multiple image format support** (PNG, JPEG, TIFF) via C FFI
- **Flexible output options** including diff masks and parseable output
- **Ignore regions** to exclude specific areas from comparison
- **Memory efficient** with configurable RAM usage optimization
- **Full CLI compatibility** with the original odiff

## Algorithm Details

### Color Difference Calculation
zdiff uses the YIQ color space for perceptually accurate color difference calculations:

- **YIQ Color Space**: Converts RGB to YIQ (luminance and chrominance) for better human perception matching
- **Semi-transparent Pixel Blending**: Properly handles alpha channel by blending with white background
- **Configurable Threshold**: Allows fine-tuning of sensitivity (0.0-1.0 range)

### Antialiasing Detection
The antialiasing detection algorithm identifies edge pixels that may appear different due to antialiasing:

- **Neighbor Analysis**: Examines 3x3 pixel neighborhoods around each different pixel
- **Brightness Delta Calculation**: Uses brightness differences to identify edge pixels
- **Sibling Counting**: Counts similar pixels in neighborhoods to detect antialiasing patterns
- **Cross-Image Validation**: Verifies antialiasing patterns exist in both images

## Installation

### Prerequisites
- Zig 0.14.1 or later
- Standard C library (for image format support)

### Building from Source
```bash
git clone
cd zdiff
zig build
```

The binary will be available at `zig-out/bin/zdiff`.

## Usage

### Basic Usage
```bash
# Compare two images
zdiff image1.png image2.png

# Compare and save diff output
zdiff image1.png image2.png diff.png

# Compare with custom threshold
zdiff image1.png image2.png -t 0.05

# Compare with antialiasing detection
zdiff image1.png image2.png --antialiasing
```

### Command Line Options

| Option | Description |
|--------|-------------|
| `-t, --threshold ` | Color difference threshold (0.0-1.0, default: 0.1) |
| `--diff-mask` | Output only changed pixels over transparent background |
| `--fail-on-layout` | Fail if image dimensions differ |
| `--parsable-stdout` | Machine-readable output format |
| `--diff-color ` | Color for highlighting differences (e.g., #cd2cc9) |
| `--aa, --antialiasing` | Ignore antialiased pixels in diff |
| `--output-diff-lines` | Output line numbers with differences |
| `--reduce-ram-usage` | Use less memory (slower) |
| `-i, --ignore ` | Ignore regions (format: x1:y1-x2:y2,x3:y3-x4:y4) |
| `-h, --help` | Show help message |
| `--version` | Show version |

### Exit Codes
- `0` - Images match
- `21` - Layout difference (when --fail-on-layout is used)
- `22` - Pixel differences found

### Examples

#### Compare with ignore regions
```bash
zdiff image1.png image2.png -i "10:10-50:50,100:100-200:200"
```

#### Parseable output for CI/CD
```bash
zdiff image1.png image2.png --parsable-stdout
# Output: number of different pixels or "layout" for dimension mismatch
```

#### Antialiasing-aware comparison
```bash
# Ignore antialiased pixels (useful for font rendering comparisons)
zdiff text1.png text2.png --antialiasing
```

## Architecture

### Core Components

1. **Image I/O** (`src/image_io.zig`)
- Abstraction layer over C image libraries
- Support for PNG, JPEG, and TIFF formats
- Memory-safe wrappers around C FFI

2. **Diff Algorithm** (`src/diff.zig`)
- Core pixel comparison logic
- YIQ color space conversion
- Difference calculation and thresholding

3. **Antialiasing Detection** (`src/antialiasing.zig`)
- Sophisticated edge detection
- Neighborhood analysis
- Cross-image pattern validation

4. **Color Delta** (`src/color_delta.zig`)
- Perceptual color difference calculations
- Alpha blending with white background
- YIQ color space transformations

5. **CLI Interface** (`src/cli.zig`)
- Command-line argument parsing
- Compatible with original odiff API
- Comprehensive help and error messages

6. **C Bindings** (`c_bindings/`)
- FFI layer for image format support
- Memory management for C structures
- Placeholder implementations (can be extended with full libpng/libjpeg/libtiff)

### Memory Management
- **RAII Pattern**: All resources automatically cleaned up via Zig's defer mechanism
- **Arena Allocators**: Efficient memory allocation patterns
- **C Interop**: Safe wrappers around C memory management

## Compatibility with odiff

zdiff maintains full API compatibility with the original odiff:

- **Same command-line arguments and flags**
- **Identical exit codes**
- **Same output formats**
- **Compatible ignore region syntax**
- **Equivalent algorithmic behavior**

This makes zdiff a drop-in replacement for odiff in existing scripts and CI/CD pipelines.

## Performance

zdiff is designed for performance:

- **Compiled to native code** via Zig's LLVM backend
- **Zero-cost abstractions** with compile-time optimization
- **Memory-efficient algorithms** with configurable RAM usage
- **SIMD potential** for future vectorization optimizations

## Development

### Project Structure
```
zdiff/
├── src/
│ ├── main.zig # CLI entry point
│ ├── root.zig # Library exports
│ ├── image_io.zig # Image loading/saving
│ ├── diff.zig # Core diff algorithm
│ ├── antialiasing.zig # Antialiasing detection
│ ├── color_delta.zig # Color difference calculation
│ ├── cli.zig # Command-line interface
│ └── c_bindings.zig # C FFI wrappers
├── c_bindings/
│ ├── zdiff_io.h # C header definitions
│ └── zdiff_io.c # C implementation (placeholder)
├── build.zig # Build configuration
└── README.md
```

### Building and Testing
```bash
# Build debug version
zig build

# Build optimized release
zig build -Doptimize=ReleaseFast

# Run tests
zig build test

# Run with arguments
zig build run -- image1.png image2.png
```

### Extending Image Format Support

To add support for additional image formats:

1. Implement C functions in `c_bindings/zdiff_io.c`
2. Add format detection in `src/image_io.zig`
3. Create wrapper functions in `src/c_bindings.zig`
4. Update build.zig to link required libraries

## Future Enhancements

- **Full image library integration** (replace placeholder C implementations)
- **SIMD optimizations** for faster pixel processing
- **Parallel processing** for large images
- **Additional output formats** (JSON, XML)
- **Web Assembly target** for browser usage
- **Integration with zig-cli library** for better argument parsing

## License

This project maintains the same license as the original odiff project.

## Contributing

Contributions are welcome! Please ensure:

- Code follows Zig formatting conventions
- All tests pass
- New features include appropriate tests
- Documentation is updated for API changes

## Acknowledgments

- Original [odiff](https://github.com/dmtrKovalenko/odiff) project by Dmitriy Kovalenko
- The Zig programming language community
- Contributors to the image processing libraries used