6.3 KiB
filmscan
- Film Scan and Negative Reversal Simulation
filmscan
is a Python script that simulates the process of scanning a film negative and converting it into a positive image. It is heavily inspired by the "Negadoctor" module found in the popular open-source raw image processor, Darktable. This script aims to provide a "batteries included" experience by auto-detecting several key parameters required for the conversion.
Features
- Implements a negative-to-positive conversion process similar to Darktable's Negadoctor.
- Automatic Parameter Detection:
Dmin
(film base color / brightest part of the negative)Dmax
(determines the dynamic range, from darkest part of the negative)Offset
(scan exposure bias)Paper Black
(density correction for print black point)Print Exposure
(overall print exposure adjustment)
- Color management: Converts input sRGB (assumed) to ACEScg for processing, then back to a chosen output colorspace (sRGB or Display P3).
- Supports TIFF, PNG, and JPG inputs.
- Outputs TIFF (16-bit uncompressed), PNG (8-bit), or JPG (8-bit).
Usage
The script is designed to be run with uv
, which handles dependency management.
Direct Execution with uv
(Recommended)
You can run filmscan
directly from its Git repository URL:
uv run https://git.dws.rip/dubey/filmsim/raw/branch/main/filmscan -- <input_file> <output_file> [options]
Example:
# Ensure input_negative.tiff is in your current directory or provide a full path
# Output will be output_positive.jpg
uv run https://git.dws.rip/dubey/filmsim/raw/branch/main/filmscan -- input_negative.tiff output_positive.jpg --output_colorspace sRGB
Local Execution
If you have cloned the repository or downloaded the script:
-
Navigate to the script's directory or ensure it's in your PATH.
-
Run the script:
uv run ./filmscan -- <input_file> <output_file> [options]
Or, if
filmscan
is in the current directory and executable:./filmscan <input_file> <output_file> [options]
Arguments
Positional Arguments:
input_file
: Path to the input negative image.- Supported formats: TIFF, PNG, JPG.
- The image is assumed to be an sRGB encoded film negative scan.
output_file
: Path to save the processed positive image.- Output format is determined by the file extension:
.tiff
/.tif
: 16-bit uncompressed TIFF..png
: 8-bit PNG..jpg
/.jpeg
: 8-bit JPG.
- Output format is determined by the file extension:
Options:
--patch_size_ratio FLOAT
: Ratio of image minimum dimension for patch size in auto-detection. (Default:1/128
)- Smaller values use smaller patches, which can be faster but potentially more susceptible to noise.
--min_patch_size INT
: Minimum patch size in pixels for auto-detection. (Default:8
)--max_patch_size INT
: Maximum patch size in pixels for auto-detection. (Default:32
)--aces_transform TEXT
: ACES working space. Currently, ACEScg is used internally and this option is noted for future flexibility but does not change behavior. (Default:ACEScg
)--output_colorspace TEXT
: Colorspace for the output image.- Supported:
sRGB
(default),Display P3
. - The output image will be gamma-corrected for the chosen colorspace.
- Supported:
Workflow
- Load Image: Reads the input negative image. It's normalized to a 0-1 float range.
- Color Conversion (Input):
- The input image (assumed sRGB) is decoded from its gamma (e.g., sRGB EOTF inverse).
- The linear sRGB data is then converted to the ACEScg color space for internal processing.
- Auto-Parameter Detection:
- The script analyzes the ACEScg image to automatically determine optimal values for:
Dmin
: The color of the unexposed film base, found by looking for the brightest representative patch in the negative.Dmax
: A measure of the film's maximum density range, calculated usingDmin
and the darkest representative patch in the negative (scene highlight).Offset
: A scan exposure bias, determined fromDmin
,Dmax
, and the brightest image content patch.Paper Black
: Adjusts the black point of the final print, derived fromDmin
,Dmax
,Offset
, and characteristics of the brightest image patch under default white balance.Print Exposure
: Overall brightness adjustment for the final print, calculated using all previously determined parameters and the darkest image patch.
- Default white balance (
WB_HIGH
,WB_LOW
), gamma (DEFAULT_GAMMA
), and soft clip (DEFAULT_SOFT_CLIP
) values are used alongside these auto-detected parameters.
- The script analyzes the ACEScg image to automatically determine optimal values for:
- Negadoctor Process:
- The core conversion logic, adapted from Darktable's
negadoctor.c
. - Density Conversion: Input pixel values are converted to log densities relative to
Dmin
. - Density Correction: Densities are adjusted using
Dmax
,Offset
, and white balance parameters. - Print Simulation: Corrected densities are transformed to simulate printing on paper, incorporating
Print Exposure
andPaper Black
. - Paper Grade (Gamma): A gamma curve (contrast adjustment) is applied.
- Highlight Compression (Soft Clip): Highlights are compressed to simulate the behavior of photographic paper gloss.
- The core conversion logic, adapted from Darktable's
- Color Conversion (Output):
- The processed image (now a positive in ACEScg) is converted to the chosen
output_colorspace
(e.g., sRGB, Display P3). - The image is clipped to the 0-1 range.
- The appropriate gamma correction (e.g., sRGB OETF) is applied for the output colorspace.
- The processed image (now a positive in ACEScg) is converted to the chosen
- Save Output: The final positive image is saved, converting to 16-bit for TIFF or 8-bit for PNG/JPG.
Notes on Auto-Detection
The auto-detection routines (auto_calculate_dmin
, auto_calculate_dmax
, etc.) work by finding representative "brightest" or "darkest" patches in the negative image.
- "Brightest" on a negative typically corresponds to the film base (for
Dmin
) or unexposed areas that will become deep shadows in the positive. - "Darkest" on a negative typically corresponds to scene highlights that will become bright areas in the positive.
The patch_size_ratio
, min_patch_size
, and max_patch_size
arguments control how these patches are sampled.