# How to Compare Two Images for Pixel-Level Differences Using the `idiff` Command-Line Tool

> Compare two images pixel by pixel using the idiff command-line tool. Discover visual differences and statistical metrics with this OpenImageIO utility. Learn more now.

- Repository: [Academy Software Foundation/openimageio](https://github.com/academysoftwarefoundation/openimageio)
- Tags: how-to-guide
- Published: 2026-02-23

---

**`idiff` is a command-line utility built on the OpenImageIO (OIIO) library that performs pixel-by-pixel comparisons of two images, computing statistical differences and optionally generating visual diff images.**

The `idiff` tool is part of the Academy Software Foundation's OpenImageIO repository and provides a robust solution to **compare two images for pixel-level differences** in visual effects pipelines. Unlike simple file comparison tools, `idiff` analyzes the actual pixel values, supporting multiple color channels, deep images, and perceptual comparison algorithms.

## How `idiff` Works Under the Hood

The implementation in [`src/idiff/idiff.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/idiff/idiff.cpp) follows a structured pipeline that ensures accurate and consistent comparisons across different image formats.

### Argument Parsing and Configuration

The tool uses the `ArgParse` class to define a comprehensive set of options, including thresholds, perceptual mode flags, and output file paths. This logic resides in the main function of [`src/idiff/idiff.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/idiff/idiff.cpp) between lines 38 and 99.

### Image Cache and Normalization

Before comparison, `idiff` initializes an `ImageCache` instance and configures it to store all pixels as 32-bit floats. This normalization step ensures that comparisons are consistent regardless of whether the source images are 8-bit PNGs, 16-bit TIFFs, or 32-bit EXR files. The cache setup appears in lines 34-47 of the main implementation file.

### Reading and Validation

The `read_input()` function loads each image (including specific subimages or MIP levels) through the image cache. If a file cannot be read or is corrupted, the tool reports an error immediately and exits with a non-zero status.

### Core Comparison Algorithms

The actual pixel comparison is performed by `ImageBufAlgo::compare()`, which computes:

- **Mean absolute difference**
- **RMS (Root Mean Square) error**
- **PSNR (Peak Signal-to-Noise Ratio)**
- **Maximum error value and its location**

If the `-p` flag is specified, `idiff` additionally runs `compare_Yee`, a perceptual comparison algorithm based on Yee's method that models human visual system limitations.

### Threshold Evaluation and Status Determination

The comparison results are evaluated against user-provided thresholds in lines 112-131 of [`src/idiff/idiff.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/idiff/idiff.cpp). The tool supports:

- **Absolute difference thresholds** (`-fail`, `-warn`)
- **Relative thresholds** (`-failrelative`, `-warnrelative`)
- **Percentage of failing pixels** (`-failpercent`, `-warnpercent`)
- **Hard failure limits** (`-hardfail`, `-hardwarn`)
- **Allowed failure counts** (`--allowfailures`)

Based on these checks, `idiff` returns a status of `PASS`, `WARNING`, or `FAILURE` and sets the appropriate exit code.

## Basic Usage Examples

### Simple Pixel-by-Pixel Comparison

To compare two images and see if they are identical at the pixel level:

```bash
idiff imageA.exr imageB.exr

```

### Tolerance-Based Comparison

Allow small differences that are common in lossy compression or floating-point rounding:

```bash
idiff -fail 0.004 -failpercent 5 imageA.png imageB.png

```

This command allows up to 5% of pixels to differ by no more than 0.004 (on a 0-1 scale) before reporting a failure.

### Hard Failure Limits

Set an absolute ceiling for any single pixel's difference while allowing a percentage of smaller errors:

```bash
idiff -fail 0.004 -failpercent 10 -hardfail 0.25 imageA.tif imageB.tif

```

This fails immediately if any single pixel differs by more than 0.25, even if fewer than 10% of pixels exceed the 0.004 threshold.

## Advanced Comparison Options

### Perceptual Comparison Mode

Enable the Yee perceptual metric to compare images based on human visual perception rather than raw numeric differences:

```bash
idiff -p -fail 0.001 -failpercent 2 imageA.exr imageB.exr

```

The `-p` flag invokes `compare_Yee` in addition to the standard statistical comparison, accounting for luminance masking and color sensitivity variations in the human visual system.

### Comparing Specific Subimages and MIP Levels

For multi-part EXR files or textures with MIP maps, specify which layers to compare:

```bash
idiff -a 0 imageA.exr imageB.exr

```

The `-a` flag selects the subimage index (0-based) for both input files.

## Generating Difference Images

### Creating Visual Diff Output

Generate an image showing the absolute differences between two inputs:

```bash
idiff -o diff.tif -abs -scale 10 imageA.jpg imageB.jpg

```

This creates `diff.tif` where each pixel represents the absolute difference between the corresponding pixels in the inputs, scaled by a factor of 10 for visibility.

### Conditional Diff Output

Only generate the difference image when the comparison fails:

```bash
idiff -od -o diff.tif imageA.png imageB.png

```

The `-od` (output on difference) flag ensures that `diff.tif` is written only if the images are not identical within the specified thresholds.

## Understanding Return Codes and Threshold Logic

`idiff` returns specific exit codes that scripts and CI pipelines can use to automate quality control:

- **0**: The images match within all specified thresholds (`PASS`)
- **1**: The comparison completed but differences exceed warning thresholds (`WARNING`)
- **2**: The comparison failed due to excessive differences or unreadable files (`FAILURE`)

The threshold evaluation logic in [`src/idiff/idiff.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/idiff/idiff.cpp) processes multiple constraints simultaneously. For example, when using `--allowfailures 100`, the tool permits exactly 100 pixels to exceed the failure threshold before changing the status from `PASS` to `FAILURE`, providing flexibility for known artifacts or border pixels.

## Summary

- **`idiff`** is the official OpenImageIO command-line tool for pixel-level image comparison, implemented in [`src/idiff/idiff.cpp`](https://github.com/academysoftwarefoundation/openimageio/blob/main/src/idiff/idiff.cpp).
- It uses **`ImageBufAlgo::compare()`** for statistical analysis and optionally **`compare_Yee`** for perceptual comparison when the `-p` flag is used.
- The tool normalizes all input to **32-bit float** via `ImageCache` to ensure format-agnostic comparisons.
- Thresholds can be set for **absolute differences**, **relative errors**, **percentages of failing pixels**, and **hard limits** on individual pixel variance.
- **Difference images** can be generated using `-o` with optional scaling (`-scale`) and absolute value conversion (`-abs`).
- Exit codes **0, 1, and 2** indicate PASS, WARNING, and FAILURE states respectively, enabling integration with automated testing pipelines.

## Frequently Asked Questions

### What image formats does idiff support?

`idiff` supports all image formats that OpenImageIO can read, including OpenEXR, TIFF, PNG, JPEG, Cineon, DPX, and RAW formats from various camera manufacturers. Because it uses the `ImageCache` subsystem, it can efficiently handle very large images and deep data formats without loading entire files into memory.

### How does the perceptual comparison mode (-p) differ from standard pixel comparison?

The standard comparison calculates absolute mathematical differences between pixel values, which can flag imperceptible noise as a failure. When you use the `-p` flag, `idiff` runs the `compare_Yee` algorithm (based on Yee's perceptual metric) which models human visual sensitivity to luminance and color variations. This mode ignores differences that the human eye cannot detect, reducing false positives in quality control workflows.

### Can idiff compare images with different resolutions or color spaces?

By default, `idiff` requires images to have identical dimensions and channel counts. If the resolutions differ, the tool will report an error during the `read_input()` phase. However, because `idiff` uses `ImageCache` with forced float conversion, it can compare images that were originally in different color spaces or bit depths (e.g., comparing an 8-bit sRGB PNG against a 32-bit linear EXR), provided you have accounted for any necessary color space transformations in your pipeline before comparison.

### What is the difference between -fail and -hardfail thresholds?

The `-fail` threshold sets a tolerance level for the average or percentage-based comparison; pixels differing by less than this value may be ignored depending on your `-failpercent` setting. The `-hardfail` threshold is an absolute ceiling: if **any single pixel** in the image differs by more than the `-hardfail` value, `idiff` immediately returns a `FAILURE` status regardless of how many other pixels passed the standard threshold. This is critical for detecting catastrophic errors like NaN values or corruption in specific regions while allowing minor compression artifacts elsewhere.