Files
filmsim/README-filmcolor.md

4.9 KiB
Raw Blame History

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 (HurterDriffield) 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.

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:

  1. Navigate to the script's directory or ensure it's in your PATH.

  2. 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).

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

  1. Load Image: Reads the input image. RAW files are processed using rawpy. sRGB images are linearized.
  2. Load Datasheet: Parses the specified JSON film datasheet.
  3. Convert to Log Exposure: Transforms linear RGB pixel values to log exposure (LogE) space, anchored by the middle_gray_logE from the datasheet.
  4. 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.
  5. Convert Density to Transmittance: Converts the resulting densities back to linear transmittance values (0-1 range).
  6. 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 and halation.size_um.
  7. Apply Saturation: Adjusts image saturation based on the couplers.amount parameter.
  8. 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.