Full Code of finnschi/heic-shenanigans for AI

main 8df2da2b0403 cached
6 files
79.5 KB
26.6k tokens
4 symbols
1 requests
Download .txt
Repository: finnschi/heic-shenanigans
Branch: main
Commit: 8df2da2b0403
Files: 6
Total size: 79.5 KB

Directory structure:
gitextract_5olro6ee/

├── README.md
├── gain_map_extract.py
├── heic_to_exr.py
├── merge_to_exr.sh
├── requirements.txt
└── studio-config-v1.0.0_aces-v1.3_ocio-v2.1.ocio

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
# 🖼️ HEIC Image Processing Tools

A collection of Python tools for processing HEIC (High Efficiency Image Container) files, with a focus on HDR content extraction and EXR conversion.

## 🛠️ Tools Overview

### 1. gain_map_extract.py
Extracts all components from HEIC files including:
- Base images
- HDR gain maps
- Depth maps
- Complete metadata (EXIF, XMP, ICC profiles)

### 2. heic_to_exr.py
Converts HEIC files to OpenEXR format:
- Combines base image and gain map into HDR EXR using apples method
- Preserves full dynamic range
- Maintains metadata where possible
- Supports batch processing

### 3. merge_to_exr.sh
Shell script for batch processing:
- Automates HEIC to EXR conversion
- Handles multiple files
- Provides progress feedback
- Maintains directory structure

## 🔧 Installation

### Prerequisites
- Python 3.8 or higher
- pip (Python package manager)
- Git (for cloning the repository)

### macOS
```bash
# Install Homebrew if not already installed
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install Python and OpenEXR dependencies
brew install python3 openexr

# Clone the repository
git clone https://github.com/finnschi/heic-shenanigans.git
cd heic-shenanigans

# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate

# Install Python dependencies
pip install -r requirements.txt
```

### Linux (Ubuntu/Debian)
```bash
# Install system dependencies
sudo apt-get update
sudo apt-get install python3 python3-pip python3-venv openexr libopenexr-dev

# Clone the repository
git clone https://github.com/finnschi/heic-shenanigans.git
cd heic-shenanigans

# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate

# Install Python dependencies
pip install -r requirements.txt
```

### Windows
```powershell
# Install Python from https://www.python.org/downloads/
# Install Git from https://git-scm.com/download/win

# Clone the repository
git clone https://github.com/finnschi/heic-shenanigans.git
cd heic-shenanigans

# Create and activate virtual environment
python -m venv venv
.\venv\Scripts\activate

# Install Python dependencies
pip install -r requirements.txt
```

## 📋 Requirements
All required Python packages are listed in requirements.txt:
- Pillow: Image processing library
- pillow-heif: HEIC file support
- numpy: Numerical operations
- defusedxml: Safe XML parsing

System dependencies (installed via package manager):
- OpenEXR and OpenImageIO (oiiotool) for EXR file handling

## 💻 Usage

### Gain Map Extraction
```bash
python gain_map_extract.py input.heic [--output-dir OUTPUT_DIR]
```

### HEIC to EXR Conversion
```bash
python heic_to_exr.py input.heic [--output-dir OUTPUT_DIR]
```

### Batch Processing
```bash
./merge_to_exr.sh input_directory output_directory
```

## 📁 Output Files

### gain_map_extract.py outputs:
- Base image: `{filename}_base.tiff`
- Gain maps: `{filename}_gain_map_{id}.tiff`
- Depth maps: `{filename}_depth_{index}.tiff`
- Metadata: `{filename}_metadata.json`

### heic_to_exr.py outputs:
- HDR EXR file: `{filename}.exr`

## 🔍 Advanced Usage

### Metadata Handling
- Binary data is base64 encoded
- ICC profiles are maintained
- EXIF data is preserved where possible

### HDR Processing
- Gain maps are properly scaled
- Linear color space is maintained
- Full dynamic range is preserved in EXR output

## ⚠️ Known Limitations
- Some HEIC variants may not be fully supported
- Depth map extraction is limited to supported devices
- Windows OpenEXR support may require additional configuration

## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.




================================================
FILE: gain_map_extract.py
================================================
#!/usr/bin/env python3

import os
from PIL import Image
import pillow_heif
import numpy as np
from pathlib import Path
import json
import base64

def extract_all_images(input_path, output_dir=None):
    """
    Extract all images from a HEIC file including base image, gain map, depth map, and all auxiliary images.
    Also dumps all metadata into a JSON file.
    
    Args:
        input_path (str): Path to input HDR image (HEIC or JPEG)
        output_dir (str, optional): Directory for output files. If None, will use input file's directory.
    """
    input_path = Path(input_path)
    
    # Create output directory if not provided
    if output_dir is None:
        output_dir = input_path.parent
    else:
        output_dir = Path(output_dir)
        output_dir.mkdir(parents=True, exist_ok=True)
    
    # Read HEIC file
    heif_file = pillow_heif.read_heif(str(input_path))
    
    # Dictionary to store all extracted images and their paths
    extracted_images = {}
    
    # Get primary image
    base_image = Image.frombytes(
        heif_file.mode,
        heif_file.size,
        heif_file.data,
        "raw",
        heif_file.mode,
        heif_file.stride,
    )
    base_path = output_dir / f"{input_path.stem}_base.tiff"
    base_image.save(base_path, format='TIFF')
    extracted_images['base'] = str(base_path)
    
    # Extract all auxiliary images
    if 'aux' in heif_file.info:
        for aux_type, aux_ids in heif_file.info['aux'].items():
            for aux_id in aux_ids:
                try:
                    aux_image = heif_file.get_aux_image(aux_id)
                    aux_pil = Image.frombytes(
                        aux_image.mode,
                        aux_image.size,
                        aux_image.data,
                        "raw",
                        aux_image.mode,
                        aux_image.stride,
                    )
                    
                    # Create a sanitized filename from the aux type
                    aux_type_name = aux_type.split(':')[-1]
                    aux_path = output_dir / f"{input_path.stem}_{aux_type_name}_{aux_id}.tiff"
                    aux_pil.save(aux_path, format='TIFF')
                    extracted_images[f"{aux_type_name}_{aux_id}"] = str(aux_path)
                except Exception as e:
                    print(f"Warning: Could not extract auxiliary image {aux_id} of type {aux_type}: {str(e)}")
    
    # Extract depth images if available
    if 'depth_images' in heif_file.info and heif_file.info['depth_images']:
        for i, depth_image in enumerate(heif_file.info['depth_images']):
            depth_pil = Image.frombytes(
                depth_image.mode,
                depth_image.size,
                depth_image.data,
                "raw",
                depth_image.mode,
                depth_image.stride,
            )
            depth_path = output_dir / f"{input_path.stem}_depth_{i}.tiff"
            depth_pil.save(depth_path, format='TIFF')
            extracted_images[f"depth_{i}"] = str(depth_path)
    
    # Prepare metadata
    metadata = {
        'info': {},
        'aux_images': {},
        'depth_images': [],
        'icc_profile': None,
        'exif': None,
        'xmp': None,
        'primary': {
            'mode': heif_file.mode,
            'size': heif_file.size,
            'stride': heif_file.stride
        }
    }
    
    # Copy all info
    for key, value in heif_file.info.items():
        if isinstance(value, (str, int, float, bool, type(None))):
            metadata['info'][key] = value
        elif isinstance(value, bytes):
            # Convert bytes to base64 for JSON serialization
            metadata['info'][key] = base64.b64encode(value).decode('utf-8')
        elif isinstance(value, dict):
            metadata['info'][key] = {
                k: base64.b64encode(v).decode('utf-8') if isinstance(v, bytes) else v
                for k, v in value.items()
            }
    
    # Handle ICC profile
    if 'icc_profile' in heif_file.info:
        metadata['icc_profile'] = base64.b64encode(heif_file.info['icc_profile']).decode('utf-8')
    
    # Handle EXIF
    if 'exif' in heif_file.info:
        metadata['exif'] = base64.b64encode(heif_file.info['exif']).decode('utf-8')
    
    # Handle XMP
    if 'xmp' in heif_file.info:
        metadata['xmp'] = base64.b64encode(heif_file.info['xmp']).decode('utf-8')
    
    # Save metadata to file
    metadata_path = output_dir / f"{input_path.stem}_metadata.json"
    with open(metadata_path, 'w') as f:
        json.dump(metadata, f, indent=2)
    
    # Return paths and metadata
    result = {
        'extracted_images': extracted_images,
        'metadata_path': str(metadata_path)
    }
    
    return result

if __name__ == "__main__":
    import argparse
    
    parser = argparse.ArgumentParser(description='Extract all images and metadata from HEIC files')
    parser.add_argument('input', help='Input HEIC image path')
    parser.add_argument('--output-dir', help='Output directory for extracted images')
    
    args = parser.parse_args()
    
    try:
        result = extract_all_images(args.input, args.output_dir)
        print("\nExtracted images:")
        for name, path in result['extracted_images'].items():
            print(f"{name}: {path}")
        print(f"\nMetadata saved to: {result['metadata_path']}")
    except Exception as e:
        print(f"Error: {str(e)}")


================================================
FILE: heic_to_exr.py
================================================
#!/usr/bin/env python3

import os
import sys
import tempfile
import shutil
from pathlib import Path
from PIL import Image
import pillow_heif
import numpy as np
import subprocess
import json

def extract_heic(input_path, output_dir):
    """Extract all images from HEIC file to TIFFs."""
    print(f"\nExtracting images from {input_path}...")
    
    heif_file = pillow_heif.read_heif(str(input_path))
    print(f"HEIC info: {heif_file.info}")
    
    # Initialize paths
    base_path = None
    gain_map_path = None
    depth_path = None
    matte_paths = []
    headroom = None
    
    # Extract base image
    print("\nExtracting base image...")
    base_image = Image.frombytes(
        heif_file.mode,
        heif_file.size,
        heif_file.data,
        "raw",
        heif_file.mode,
        heif_file.stride,
    )
    base_path = output_dir / "input_base.tiff"
    base_image.save(base_path, format='TIFF')
    print(f"Saved base image to {base_path}")
    
    # Extract gain map
    print("\nLooking for gain map...")
    if 'aux' in heif_file.info:
        print(f"Found aux data: {heif_file.info['aux']}")
        if 'urn:com:apple:photo:2020:aux:hdrgainmap' in heif_file.info['aux']:
            try:
                aux_id = heif_file.info['aux']['urn:com:apple:photo:2020:aux:hdrgainmap'][0]
                print(f"Found gain map aux ID: {aux_id}")
                aux_image = heif_file.get_aux_image(aux_id)
                gain_map = Image.frombytes(
                    aux_image.mode,
                    aux_image.size,
                    aux_image.data,
                    "raw",
                    aux_image.mode,
                    aux_image.stride,
                )
                gain_map_path = output_dir / "input_hdrgainmap_50.tiff"
                gain_map.save(gain_map_path, format='TIFF')
                print(f"Saved gain map to {gain_map_path}")
            except Exception as e:
                print(f"Warning: Could not extract gain map: {str(e)}")
        else:
            print("No gain map found in aux data")
    else:
        print("No aux data found in HEIC")
    
    # Extract depth map
    print("\nLooking for depth map...")
    if 'depth_images' in heif_file.info and heif_file.info['depth_images']:
        try:
            depth_image = heif_file.info['depth_images'][0]
            depth_map = Image.frombytes(
                depth_image.mode,
                depth_image.size,
                depth_image.data,
                "raw",
                depth_image.mode,
                depth_image.stride,
            )
            depth_path = output_dir / "input_depth_0.tiff"
            depth_map.save(depth_path, format='TIFF')
            print(f"Saved depth map to {depth_path}")
        except Exception as e:
            print(f"Warning: Could not extract depth map: {str(e)}")
    else:
        print("No depth map found")
    
    # Extract mattes
    print("\nLooking for mattes...")
    if 'aux' in heif_file.info:
        for aux_type, aux_ids in heif_file.info['aux'].items():
            if 'matte' in aux_type.lower():
                print(f"Found matte type: {aux_type}")
                for aux_id in aux_ids:
                    try:
                        aux_image = heif_file.get_aux_image(aux_id)
                        aux_pil = Image.frombytes(
                            aux_image.mode,
                            aux_image.size,
                            aux_image.data,
                            "raw",
                            aux_image.mode,
                            aux_image.stride,
                        )
                        aux_type_name = aux_type.split(':')[-1]
                        aux_path = output_dir / f"input_{aux_type_name}_{aux_id}.tiff"
                        aux_pil.save(aux_path, format='TIFF')
                        matte_paths.append(aux_path)
                        print(f"Saved matte {aux_id} to {aux_path}")
                    except Exception as e:
                        print(f"Warning: Could not extract matte {aux_id}: {str(e)}")
    else:
        print("No mattes found")
    
    # Get HDR headroom
    if 'HDRGainMapHeadroom' in heif_file.info:
        headroom = heif_file.info['HDRGainMapHeadroom']
        print(f"\nFound HDR headroom: {headroom}")
    else:
        print("\nNo HDR headroom found in HEIC info")
    
    return base_path, gain_map_path, depth_path, matte_paths, headroom

def merge_to_exr(input_dir, original_heic, output_path):
    """Merge extracted TIFFs into a multilayer EXR."""
    print("\nMerging to EXR...")
    
    # Get dimensions from base image
    print("Getting image dimensions...")
    base_info = subprocess.check_output(['oiiotool', '--info', str(input_dir / "input_base.tiff")]).decode()
    print(f"Base image info: {base_info}")
    width = int(base_info.split()[2])
    height = int(base_info.split()[4].rstrip(','))
    print(f"Image dimensions: {width}x{height}")

    # Process base image (RGB) - Convert from sRGB curve through Linear P3 to ACEScg
    print("\nProcessing base image...")
    subprocess.run([
        'oiiotool', str(input_dir / "input_base.tiff"),
        '--ch', 'R,G,B',
        '--chnames', 'sdr.R,sdr.G,sdr.B',
        '--colorconfig', 'studio-config-v1.0.0_aces-v1.3_ocio-v2.1.ocio',
        '--colorconvert', 'sRGB - Texture', 'Linear Rec.709 (sRGB)',
        '--colorconvert', 'Linear P3-D65', 'ACES - ACEScg',
        '-o', str(input_dir / "base.exr")
    ], check=True)
    print("Base image processed")

    # Process gain map if it exists
    gain_map_path = input_dir / "input_hdrgainmap_50.tiff"
    if gain_map_path.exists():
        print("\nProcessing gain map...")
        # Process gain map (Y) - Convert from Rec709 curve to Linear
        subprocess.run([
            'oiiotool', str(gain_map_path),
            '--ch', 'Y',
            '--chnames', 'gainmap.Y',
            '--resize', f"{width}x{height}",
            '--colorconfig', 'studio-config-v1.0.0_aces-v1.3_ocio-v2.1.ocio',
            '--ocionamedtransform', 'Rec.709 - Curve',
            '-o', str(input_dir / "gainmap.exr")
        ], check=True)
        print("Gain map processed")

        # Create 3-channel gainmap by duplicating Y to RGB
        subprocess.run([
            'oiiotool', str(input_dir / "gainmap.exr"),
            '--ch', 'gainmap.Y,gainmap.Y,gainmap.Y',
            '--chnames', 'gainmap.R,gainmap.G,gainmap.B',
            '-o', str(input_dir / "gainmap_rgb.exr")
        ], check=True)
        print("Gain map converted to RGB")

        # Calculate HDR: first multiply gainmap by (headroom - 1.0)
        headroom = float(subprocess.check_output(['exiftool', '-HDRGainMapHeadroom', '-b', str(original_heic)]).decode())
        print(f"Using HDR headroom: {headroom}")
        subprocess.run([
            'oiiotool', str(input_dir / "gainmap_rgb.exr"),
            '--mulc', str(headroom - 1.0),
            '--addc', '1.0',
            '-o', str(input_dir / "gainmap_scaled.exr")
        ], check=True)
        print("Gain map scaled")

        # Then multiply base image by scaled gainmap
        subprocess.run([
            'oiiotool', str(input_dir / "base.exr"),
            str(input_dir / "gainmap_scaled.exr"),
            '--mul',
            '--chnames', 'R,G,B',
            '-o', str(input_dir / "hdr_base.exr")
        ], check=True)
        print("HDR base created")
    else:
        print("\nNo gain map found, using base image as HDR base")
        shutil.copy(str(input_dir / "base.exr"), str(input_dir / "hdr_base.exr"))

    # Process depth if it exists
    depth_path = input_dir / "input_depth_0.tiff"
    if depth_path.exists():
        print("\nProcessing depth map...")
        subprocess.run([
            'oiiotool', str(depth_path),
            '--ch', 'Y',
            '--chnames', 'depth.Y',
            '--resize', f"{width}x{height}",
            '-o', str(input_dir / "depth.exr")
        ], check=True)
        print("Depth map processed")
    else:
        print("\nNo depth map found")

    # Process mattes
    print("\nProcessing mattes...")
    for matte in input_dir.glob("input_*matte_*.tiff"):
        if matte.exists():
            clean_name = matte.stem.replace("input_", "").replace("matte_", "")
            print(f"Processing matte: {clean_name}")
            subprocess.run([
                'oiiotool', str(matte),
                '--ch', 'Y',
                '--chnames', f"mattes.{clean_name}.Y",
                '--resize', f"{width}x{height}",
                '-o', str(input_dir / f"{clean_name}.exr")
            ], check=True)
            print(f"Matte {clean_name} processed")
    else:
        print("No mattes found")

    # Create final EXR with HDR as main RGB
    print("\nCreating final EXR...")
    subprocess.run([
        'oiiotool', str(input_dir / "hdr_base.exr"),
        '--ch', 'R,G,B',
        '-o', str(input_dir / "final.exr")
    ], check=True)
    print("Base layer created")

    # Add SDR layer
    print("Adding SDR layer...")
    subprocess.run([
        'oiiotool', str(input_dir / "final.exr"),
        str(input_dir / "base.exr"),
        '--ch', 'sdr.R,sdr.G,sdr.B',
        '--siappend',
        '-o', str(input_dir / "final.exr")
    ], check=True)
    print("SDR layer added")

    # Add gainmap layer if it exists
    if gain_map_path.exists():
        print("Adding gainmap layer...")
        subprocess.run([
            'oiiotool', str(input_dir / "final.exr"),
            str(input_dir / "gainmap_rgb.exr"),
            '--ch', 'gainmap.R,gainmap.G,gainmap.B',
            '--siappend',
            '-o', str(input_dir / "final.exr")
        ], check=True)
        print("Gainmap layer added")

    # Add depth layer if it exists
    if depth_path.exists():
        print("Adding depth layer...")
        subprocess.run([
            'oiiotool', str(input_dir / "final.exr"),
            str(input_dir / "depth.exr"),
            '--ch', 'depth.Y',
            '--siappend',
            '-o', str(input_dir / "final.exr")
        ], check=True)
        print("Depth layer added")

    # Add matte layers
    print("Adding matte layers...")
    for matte in input_dir.glob("*.exr"):
        if matte.stem.startswith("semantic"):
            clean_name = matte.stem
            print(f"Adding matte layer: {clean_name}")
            subprocess.run([
                'oiiotool', str(input_dir / "final.exr"),
                str(matte),
                '--ch', f"mattes.{clean_name}.Y",
                '--siappend',
                '-o', str(input_dir / "final.exr")
            ], check=True)
            print(f"Matte layer {clean_name} added")

    # Move to final destination
    print(f"\nMoving final EXR to {output_path}")
    shutil.move(str(input_dir / "final.exr"), str(output_path))
    print("Done!")

def main():
    if len(sys.argv) != 2:
        print("Usage: python heic_to_exr.py <input.heic>")
        sys.exit(1)

    input_path = Path(sys.argv[1])
    if not input_path.exists():
        print(f"Error: Input file {input_path} does not exist")
        sys.exit(1)

    # Create output path next to input file
    output_path = input_path.parent / f"{input_path.stem}_acesCG.exr"

    # Create temporary directory
    with tempfile.TemporaryDirectory() as temp_dir:
        temp_dir = Path(temp_dir)
        print(f"Using temporary directory: {temp_dir}")
        
        # Extract images from HEIC
        base_path, gain_map_path, depth_path, matte_paths, headroom = extract_heic(input_path, temp_dir)
        
        # Merge to EXR
        merge_to_exr(temp_dir, input_path, output_path)

    print(f"\nSuccessfully created: {output_path}")

if __name__ == "__main__":
    main() 

================================================
FILE: merge_to_exr.sh
================================================
#!/bin/bash

if [ $# -lt 2 ]; then
    echo "Usage: ./merge_to_exr.sh <input_folder> <original.HEIC> [output.exr]"
    exit 1
fi

input_folder="$1"
original_heic="$2"
output_path="${3:-output_acesCG.exr}"

# Create a temporary directory for intermediate files
temp_dir=$(mktemp -d)
echo "Using temporary directory: $temp_dir"

# Get dimensions from base image
base_info=$(oiiotool --info "$input_folder/input_base.tiff" | head -n1)
width=$(echo "$base_info" | cut -d' ' -f3)
height=$(echo "$base_info" | cut -d' ' -f5 | tr -d ',')

if [ -z "$width" ] || [ -z "$height" ]; then
    echo "Error: Could not determine image dimensions"
    echo "Debug info: $base_info"
    exit 1
fi
echo "Image dimensions: ${width}x${height}"

# Extract headroom from original HEIC
headroom=$(exiftool -HDRGainMapHeadroom -b "$original_heic")
if [ -z "$headroom" ]; then
    echo "Error: Could not extract HDR headroom"
    exit 1
fi
echo "Extracted HDR headroom: $headroom"

# List all input files
echo "Input files found:"
ls -1 "$input_folder"/*.tiff

# Process base image (RGB) - Convert from sRGB curve through Linear P3 to ACEScg
echo "Processing base image..."
oiiotool "$input_folder/input_base.tiff" \
    --ch R,G,B \
    --chnames sdr.R,sdr.G,sdr.B \
    --colorconfig studio-config-v1.0.0_aces-v1.3_ocio-v2.1.ocio \
    --colorconvert "sRGB - Texture" "Linear Rec.709 (sRGB)" \
    --colorconvert "Linear P3-D65" "ACES - ACEScg" \
    -o "$temp_dir/base.exr" || exit 1

# Process gain map (Y) - Convert from Rec709 curve to Linear
echo "Processing gain map..."
oiiotool "$input_folder/input_hdrgainmap_50.tiff" \
    --ch Y \
    --chnames gainmap.Y \
    --resize "${width}x${height}" \
    --colorconfig studio-config-v1.0.0_aces-v1.3_ocio-v2.1.ocio \
    --ocionamedtransform "Rec.709 - Curve" \
    -o "$temp_dir/gainmap.exr" || exit 1

# Process depth (Y)
echo "Processing depth map..."
oiiotool "$input_folder/input_depth_0.tiff" \
    --ch Y \
    --chnames depth.Y \
    --resize "${width}x${height}" \
    -o "$temp_dir/depth.exr" || exit 1

# Process all mattes (Y)
echo "Processing mattes..."
for matte in "$input_folder"/input_*matte_*.tiff; do
    if [ -f "$matte" ]; then
        name=$(basename "$matte" .tiff)
        # Clean up the matte name to be more Nuke-friendly
        clean_name=$(echo "$name" | sed 's/input_//' | sed 's/matte_//')
        echo "Processing matte: $clean_name"
        oiiotool "$matte" \
            --ch Y \
            --chnames "mattes.$clean_name.Y" \
            --resize "${width}x${height}" \
            -o "$temp_dir/$clean_name.exr" || exit 1
    else
        echo "Warning: No matte files found matching pattern: $matte"
    fi
done

# Apply HDR formula: hdr_rgb = sdr_rgb * (1.0 + (headroom - 1.0) * gainmap)
echo "Applying HDR formula..."
# Create 3-channel gainmap by duplicating Y to RGB
oiiotool "$temp_dir/gainmap.exr" \
    --ch gainmap.Y,gainmap.Y,gainmap.Y \
    --chnames R,G,B \
    -o "$temp_dir/gainmap_rgb.exr" || exit 1

# Calculate HDR: first multiply gainmap by (headroom - 1.0)
oiiotool "$temp_dir/gainmap_rgb.exr" \
    --mulc "$(echo "$headroom - 1.0" | bc -l)" \
    --addc 1.0 \
    -o "$temp_dir/gainmap_scaled.exr" || exit 1

# Then multiply base image by scaled gainmap
oiiotool "$temp_dir/base.exr" \
    "$temp_dir/gainmap_scaled.exr" \
    --mul \
    --chnames R,G,B \
    -o "$temp_dir/hdr_base.exr" || exit 1

# Create final EXR
echo "Creating final multilayer EXR..."

# First, create with HDR as main RGB
oiiotool "$temp_dir/hdr_base.exr" \
    --ch R,G,B \
    -o "$temp_dir/final.exr" || exit 1

# Add SDR layer
oiiotool "$temp_dir/final.exr" "$temp_dir/base.exr" \
    --ch sdr.R,sdr.G,sdr.B \
    --siappend \
    -o "$temp_dir/final.exr" || exit 1

# Add gainmap layer (using the RGB version we created earlier)
oiiotool "$temp_dir/final.exr" "$temp_dir/gainmap_rgb.exr" \
    --ch R,G,B \
    --chnames gainmap.R,gainmap.G,gainmap.B \
    --siappend \
    -o "$temp_dir/final.exr" || exit 1

# Add depth layer
oiiotool "$temp_dir/final.exr" "$temp_dir/depth.exr" \
    --ch depth.Y \
    --siappend \
    -o "$temp_dir/final.exr" || exit 1

# Add matte layers
for m in "$temp_dir"/semantic*.exr; do
    if [ -f "$m" ]; then
        clean_name=$(basename "$m" .exr)
        oiiotool "$temp_dir/final.exr" "$m" \
            --ch "mattes.$clean_name.Y" \
            --siappend \
            -o "$temp_dir/final.exr" || exit 1
    fi
done

# Move to final destination
mv "$temp_dir/final.exr" "$output_path"

# Clean up temporary files
rm -rf "$temp_dir"

echo "Successfully merged TIFFs into: $output_path" 

================================================
FILE: requirements.txt
================================================
Pillow>=10.0.0
pillow-heif>=0.13.0
numpy>=1.24.0
defusedxml>=0.7.1 

================================================
FILE: studio-config-v1.0.0_aces-v1.3_ocio-v2.1.ocio
================================================
ocio_profile_version: 2.1

environment:
  {}
search_path: ""
strictparsing: true
luma: [0.2126, 0.7152, 0.0722]
name: studio-config-v1.0.0_aces-v1.3_ocio-v2.1
description: |
  Academy Color Encoding System - Studio Config [COLORSPACES v1.0.0] [ACES v1.3] [OCIO v2.1]
  ------------------------------------------------------------------------------------------
  
  This "OpenColorIO" config is geared toward studios requiring a config that includes a wide variety of camera colorspaces, displays and looks.
  
  Generated with "OpenColorIO-Config-ACES" v1.0.0 on the 2022/10/26 at 05:59.

roles:
  aces_interchange: ACES2065-1
  cie_xyz_d65_interchange: CIE-XYZ-D65
  color_picking: sRGB - Texture
  color_timing: ACEScct
  compositing_log: ACEScct
  data: Raw
  matte_paint: sRGB - Texture
  scene_linear: ACEScg
  texture_paint: ACEScct

file_rules:
  - !<Rule> {name: Default, colorspace: ACES2065-1}

shared_views:
  - !<View> {name: ACES 1.0 - SDR Video, view_transform: ACES 1.0 - SDR Video, display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.0 - SDR Video (D60 sim on D65), view_transform: ACES 1.0 - SDR Video (D60 sim on D65), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - SDR Video (P3 lim), view_transform: ACES 1.1 - SDR Video (P3 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - SDR Video (Rec.709 lim), view_transform: ACES 1.1 - SDR Video (Rec.709 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim), view_transform: ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - HDR Video (2000 nits & Rec.2020 lim), view_transform: ACES 1.1 - HDR Video (2000 nits & Rec.2020 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - HDR Video (4000 nits & Rec.2020 lim), view_transform: ACES 1.1 - HDR Video (4000 nits & Rec.2020 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - HDR Video (1000 nits & P3 lim), view_transform: ACES 1.1 - HDR Video (1000 nits & P3 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - HDR Video (2000 nits & P3 lim), view_transform: ACES 1.1 - HDR Video (2000 nits & P3 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - HDR Video (4000 nits & P3 lim), view_transform: ACES 1.1 - HDR Video (4000 nits & P3 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.0 - SDR Cinema, view_transform: ACES 1.0 - SDR Cinema, display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - SDR Cinema (D60 sim on D65), view_transform: ACES 1.1 - SDR Cinema (D60 sim on D65), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - SDR Cinema (Rec.709 lim), view_transform: ACES 1.1 - SDR Cinema (Rec.709 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.0 - SDR Cinema (D60 sim on DCI), view_transform: ACES 1.0 - SDR Cinema (D60 sim on DCI), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - SDR Cinema (D65 sim on DCI), view_transform: ACES 1.1 - SDR Cinema (D65 sim on DCI), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: ACES 1.1 - HDR Cinema (108 nits & P3 lim), view_transform: ACES 1.1 - HDR Cinema (108 nits & P3 lim), display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: Un-tone-mapped, view_transform: Un-tone-mapped, display_colorspace: <USE_DISPLAY_NAME>}

displays:
  sRGB - Display:
    - !<View> {name: Raw, colorspace: Raw}
    - !<Views> [ACES 1.0 - SDR Video, ACES 1.0 - SDR Video (D60 sim on D65), Un-tone-mapped]
  Rec.1886 Rec.709 - Display:
    - !<View> {name: Raw, colorspace: Raw}
    - !<Views> [ACES 1.0 - SDR Video, ACES 1.0 - SDR Video (D60 sim on D65), Un-tone-mapped]
  Rec.1886 Rec.2020 - Display:
    - !<View> {name: Raw, colorspace: Raw}
    - !<Views> [ACES 1.0 - SDR Video, ACES 1.1 - SDR Video (P3 lim), ACES 1.1 - SDR Video (Rec.709 lim), Un-tone-mapped]
  Rec.2100-HLG - Display:
    - !<View> {name: Raw, colorspace: Raw}
    - !<Views> [ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim), Un-tone-mapped]
  Rec.2100-PQ - Display:
    - !<View> {name: Raw, colorspace: Raw}
    - !<Views> [ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim), ACES 1.1 - HDR Video (2000 nits & Rec.2020 lim), ACES 1.1 - HDR Video (4000 nits & Rec.2020 lim), Un-tone-mapped]
  ST2084-P3-D65 - Display:
    - !<View> {name: Raw, colorspace: Raw}
    - !<Views> [ACES 1.1 - HDR Video (1000 nits & P3 lim), ACES 1.1 - HDR Video (2000 nits & P3 lim), ACES 1.1 - HDR Video (4000 nits & P3 lim), ACES 1.1 - HDR Cinema (108 nits & P3 lim), Un-tone-mapped]
  P3-D60 - Display:
    - !<View> {name: Raw, colorspace: Raw}
    - !<Views> [ACES 1.0 - SDR Cinema, Un-tone-mapped]
  P3-D65 - Display:
    - !<View> {name: Raw, colorspace: Raw}
    - !<Views> [ACES 1.0 - SDR Cinema, ACES 1.1 - SDR Cinema (D60 sim on D65), ACES 1.1 - SDR Cinema (Rec.709 lim), Un-tone-mapped]
  P3-DCI - Display:
    - !<View> {name: Raw, colorspace: Raw}
    - !<Views> [ACES 1.0 - SDR Cinema (D60 sim on DCI), ACES 1.1 - SDR Cinema (D65 sim on DCI), Un-tone-mapped]

active_displays: [sRGB - Display, Rec.1886 Rec.709 - Display, Rec.1886 Rec.2020 - Display, Rec.2100-HLG - Display, Rec.2100-PQ - Display, ST2084-P3-D65 - Display, P3-D60 - Display, P3-D65 - Display, P3-DCI - Display]
active_views: [ACES 1.0 - SDR Video, ACES 1.0 - SDR Video (D60 sim on D65), ACES 1.1 - SDR Video (P3 lim), ACES 1.1 - SDR Video (Rec.709 lim), ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim), ACES 1.1 - HDR Video (2000 nits & Rec.2020 lim), ACES 1.1 - HDR Video (4000 nits & Rec.2020 lim), ACES 1.1 - HDR Video (1000 nits & P3 lim), ACES 1.1 - HDR Video (2000 nits & P3 lim), ACES 1.1 - HDR Video (4000 nits & P3 lim), ACES 1.0 - SDR Cinema, ACES 1.1 - SDR Cinema (D60 sim on D65), ACES 1.1 - SDR Cinema (Rec.709 lim), ACES 1.0 - SDR Cinema (D60 sim on DCI), ACES 1.1 - SDR Cinema (D65 sim on DCI), ACES 1.1 - HDR Cinema (108 nits & P3 lim), Un-tone-mapped, Raw]
inactive_colorspaces: [CIE-XYZ-D65, sRGB - Display, Rec.1886 Rec.709 - Display, Rec.1886 Rec.2020 - Display, sRGB - Display, Rec.1886 Rec.709 - Display, Rec.1886 Rec.2020 - Display, Rec.1886 Rec.2020 - Display, Rec.2100-HLG - Display, Rec.2100-PQ - Display, Rec.2100-PQ - Display, Rec.2100-PQ - Display, ST2084-P3-D65 - Display, ST2084-P3-D65 - Display, ST2084-P3-D65 - Display, P3-D60 - Display, P3-D65 - Display, P3-D65 - Display, P3-D65 - Display, P3-DCI - Display, P3-DCI - Display, ST2084-P3-D65 - Display]

looks:
  - !<Look>
    name: ACES 1.3 Reference Gamut Compression
    process_space: ACES2065-1
    description: |
      LMT (applied in ACES2065-1) to compress scene-referred values from common cameras into the AP1 gamut
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:LMT.Academy.GamutCompress.a1.3.0
    transform: !<BuiltinTransform> {style: ACES-LMT - ACES 1.3 Reference Gamut Compression}


default_view_transform: Un-tone-mapped

view_transforms:
  - !<ViewTransform>
    name: ACES 1.0 - SDR Video
    description: |
      Component of ACES Output Transforms for SDR D65 video
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.RGBmonitor_100nits_dim.a1.0.3
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.Rec709_100nits_dim.a1.0.3
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.Rec2020_100nits_dim.a1.0.3
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-VIDEO_1.0}

  - !<ViewTransform>
    name: ACES 1.0 - SDR Video (D60 sim on D65)
    description: |
      Component of ACES Output Transforms for SDR D65 video simulating D60 white
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.RGBmonitor_D60sim_100nits_dim.a1.0.3
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.Rec709_D60sim_100nits_dim.a1.0.3
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-VIDEO-D60sim-D65_1.0}

  - !<ViewTransform>
    name: ACES 1.1 - SDR Video (P3 lim)
    description: |
      Component of ACES Output Transforms for SDR D65 video
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.Rec2020_P3D65limited_100nits_dim.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-VIDEO-P3lim_1.1}

  - !<ViewTransform>
    name: ACES 1.1 - SDR Video (Rec.709 lim)
    description: |
      Component of ACES Output Transforms for SDR D65 video
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.Rec2020_Rec709limited_100nits_dim.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-VIDEO-REC709lim_1.1}

  - !<ViewTransform>
    name: ACES 1.1 - HDR Video (1000 nits & Rec.2020 lim)
    description: |
      Component of ACES Output Transforms for 1000 nit HDR D65 video
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:RRTODT.Academy.Rec2020_1000nits_15nits_HLG.a1.1.0
      ACEStransformID: urn:ampas:aces:transformId:v1.5:RRTODT.Academy.Rec2020_1000nits_15nits_ST2084.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - HDR-VIDEO-1000nit-15nit-REC2020lim_1.1}

  - !<ViewTransform>
    name: ACES 1.1 - HDR Video (2000 nits & Rec.2020 lim)
    description: |
      Component of ACES Output Transforms for 2000 nit HDR D65 video
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:RRTODT.Academy.Rec2020_2000nits_15nits_ST2084.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - HDR-VIDEO-2000nit-15nit-REC2020lim_1.1}

  - !<ViewTransform>
    name: ACES 1.1 - HDR Video (4000 nits & Rec.2020 lim)
    description: |
      Component of ACES Output Transforms for 4000 nit HDR D65 video
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:RRTODT.Academy.Rec2020_4000nits_15nits_ST2084.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - HDR-VIDEO-4000nit-15nit-REC2020lim_1.1}

  - !<ViewTransform>
    name: ACES 1.1 - HDR Video (1000 nits & P3 lim)
    description: |
      Component of ACES Output Transforms for 1000 nit HDR D65 video
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:RRTODT.Academy.P3D65_1000nits_15nits_ST2084.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - HDR-VIDEO-1000nit-15nit-P3lim_1.1}

  - !<ViewTransform>
    name: ACES 1.1 - HDR Video (2000 nits & P3 lim)
    description: |
      Component of ACES Output Transforms for 2000 nit HDR D65 video
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:RRTODT.Academy.P3D65_2000nits_15nits_ST2084.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - HDR-VIDEO-2000nit-15nit-P3lim_1.1}

  - !<ViewTransform>
    name: ACES 1.1 - HDR Video (4000 nits & P3 lim)
    description: |
      Component of ACES Output Transforms for 4000 nit HDR D65 video
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:RRTODT.Academy.P3D65_4000nits_15nits_ST2084.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - HDR-VIDEO-4000nit-15nit-P3lim_1.1}

  - !<ViewTransform>
    name: ACES 1.0 - SDR Cinema
    description: |
      Component of ACES Output Transforms for SDR cinema
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.P3D60_48nits.a1.0.3
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.P3D65_48nits.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-CINEMA_1.0}

  - !<ViewTransform>
    name: ACES 1.1 - SDR Cinema (D60 sim on D65)
    description: |
      Component of ACES Output Transforms for SDR D65 cinema simulating D60 white
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.P3D65_D60sim_48nits.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-CINEMA-D60sim-D65_1.1}

  - !<ViewTransform>
    name: ACES 1.1 - SDR Cinema (Rec.709 lim)
    description: |
      Component of ACES Output Transforms for SDR cinema
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.P3D65_Rec709limited_48nits.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-CINEMA-REC709lim_1.1}

  - !<ViewTransform>
    name: ACES 1.0 - SDR Cinema (D60 sim on DCI)
    description: |
      Component of ACES Output Transforms for SDR DCI cinema simulating D60 white
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.P3DCI_48nits.a1.0.3
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-CINEMA-D60sim-DCI_1.0}

  - !<ViewTransform>
    name: ACES 1.1 - SDR Cinema (D65 sim on DCI)
    description: |
      Component of ACES Output Transforms for SDR DCI cinema simulating D65 white
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ODT.Academy.P3DCI_D65sim_48nits.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-CINEMA-D65sim-DCI_1.1}

  - !<ViewTransform>
    name: ACES 1.1 - HDR Cinema (108 nits & P3 lim)
    description: |
      Component of ACES Output Transforms for 108 nit HDR D65 cinema
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:RRTODT.Academy.P3D65_108nits_7point2nits_ST2084.a1.1.0
    from_scene_reference: !<BuiltinTransform> {style: ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - HDR-CINEMA-108nit-7.2nit-P3lim_1.1}

  - !<ViewTransform>
    name: Un-tone-mapped
    from_scene_reference: !<BuiltinTransform> {style: UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD}

display_colorspaces:
  - !<ColorSpace>
    name: CIE-XYZ-D65
    aliases: [cie_xyz_d65]
    family: ""
    equalitygroup: ""
    bitdepth: 32f
    description: The "CIE XYZ (D65)" display connection colorspace.
    isdata: false
    allocation: uniform

  - !<ColorSpace>
    name: sRGB - Display
    aliases: [srgb_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to sRGB (piecewise EOTF)
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_sRGB}

  - !<ColorSpace>
    name: Rec.1886 Rec.709 - Display
    aliases: [rec1886_rec709_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to Rec.1886/Rec.709 (HD video)
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_REC.1886-REC.709}

  - !<ColorSpace>
    name: Rec.1886 Rec.2020 - Display
    aliases: [rec1886_rec2020_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to Rec.1886/Rec.2020 (UHD video)
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_REC.1886-REC.2020}

  - !<ColorSpace>
    name: Rec.2100-HLG - Display
    aliases: [rec2100_hlg_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to Rec.2100-HLG, 1000 nit
    isdata: false
    categories: [file-io]
    encoding: hdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_REC.2100-HLG-1000nit}

  - !<ColorSpace>
    name: Rec.2100-PQ - Display
    aliases: [rec2100_pq_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to Rec.2100-PQ
    isdata: false
    categories: [file-io]
    encoding: hdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_REC.2100-PQ}

  - !<ColorSpace>
    name: ST2084-P3-D65 - Display
    aliases: [st2084_p3d65_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to ST-2084 (PQ), P3-D65 primaries
    isdata: false
    categories: [file-io]
    encoding: hdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_ST2084-P3-D65}

  - !<ColorSpace>
    name: P3-D60 - Display
    aliases: [p3d60_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to Gamma 2.6, P3-D60 (Bradford adaptation)
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_G2.6-P3-D60-BFD}

  - !<ColorSpace>
    name: P3-D65 - Display
    aliases: [p3d65_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to Gamma 2.6, P3-D65
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_G2.6-P3-D65}

  - !<ColorSpace>
    name: P3-DCI - Display
    aliases: [p3_dci_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to Gamma 2.6, P3-DCI (DCI white with Bradford adaptation)
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_G2.6-P3-DCI-BFD}

colorspaces:
  - !<ColorSpace>
    name: ACES2065-1
    aliases: [aces2065_1, ACES - ACES2065-1, lin_ap0]
    family: ACES
    equalitygroup: ""
    bitdepth: 32f
    description: The "Academy Color Encoding System" reference colorspace.
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform

  - !<ColorSpace>
    name: ACEScc
    aliases: [ACES - ACEScc, acescc_ap1]
    family: ACES
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACEScc to ACES2065-1
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ACEScsc.Academy.ACEScc_to_ACES.a1.0.3
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<BuiltinTransform> {style: ACEScc_to_ACES2065-1}

  - !<ColorSpace>
    name: ACEScct
    aliases: [ACES - ACEScct, acescct_ap1]
    family: ACES
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACEScct to ACES2065-1
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ACEScsc.Academy.ACEScct_to_ACES.a1.0.3
    isdata: false
    categories: [file-io, working-space]
    encoding: log
    allocation: uniform
    to_scene_reference: !<BuiltinTransform> {style: ACEScct_to_ACES2065-1}

  - !<ColorSpace>
    name: ACEScg
    aliases: [ACES - ACEScg, lin_ap1]
    family: ACES
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACEScg to ACES2065-1
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ACEScsc.Academy.ACEScg_to_ACES.a1.0.3
    isdata: false
    categories: [file-io, working-space]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<BuiltinTransform> {style: ACEScg_to_ACES2065-1}

  - !<ColorSpace>
    name: ADX10
    aliases: [Input - ADX - ADX10]
    family: ACES
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ADX10 to ACES2065-1
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ACEScsc.Academy.ADX10_to_ACES.a1.0.3
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<BuiltinTransform> {style: ADX10_to_ACES2065-1}

  - !<ColorSpace>
    name: ADX16
    aliases: [Input - ADX - ADX16]
    family: ACES
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ADX16 to ACES2065-1
      
      ACEStransformID: urn:ampas:aces:transformId:v1.5:ACEScsc.Academy.ADX16_to_ACES.a1.0.3
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<BuiltinTransform> {style: ADX16_to_ACES2065-1}

  - !<ColorSpace>
    name: Linear ARRI Wide Gamut 3
    aliases: [lin_arri_wide_gamut_3, Input - ARRI - Linear - ALEXA Wide Gamut, lin_alexawide]
    family: Input/ARRI
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear ARRI Wide Gamut 3 to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:ARRI:Input:Linear_ARRI_Wide_Gamut_3_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear ARRI Wide Gamut 3 to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.680205505106279, 0.236136601606481, 0.0836578932872399, 0, 0.0854149797421404, 1.01747087860704, -0.102885858349182, 0, 0.00205652166929683, -0.0625625003847921, 1.0605059787155, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: ARRI LogC3 (EI800)
    aliases: [arri_logc3_ei800, Input - ARRI - V3 LogC (EI800) - Wide Gamut, logc3ei800_alexawide]
    family: Input/ARRI
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ARRI LogC3 (EI800) to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:ARRI:Input:ARRI_LogC3_EI800_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: ARRI LogC3 (EI800) to ACES2065-1
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.247189638318671, log_side_offset: 0.385536998692443, lin_side_slope: 5.55555555555556, lin_side_offset: 0.0522722750251688, lin_side_break: 0.0105909904954696, direction: inverse}
        - !<MatrixTransform> {matrix: [0.680205505106279, 0.236136601606481, 0.0836578932872399, 0, 0.0854149797421404, 1.01747087860704, -0.102885858349182, 0, 0.00205652166929683, -0.0625625003847921, 1.0605059787155, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear ARRI Wide Gamut 4
    aliases: [lin_arri_wide_gamut_4, lin_awg4]
    family: Input/ARRI
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear ARRI Wide Gamut 4 to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:ARRI:Input:Linear_ARRI_Wide_Gamut_4_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear ARRI Wide Gamut 4 to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.750957362824734, 0.144422786709757, 0.104619850465509, 0, 0.000821837079380207, 1.007397584885, -0.00821942196438358, 0, -0.000499952143533471, -0.000854177231436971, 1.00135412937497, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: ARRI LogC4
    aliases: [arri_logc4]
    family: Input/ARRI
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ARRI LogC4 to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:ARRI:Input:ARRI_LogC4_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: ARRI LogC4 to ACES2065-1
      children:
        - !<LogCameraTransform> {log_side_slope: 0.0647954196341293, log_side_offset: -0.295908392682586, lin_side_slope: 2231.82630906769, lin_side_offset: 64, lin_side_break: -0.0180569961199113, direction: inverse}
        - !<MatrixTransform> {matrix: [0.750957362824734, 0.144422786709757, 0.104619850465509, 0, 0.000821837079380207, 1.007397584885, -0.00821942196438358, 0, -0.000499952143533471, -0.000854177231436971, 1.00135412937497, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: BMDFilm WideGamut Gen5
    aliases: [bmdfilm_widegamut_gen5]
    family: Input/BlackmagicDesign
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Blackmagic Film Wide Gamut (Gen 5) to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:BlackmagicDesign:Input:BMDFilm_WideGamut_Gen5_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Blackmagic Film Wide Gamut (Gen 5) to ACES2065-1
      children:
        - !<LogCameraTransform> {base: 2.71828182845905, log_side_slope: 0.0869287606549122, log_side_offset: 0.530013339229194, lin_side_offset: 0.00549407243225781, lin_side_break: 0.005, direction: inverse}
        - !<MatrixTransform> {matrix: [0.647091325580708, 0.242595385134207, 0.110313289285085, 0, 0.0651915997328519, 1.02504756760476, -0.0902391673376125, 0, -0.0275570729194699, -0.0805887097177784, 1.10814578263725, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: DaVinci Intermediate WideGamut
    aliases: [davinci_intermediate_widegamut]
    family: Input/BlackmagicDesign
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert DaVinci Intermediate Wide Gamut to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:BlackmagicDesign:Input:DaVinci_Intermediate_WideGamut_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: DaVinci Intermediate Wide Gamut to ACES2065-1
      children:
        - !<LogCameraTransform> {log_side_slope: 0.07329248, log_side_offset: 0.51304736, lin_side_offset: 0.0075, lin_side_break: 0.00262409, linear_slope: 10.44426855, direction: inverse}
        - !<MatrixTransform> {matrix: [0.748270290272981, 0.167694659554328, 0.0840350501726906, 0, 0.0208421234689102, 1.11190474268894, -0.132746866157851, 0, -0.0915122574225729, -0.127746712807307, 1.21925897022988, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear BMD WideGamut Gen5
    aliases: [lin_bmd_widegamut_gen5]
    family: Input/BlackmagicDesign
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear Blackmagic Wide Gamut (Gen 5) to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:BlackmagicDesign:Input:Linear_BMD_WideGamut_Gen5_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear Blackmagic Wide Gamut (Gen 5) to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.647091325580708, 0.242595385134207, 0.110313289285085, 0, 0.0651915997328519, 1.02504756760476, -0.0902391673376125, 0, -0.0275570729194699, -0.0805887097177784, 1.10814578263725, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear DaVinci WideGamut
    aliases: [lin_davinci_widegamut]
    family: Input/BlackmagicDesign
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear DaVinci Wide Gamut to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:BlackmagicDesign:Input:Linear_DaVinci_WideGamut_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear DaVinci Wide Gamut to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.748270290272981, 0.167694659554328, 0.0840350501726906, 0, 0.0208421234689102, 1.11190474268894, -0.132746866157851, 0, -0.0915122574225729, -0.127746712807307, 1.21925897022988, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: CanonLog3 CinemaGamut D55
    aliases: [canonlog3_cinemagamut_d55, Input - Canon - Canon-Log3 - Cinema Gamut Daylight, canonlog3_cgamutday]
    family: Input/Canon
    equalitygroup: ""
    bitdepth: 32f
    description: Convert Canon Log 3 Cinema Gamut to ACES2065-1
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<BuiltinTransform> {style: CANON_CLOG3-CGAMUT_to_ACES2065-1}

  - !<ColorSpace>
    name: Linear CinemaGamut D55
    aliases: [lin_cinemagamut_d55, Input - Canon - Linear - Canon Cinema Gamut Daylight, lin_canoncgamutday]
    family: Input/Canon
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear Canon Cinema Gamut (Daylight) to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Canon:Input:Linear-CinemaGamut-D55_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear Canon Cinema Gamut (Daylight) to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.763064454775734, 0.14902116113706, 0.0879143840872056, 0, 0.00365745670512393, 1.10696038037622, -0.110617837081339, 0, -0.0094077940457189, -0.218383304989987, 1.22779109903571, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear V-Gamut
    aliases: [lin_vgamut, Input - Panasonic - Linear - V-Gamut]
    family: Input/Panasonic
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear Panasonic V-Gamut to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Panasonic:Input:Linear_VGamut_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear Panasonic V-Gamut to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.72461670413153, 0.166915288193706, 0.108468007674764, 0, 0.021390245413146, 0.984908155703054, -0.00629840111620089, 0, -0.00923556287076561, -0.00105690563900513, 1.01029246850977, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: V-Log V-Gamut
    aliases: [vlog_vgamut, Input - Panasonic - V-Log - V-Gamut]
    family: Input/Panasonic
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Panasonic V-Log - V-Gamut to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Panasonic:Input:VLog_VGamut_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Panasonic V-Log - V-Gamut to ACES2065-1
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.241514, log_side_offset: 0.598206, lin_side_offset: 0.00873, lin_side_break: 0.01, direction: inverse}
        - !<MatrixTransform> {matrix: [0.72461670413153, 0.166915288193706, 0.108468007674764, 0, 0.021390245413146, 0.984908155703054, -0.00629840111620089, 0, -0.00923556287076561, -0.00105690563900513, 1.01029246850977, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear REDWideGamutRGB
    aliases: [lin_redwidegamutrgb, Input - RED - Linear - REDWideGamutRGB, lin_rwg]
    family: Input/RED
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear REDWideGamutRGB to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:RED:Input:Linear_REDWideGamutRGB_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear REDWideGamutRGB to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.785058804068092, 0.0838587565440846, 0.131082439387823, 0, 0.0231738348454756, 1.08789754919233, -0.111071384037806, 0, -0.0737604353682082, -0.314590072290208, 1.38835050765842, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Log3G10 REDWideGamutRGB
    aliases: [log3g10_redwidegamutrgb, Input - RED - REDLog3G10 - REDWideGamutRGB, rl3g10_rwg]
    family: Input/RED
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert RED Log3G10 REDWideGamutRGB to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:RED:Input:Log3G10_REDWideGamutRGB_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: RED Log3G10 REDWideGamutRGB to ACES2065-1
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.224282, lin_side_slope: 155.975327, lin_side_offset: 2.55975327, lin_side_break: -0.01, direction: inverse}
        - !<MatrixTransform> {matrix: [0.785058804068092, 0.0838587565440846, 0.131082439387823, 0, 0.0231738348454756, 1.08789754919233, -0.111071384037806, 0, -0.0737604353682082, -0.314590072290208, 1.38835050765842, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear S-Gamut3
    aliases: [lin_sgamut3, Input - Sony - Linear - S-Gamut3]
    family: Input/Sony
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear S-Gamut3 to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Sony:Input:Linear_SGamut3_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear S-Gamut3 to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.75298259539984, 0.143370216235557, 0.103647188364603, 0, 0.0217076974414429, 1.01531883550528, -0.0370265329467195, 0, -0.00941605274963355, 0.00337041785882367, 1.00604563489081, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear S-Gamut3.Cine
    aliases: [lin_sgamut3cine, Input - Sony - Linear - S-Gamut3.Cine]
    family: Input/Sony
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear S-Gamut3.Cine to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Sony:Input:Linear_SGamut3Cine_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear S-Gamut3.Cine to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.638788667185978, 0.272351433711262, 0.0888598991027595, 0, -0.00391590602528224, 1.0880732308974, -0.0841573248721177, 0, -0.0299072021239151, -0.0264325799101947, 1.05633978203411, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear Venice S-Gamut3
    aliases: [lin_venice_sgamut3, Input - Sony - Linear - Venice S-Gamut3]
    family: Input/Sony
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear Venice S-Gamut3 to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Sony:Input:Linear_Venice_SGamut3_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear Venice S-Gamut3 to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.793329741146434, 0.0890786256206771, 0.117591633232888, 0, 0.0155810585252582, 1.03271230692988, -0.0482933654551394, 0, -0.0188647477991488, 0.0127694120973433, 1.0060953357018, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear Venice S-Gamut3.Cine
    aliases: [lin_venice_sgamut3cine, Input - Sony - Linear - Venice S-Gamut3.Cine]
    family: Input/Sony
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Linear Venice S-Gamut3.Cine to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Sony:Input:Linear_Venice_SGamut3Cine_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Linear Venice S-Gamut3.Cine to ACES2065-1
      children:
        - !<MatrixTransform> {matrix: [0.674257092126512, 0.220571735923397, 0.10517117195009, 0, -0.00931360607857167, 1.10595886142466, -0.0966452553460855, 0, -0.0382090673002312, -0.017938376600236, 1.05614744390047, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: S-Log3 S-Gamut3
    aliases: [slog3_sgamut3, Input - Sony - S-Log3 - S-Gamut3]
    family: Input/Sony
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Sony S-Log3 S-Gamut3 to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Sony:Input:SLog3_SGamut3_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Sony S-Log3 S-Gamut3 to ACES2065-1
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.255620723362659, log_side_offset: 0.410557184750733, lin_side_slope: 5.26315789473684, lin_side_offset: 0.0526315789473684, lin_side_break: 0.01125, linear_slope: 6.62194371177582, direction: inverse}
        - !<MatrixTransform> {matrix: [0.75298259539984, 0.143370216235557, 0.103647188364603, 0, 0.0217076974414429, 1.01531883550528, -0.0370265329467195, 0, -0.00941605274963355, 0.00337041785882367, 1.00604563489081, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: S-Log3 S-Gamut3.Cine
    aliases: [slog3_sgamut3cine, Input - Sony - S-Log3 - S-Gamut3.Cine, slog3_sgamutcine]
    family: Input/Sony
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Sony S-Log3 S-Gamut3.Cine to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Sony:Input:SLog3_SGamut3Cine_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Sony S-Log3 S-Gamut3.Cine to ACES2065-1
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.255620723362659, log_side_offset: 0.410557184750733, lin_side_slope: 5.26315789473684, lin_side_offset: 0.0526315789473684, lin_side_break: 0.01125, linear_slope: 6.62194371177582, direction: inverse}
        - !<MatrixTransform> {matrix: [0.638788667185978, 0.272351433711262, 0.0888598991027595, 0, -0.00391590602528224, 1.0880732308974, -0.0841573248721177, 0, -0.0299072021239151, -0.0264325799101947, 1.05633978203411, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: S-Log3 Venice S-Gamut3
    aliases: [slog3_venice_sgamut3, Input - Sony - S-Log3 - Venice S-Gamut3]
    family: Input/Sony
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Sony S-Log3 Venice S-Gamut3 to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Sony:Input:SLog3_Venice_SGamut3_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Sony S-Log3 Venice S-Gamut3 to ACES2065-1
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.255620723362659, log_side_offset: 0.410557184750733, lin_side_slope: 5.26315789473684, lin_side_offset: 0.0526315789473684, lin_side_break: 0.01125, linear_slope: 6.62194371177582, direction: inverse}
        - !<MatrixTransform> {matrix: [0.793329741146434, 0.089078625620677, 0.117591633232888, 0, 0.0155810585252582, 1.03271230692988, -0.0482933654551394, 0, -0.0188647477991488, 0.0127694120973433, 1.00609533570181, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: S-Log3 Venice S-Gamut3.Cine
    aliases: [slog3_venice_sgamut3cine, Input - Sony - S-Log3 - Venice S-Gamut3.Cine, slog3_venice_sgamutcine]
    family: Input/Sony
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert Sony S-Log3 Venice S-Gamut3.Cine to ACES2065-1
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Sony:Input:SLog3_Venice_SGamut3Cine_to_ACES2065-1:1.0
    isdata: false
    categories: [file-io]
    encoding: log
    allocation: uniform
    to_scene_reference: !<GroupTransform>
      name: Sony S-Log3 Venice S-Gamut3.Cine to ACES2065-1
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.255620723362659, log_side_offset: 0.410557184750733, lin_side_slope: 5.26315789473684, lin_side_offset: 0.0526315789473684, lin_side_break: 0.01125, linear_slope: 6.62194371177582, direction: inverse}
        - !<MatrixTransform> {matrix: [0.674257092126512, 0.220571735923397, 0.10517117195009, 0, -0.00931360607857167, 1.10595886142466, -0.0966452553460855, 0, -0.0382090673002312, -0.017938376600236, 1.05614744390047, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Camera Rec.709
    aliases: [camera_rec709, Utility - Rec.709 - Camera, rec709_camera]
    family: Utility/ITU
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to Rec.709 camera OETF Rec.709 primaries, D65 white point
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:ITU:Utility:AP0_to_Camera_Rec709:1.0
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to Camera Rec.709
      children:
        - !<MatrixTransform> {matrix: [2.52168618674388, -1.13413098823972, -0.387555198504164, 0, -0.276479914229922, 1.37271908766826, -0.096239173438334, 0, -0.0153780649660342, -0.152975335867399, 1.16835340083343, 0, 0, 0, 0, 1]}
        - !<ExponentWithLinearTransform> {gamma: 2.22222222222222, offset: 0.099, direction: inverse}

  - !<ColorSpace>
    name: Linear P3-D65
    aliases: [lin_p3d65, Utility - Linear - P3-D65]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to linear P3 primaries, D65 white point
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:AP0_to_Linear_P3-D65:1.0
    isdata: false
    categories: [file-io, working-space]
    encoding: scene-linear
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to Linear P3-D65
      children:
        - !<MatrixTransform> {matrix: [2.02490528596679, -0.689069761034766, -0.335835524932019, 0, -0.183597032256178, 1.28950620775902, -0.105909175502841, 0, 0.00905856112234766, -0.0592796840575522, 1.0502211229352, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear Rec.2020
    aliases: [lin_rec2020, Utility - Linear - Rec.2020]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to linear Rec.2020 primaries, D65 white point
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:AP0_to_Linear_Rec2020:1.0
    isdata: false
    categories: [file-io]
    encoding: scene-linear
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to Linear Rec.2020
      children:
        - !<MatrixTransform> {matrix: [1.49040952054172, -0.26617091926613, -0.224238601275593, 0, -0.0801674998722558, 1.18216712109757, -0.10199962122531, 0, 0.00322763119162216, -0.0347764757450576, 1.03154884455344, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Linear Rec.709 (sRGB)
    aliases: [lin_rec709_srgb, Utility - Linear - Rec.709, lin_rec709, lin_srgb, Utility - Linear - sRGB]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to linear Rec.709 primaries, D65 white point
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:AP0_to_Linear_Rec709:1.0
    isdata: false
    categories: [file-io, working-space]
    encoding: scene-linear
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to Linear Rec.709 (sRGB)
      children:
        - !<MatrixTransform> {matrix: [2.52168618674388, -1.13413098823972, -0.387555198504164, 0, -0.276479914229922, 1.37271908766826, -0.096239173438334, 0, -0.0153780649660342, -0.152975335867399, 1.16835340083343, 0, 0, 0, 0, 1]}

  - !<ColorSpace>
    name: Gamma 1.8 Rec.709 - Texture
    aliases: [g18_rec709_tx, Utility - Gamma 1.8 - Rec.709 - Texture, g18_rec709]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to 1.8 gamma-corrected Rec.709 primaries, D65 white point
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:AP0_to_Gamma1.8_Rec709-Texture:1.0
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to Gamma 1.8 Rec.709 - Texture
      children:
        - !<MatrixTransform> {matrix: [2.52168618674388, -1.13413098823972, -0.387555198504164, 0, -0.276479914229922, 1.37271908766826, -0.096239173438334, 0, -0.0153780649660342, -0.152975335867399, 1.16835340083343, 0, 0, 0, 0, 1]}
        - !<ExponentTransform> {value: 1.8, style: pass_thru, direction: inverse}

  - !<ColorSpace>
    name: Gamma 2.2 AP1 - Texture
    aliases: [g22_ap1_tx, g22_ap1]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to 2.2 gamma-corrected AP1 primaries, D60 white point
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:AP0_to_Gamma2.2_AP1-Texture:1.0
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to Gamma 2.2 AP1 - Texture
      children:
        - !<MatrixTransform> {matrix: [1.45143931614567, -0.23651074689374, -0.214928569251925, 0, -0.0765537733960206, 1.17622969983357, -0.0996759264375522, 0, 0.00831614842569772, -0.00603244979102102, 0.997716301365323, 0, 0, 0, 0, 1]}
        - !<ExponentTransform> {value: 2.2, style: pass_thru, direction: inverse}

  - !<ColorSpace>
    name: Gamma 2.2 Rec.709 - Texture
    aliases: [g22_rec709_tx, Utility - Gamma 2.2 - Rec.709 - Texture, g22_rec709]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to 2.2 gamma-corrected Rec.709 primaries, D65 white point
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:AP0_to_Gamma2.2_Rec709-Texture:1.0
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to Gamma 2.2 Rec.709 - Texture
      children:
        - !<MatrixTransform> {matrix: [2.52168618674388, -1.13413098823972, -0.387555198504164, 0, -0.276479914229922, 1.37271908766826, -0.096239173438334, 0, -0.0153780649660342, -0.152975335867399, 1.16835340083343, 0, 0, 0, 0, 1]}
        - !<ExponentTransform> {value: 2.2, style: pass_thru, direction: inverse}

  - !<ColorSpace>
    name: Gamma 2.4 Rec.709 - Texture
    aliases: [g24_rec709_tx, g24_rec709, rec709_display, Utility - Rec.709 - Display]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to 2.4 gamma-corrected Rec.709 primaries, D65 white point
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:AP0_to_Gamma2.4_Rec709-Texture:1.0
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to Gamma 2.4 Rec.709 - Texture
      children:
        - !<MatrixTransform> {matrix: [2.52168618674388, -1.13413098823972, -0.387555198504164, 0, -0.276479914229922, 1.37271908766826, -0.096239173438334, 0, -0.0153780649660342, -0.152975335867399, 1.16835340083343, 0, 0, 0, 0, 1]}
        - !<ExponentTransform> {value: 2.4, style: pass_thru, direction: inverse}

  - !<ColorSpace>
    name: sRGB Encoded AP1 - Texture
    aliases: [srgb_encoded_ap1_tx, srgb_ap1]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to sRGB Encoded AP1 primaries, D60 white point
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:AP0_to_sRGB_Encoded_AP1-Texture:1.0
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to sRGB Encoded AP1 - Texture
      children:
        - !<MatrixTransform> {matrix: [1.45143931614567, -0.23651074689374, -0.214928569251925, 0, -0.0765537733960206, 1.17622969983357, -0.0996759264375522, 0, 0.00831614842569772, -0.00603244979102102, 0.997716301365323, 0, 0, 0, 0, 1]}
        - !<ExponentWithLinearTransform> {gamma: 2.4, offset: 0.055, direction: inverse}

  - !<ColorSpace>
    name: sRGB - Texture
    aliases: [srgb_tx, Utility - sRGB - Texture, srgb_texture, Input - Generic - sRGB - Texture]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: |
      Convert ACES2065-1 to sRGB
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:AP0_to_sRGB-Texture:1.0
    isdata: false
    categories: [file-io]
    allocation: uniform
    from_scene_reference: !<GroupTransform>
      name: AP0 to sRGB Rec.709
      children:
        - !<MatrixTransform> {matrix: [2.52168618674388, -1.13413098823972, -0.387555198504164, 0, -0.276479914229922, 1.37271908766826, -0.096239173438334, 0, -0.0153780649660342, -0.152975335867399, 1.16835340083343, 0, 0, 0, 0, 1]}
        - !<ExponentWithLinearTransform> {gamma: 2.4, offset: 0.055, direction: inverse}

  - !<ColorSpace>
    name: Raw
    aliases: [Utility - Raw]
    family: Utility
    equalitygroup: ""
    bitdepth: 32f
    description: The utility "Raw" colorspace.
    isdata: true
    categories: [file-io]
    allocation: uniform

named_transforms:
  - !<NamedTransform>
    name: ARRI LogC3 - Curve (EI800)
    aliases: [arri_logc3_crv_ei800, Input - ARRI - Curve - V3 LogC (EI800), crv_logc3ei800]
    description: |
      Convert ARRI LogC3 Curve (EI800) to Relative Scene Linear
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:ARRI:Input:ARRI_LogC3_Curve_EI800_to_Linear:1.0
    family: Input/ARRI
    categories: [file-io]
    encoding: log
    transform: !<GroupTransform>
      name: ARRI LogC3 Curve (EI800) to Relative Scene Linear
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.247189638318671, log_side_offset: 0.385536998692443, lin_side_slope: 5.55555555555556, lin_side_offset: 0.0522722750251688, lin_side_break: 0.0105909904954696, direction: inverse}

  - !<NamedTransform>
    name: ARRI LogC4 - Curve
    aliases: [arri_logc4_crv]
    description: |
      Convert ARRI LogC4 Curve to Relative Scene Linear
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:ARRI:Input:ARRI_LogC4_Curve_to_Linear:1.0
    family: Input/ARRI
    categories: [file-io]
    encoding: log
    transform: !<GroupTransform>
      name: ARRI LogC4 Curve to Relative Scene Linear
      children:
        - !<LogCameraTransform> {log_side_slope: 0.0647954196341293, log_side_offset: -0.295908392682586, lin_side_slope: 2231.82630906769, lin_side_offset: 64, lin_side_break: -0.0180569961199113, direction: inverse}

  - !<NamedTransform>
    name: BMDFilm Gen5 Log - Curve
    aliases: [bmdfilm_gen5_log_crv]
    description: |
      Convert Blackmagic Film (Gen 5) Log to Blackmagic Film (Gen 5) Linear
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:BlackmagicDesign:Input:BMDFilm_Gen5_Log-Curve_to_Linear:1.0
    family: Input/BlackmagicDesign
    categories: [file-io]
    encoding: log
    transform: !<GroupTransform>
      name: Blackmagic Film (Gen 5) Log to Linear Curve
      children:
        - !<LogCameraTransform> {base: 2.71828182845905, log_side_slope: 0.0869287606549122, log_side_offset: 0.530013339229194, lin_side_offset: 0.00549407243225781, lin_side_break: 0.005, direction: inverse}

  - !<NamedTransform>
    name: DaVinci Intermediate Log - Curve
    aliases: [davinci_intermediate_log_crv]
    description: |
      Convert DaVinci Intermediate Log to DaVinci Intermediate Linear
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:BlackmagicDesign:Input:DaVinci_Intermediate_Log-Curve_to_Linear:1.0
    family: Input/BlackmagicDesign
    categories: [file-io]
    encoding: log
    transform: !<GroupTransform>
      name: DaVinci Intermediate Log to Linear Curve
      children:
        - !<LogCameraTransform> {log_side_slope: 0.07329248, log_side_offset: 0.51304736, lin_side_offset: 0.0075, lin_side_break: 0.00262409, linear_slope: 10.44426855, direction: inverse}

  - !<NamedTransform>
    name: V-Log - Curve
    aliases: [vlog_crv, Input - Panasonic - Curve - V-Log, crv_vlog]
    description: |
      Convert Panasonic V-Log Log (arbitrary primaries) to Panasonic V-Log Linear (arbitrary primaries)
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Panasonic:Input:VLog-Curve_to_Linear:1.0
    family: Input/Panasonic
    categories: [file-io]
    encoding: log
    transform: !<GroupTransform>
      name: Panasonic V-Log Log to Linear Curve
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.241514, log_side_offset: 0.598206, lin_side_offset: 0.00873, lin_side_break: 0.01, direction: inverse}

  - !<NamedTransform>
    name: Log3G10 - Curve
    aliases: [log3g10_crv, Input - RED - Curve - REDLog3G10, crv_rl3g10]
    description: |
      Convert RED Log3G10 Log (arbitrary primaries) to RED Log3G10 Linear (arbitrary primaries)
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:RED:Input:Log3G10-Curve_to_Linear:1.0
    family: Input/RED
    categories: [file-io]
    encoding: log
    transform: !<GroupTransform>
      name: RED Log3G10 Log to Linear Curve
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.224282, lin_side_slope: 155.975327, lin_side_offset: 2.55975327, lin_side_break: -0.01, direction: inverse}

  - !<NamedTransform>
    name: S-Log3 - Curve
    aliases: [slog3_crv, Input - Sony - Curve - S-Log3, crv_slog3]
    description: |
      Convert S-Log3 Log (arbitrary primaries) to S-Log3 Linear (arbitrary primaries)
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:Sony:Input:SLog3-Curve_to_Linear:1.0
    family: Input/Sony
    categories: [file-io]
    encoding: log
    transform: !<GroupTransform>
      name: S-Log3 Log to Linear Curve
      children:
        - !<LogCameraTransform> {base: 10, log_side_slope: 0.255620723362659, log_side_offset: 0.410557184750733, lin_side_slope: 5.26315789473684, lin_side_offset: 0.0526315789473684, lin_side_break: 0.01125, linear_slope: 6.62194371177582, direction: inverse}

  - !<NamedTransform>
    name: Rec.1886 - Curve
    aliases: [rec1886_crv, Utility - Curve - Rec.1886, crv_rec1886]
    description: |
      Convert generic linear RGB to generic gamma-corrected RGB
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:Linear_to_Rec1886-Curve:1.0
    family: Utility
    categories: [file-io]
    encoding: sdr-video
    inverse_transform: !<GroupTransform>
      name: Linear to Rec.1886
      children:
        - !<ExponentTransform> {value: 2.4, style: pass_thru, direction: inverse}

  - !<NamedTransform>
    name: Rec.709 - Curve
    aliases: [rec709_crv, Utility - Curve - Rec.709, crv_rec709]
    description: |
      Convert generic linear RGB to generic gamma-corrected RGB
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:ITU:Utility:Linear_to_Rec709-Curve:1.0
    family: Utility/ITU
    categories: [file-io]
    encoding: sdr-video
    inverse_transform: !<GroupTransform>
      name: Linear to Rec.709
      children:
        - !<ExponentWithLinearTransform> {gamma: 2.22222222222222, offset: 0.099, direction: inverse}

  - !<NamedTransform>
    name: sRGB - Curve
    aliases: [srgb_crv, Utility - Curve - sRGB, crv_srgb]
    description: |
      Convert generic linear RGB to generic gamma-corrected RGB
      
      CLFtransformID: urn:aswf:ocio:transformId:1.0:OCIO:Utility:Linear_to_sRGB-Curve:1.0
    family: Utility
    categories: [file-io]
    encoding: sdr-video
    inverse_transform: !<GroupTransform>
      name: Linear to sRGB
      children:
        - !<ExponentWithLinearTransform> {gamma: 2.4, offset: 0.055, direction: inverse}

  - !<NamedTransform>
    name: ST-2084 - Curve
    aliases: [st_2084_crv]
    description: Convert linear nits/100 to SMPTE ST-2084 (PQ) full-range
    family: Utility
    categories: [file-io]
    encoding: hdr-video
    inverse_transform: !<BuiltinTransform> {style: CURVE - LINEAR_to_ST-2084}
Download .txt
gitextract_5olro6ee/

├── README.md
├── gain_map_extract.py
├── heic_to_exr.py
├── merge_to_exr.sh
├── requirements.txt
└── studio-config-v1.0.0_aces-v1.3_ocio-v2.1.ocio
Download .txt
SYMBOL INDEX (4 symbols across 2 files)

FILE: gain_map_extract.py
  function extract_all_images (line 11) | def extract_all_images(input_path, output_dir=None):

FILE: heic_to_exr.py
  function extract_heic (line 14) | def extract_heic(input_path, output_dir):
  function merge_to_exr (line 126) | def merge_to_exr(input_dir, original_heic, output_path):
  function main (line 296) | def main():
Condensed preview — 6 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (84K chars).
[
  {
    "path": "README.md",
    "chars": 3672,
    "preview": "# 🖼️ HEIC Image Processing Tools\n\nA collection of Python tools for processing HEIC (High Efficiency Image Container) fil"
  },
  {
    "path": "gain_map_extract.py",
    "chars": 5456,
    "preview": "#!/usr/bin/env python3\n\nimport os\nfrom PIL import Image\nimport pillow_heif\nimport numpy as np\nfrom pathlib import Path\ni"
  },
  {
    "path": "heic_to_exr.py",
    "chars": 11736,
    "preview": "#!/usr/bin/env python3\n\nimport os\nimport sys\nimport tempfile\nimport shutil\nfrom pathlib import Path\nfrom PIL import Imag"
  },
  {
    "path": "merge_to_exr.sh",
    "chars": 4592,
    "preview": "#!/bin/bash\n\nif [ $# -lt 2 ]; then\n    echo \"Usage: ./merge_to_exr.sh <input_folder> <original.HEIC> [output.exr]\"\n    e"
  },
  {
    "path": "requirements.txt",
    "chars": 67,
    "preview": "Pillow>=10.0.0\npillow-heif>=0.13.0\nnumpy>=1.24.0\ndefusedxml>=0.7.1 "
  },
  {
    "path": "studio-config-v1.0.0_aces-v1.3_ocio-v2.1.ocio",
    "chars": 55873,
    "preview": "ocio_profile_version: 2.1\n\nenvironment:\n  {}\nsearch_path: \"\"\nstrictparsing: true\nluma: [0.2126, 0.7152, 0.0722]\nname: st"
  }
]

About this extraction

This page contains the full source code of the finnschi/heic-shenanigans GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 6 files (79.5 KB), approximately 26.6k tokens, and a symbol index with 4 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!