film-emulsion
v0.1.0
Published
Apply warm film emulsion color grading to images
Readme
film-emulsion
A TypeScript library for applying warm film emulsion color grading to images. Built with Effect for type-safe, composable error handling.
Features
- HSL Adjustments - Applies warm film-style hue, saturation, and luminance shifts
- Tone Curves - Master RGB curve + per-channel curves for that classic film look
- Type-safe Errors - All errors are typed and composable with Effect
- Fast Processing - Uses Sharp for efficient image I/O
- Fully Tested - Comprehensive test suite
Installation
bun add film-emulsionQuick Start
import { transformFile } from "film-emulsion";
import { Effect } from "effect";
// Transform an image file
const program = transformFile("photo.jpg", "photo-graded.jpg");
await Effect.runPromise(program);API
transformFile
Transform an image file with warm film emulsion color grading.
import { transformFile } from "film-emulsion";
import { Effect } from "effect";
const program = transformFile("input.jpg", "output.jpg", {
quality: 90, // JPEG quality (1-100, default 90)
applyHsl: true, // Apply HSL adjustments (default true)
applyCurves: true, // Apply tone curves (default true)
});
await Effect.runPromise(program);transformBuffer
Transform an image buffer with warm film emulsion color grading.
import { transformBuffer } from "film-emulsion";
import { Effect } from "effect";
import * as fs from "node:fs/promises";
const input = await fs.readFile("photo.jpg");
const output = await Effect.runPromise(transformBuffer(Buffer.from(input)));
await fs.writeFile("output.jpg", output);Low-Level APIs
For advanced usage, you can use the individual modules:
import {
// HSL adjustments
applyHslAdjustments,
FILM_PRESET_HSL,
// Tone curves
createPresetLuts,
applyCurves,
// Color utilities
rgbToHsl,
hslToRgb,
} from "film-emulsion";Error Handling
All functions return Effect values with typed errors:
import { transformFile, FileReadError, ImageProcessingError } from "film-emulsion";
import { Effect, Match } from "effect";
const program = transformFile("input.jpg", "output.jpg").pipe(
Effect.catchAll((error) =>
Match.value(error).pipe(
Match.tag("FileReadError", (e) =>
Effect.logError(`Could not read file: ${e.path}`)
),
Match.tag("ImageProcessingError", (e) =>
Effect.logError(`Processing failed: ${e.operation}`)
),
Match.exhaustive
)
)
);Error Types
| Error | Description |
|-------|-------------|
| FileReadError | Could not read the input file |
| FileWriteError | Could not write the output file |
| ImageProcessingError | Sharp/image manipulation failed |
How It Works
The film emulsion simulation applies two main transformations:
HSL Adjustments
Color-specific hue, saturation, and luminance shifts:
| Color | Hue | Saturation | Luminance | |-------|-----|------------|-----------| | Red | -11 | +10 | +10 | | Orange | -1 | +2 | -10 | | Yellow | +13 | +27 | 0 | | Green | -15 | 0 | 0 | | Purple | -18 | +10 | 0 | | Magenta | +20 | -9 | 0 |
Tone Curves
- Master RGB curve - Lifts shadows, compresses highlights
- Per-channel curves - Subtle color cast adjustments
Requirements
- Node.js >= 24.0.0
- Bun runtime
Development
# Install dependencies
bun install
# Run tests
bun run test
# Run tests in watch mode
bun run test:watchLicense
MIT
