4.9 KiB
filmcolor
- Film Stock Color Emulation
filmcolor
is a Python script that transforms digital color positive images (like those from a digital camera) into simulated film negatives. It bases its transformations on datasheet parameters for specific film stocks, focusing on color response, H&D curves, spatial effects like halation and diffusion, and saturation.
Features
- Applies film stock characteristics based on a JSON datasheet.
- Converts linear RGB input to log exposure.
- Applies H&D (Hurter–Driffield) curves for tonal mapping.
- Simulates dye coupler diffusion and interlayer effects.
- Applies halation effects.
- Adjusts saturation based on coupler properties.
- Supports RAW (Sony ARW, DNG), 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 filmcolor
directly from its Git repository URL:
uv run https://git.dws.rip/dubey/filmsim/raw/branch/main/filmcolor -- <input_image> <datasheet_json> <output_image>
Example:
# Ensure input.jpg and sim_data/portra_400.json are in your current directory or provide full paths
# Output will be output_negative.tiff
uv run https://git.dws.rip/dubey/filmsim/raw/branch/main/filmcolor -- input.jpg sim_data/portra_400.json output_negative.tiff
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 ./filmcolor -- <input_image> <datasheet_json> <output_image>
Or, if
filmcolor
is in the current directory and executable:./filmcolor <input_image> <datasheet_json> <output_image>
Arguments
Positional Arguments:
input_image
: Path to the input RGB image.- Supported formats: TIFF, PNG, JPG, Sony ARW, DNG.
- Non-RAW images are assumed to be sRGB and will be linearized. RAW files are processed to sRGB.
datasheet_json
: Path to the film datasheet JSON file (e.g.,sim_data/portra_400.json
).output_image
: Path to save the output emulated film negative.- Output format is determined by the file extension:
.tiff
/.tif
: 16-bit uncompressed TIFF..png
: 8-bit PNG..jpg
/.jpeg
: 8-bit JPG (quality 95).
- Output format is determined by the file extension:
Options:
The script currently does not have additional command-line options beyond the positional arguments. Configuration is primarily driven by the content of the datasheet_json
file.
Input Image Preparation
- Linear RGB: The script internally works with linear RGB data.
- If an 8-bit or 16-bit integer image (PNG, JPG, TIFF) is provided, it's assumed to be sRGB encoded and will be automatically linearized.
- If a float32/float64 image is provided, it's assumed to be already in linear RGB.
- RAW files (ARW, DNG) are demosaiced, white-balanced (using camera WB), and converted to linear sRGB.
- Alpha Channel: If an alpha channel is present, it will be discarded.
Datasheet Format
The datasheet_json
file contains detailed parameters for the film stock being simulated. This includes:
- Information (name, format, version)
- Processing parameters (gamma, balance)
- Physical properties (halation strength and size, coupler diffusion, interlayer diffusion)
- H&D curves
- Calibration data (ISO, middle gray log exposure)
An example datasheet (sim_data/portra_400.json
) is provided in the repository.
Workflow
- Load Image: Reads the input image. RAW files are processed using
rawpy
. sRGB images are linearized. - Load Datasheet: Parses the specified JSON film datasheet.
- Convert to Log Exposure: Transforms linear RGB pixel values to log exposure (LogE) space, anchored by the
middle_gray_logE
from the datasheet. - Apply H&D Curves: Maps LogE values to densities for each color channel (R, G, B) using the H&D curves from the datasheet. This step also incorporates processing gamma and balance shifts.
- Convert Density to Transmittance: Converts the resulting densities back to linear transmittance values (0-1 range).
- Apply Spatial Effects:
- Diffusion Blur: Simulates dye coupler and interlayer diffusion by applying a Gaussian blur. The blur radius is derived from
diffusion_um
values in the datasheet and the image dimensions/film format. - Halation: Simulates light scattering within the film base by applying channel-specific Gaussian blurs, controlled by
halation.strength
andhalation.size_um
.
- Diffusion Blur: Simulates dye coupler and interlayer diffusion by applying a Gaussian blur. The blur radius is derived from
- Apply Saturation: Adjusts image saturation based on the
couplers.amount
parameter. - Save Output: The processed image (now a simulated film negative) is saved to the specified output file, converting to 16-bit for TIFF or 8-bit for PNG/JPG.