How to Compare Two Images for Pixel-Level Differences Using the `idiff` Command-Line Tool
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 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 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. 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:
idiff imageA.exr imageB.exr
Tolerance-Based Comparison
Allow small differences that are common in lossy compression or floating-point rounding:
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:
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:
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:
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:
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:
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 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
idiffis the official OpenImageIO command-line tool for pixel-level image comparison, implemented insrc/idiff/idiff.cpp.- It uses
ImageBufAlgo::compare()for statistical analysis and optionallycompare_Yeefor perceptual comparison when the-pflag is used. - The tool normalizes all input to 32-bit float via
ImageCacheto 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
-owith 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →