Apply warm film emulsion color grading to images
npm install film-emulsionA TypeScript library for applying warm film emulsion color grading to images. Built with Effect for type-safe, composable error handling.
- 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
``bash`
bun add film-emulsion
`typescript
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);
`
Transform an image file with warm film emulsion color grading.
`typescript
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);
`
Transform an image buffer with warm film emulsion color grading.
`typescript
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);
`
For advanced usage, you can use the individual modules:
`typescript`
import {
// HSL adjustments
applyHslAdjustments,
FILM_PRESET_HSL,
// Tone curves
createPresetLuts,
applyCurves,
// Color utilities
rgbToHsl,
hslToRgb,
} from "film-emulsion";
All functions return Effect values with typed errors:
`typescript
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})Processing failed: ${e.operation}
),
Match.tag("ImageProcessingError", (e) =>
Effect.logError()`
),
Match.exhaustive
)
)
);
| Error | Description |
|-------|-------------|
| FileReadError | Could not read the input file |FileWriteError
| | Could not write the output file |ImageProcessingError
| | Sharp/image manipulation failed |
The film emulsion simulation applies two main transformations:
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 |
- Master RGB curve - Lifts shadows, compresses highlights
- Per-channel curves - Subtle color cast adjustments
- Node.js >= 24.0.0
- Bun runtime
`bashInstall dependencies
bun install
MIT