Color Adjustments
Color adjustment operations modify pixel colors to achieve effects like brightening, increasing contrast, adjusting saturation, and converting to grayscale.
Brightness
Adjust the overall brightness of an image by adding or subtracting from all RGB channels.
Signature
brightness(amount: number): this
Parameters
amount- Brightness adjustment from -1 to 1-1.0- Maximum darkening (black)0.0- No change1.0- Maximum brightening (white)
Example
import { Image } from "@cross/image";
const data = await Deno.readFile("photo.jpg");
const image = await Image.decode(data);
// Brighten by 20%
image.brightness(0.2);
// Darken by 30%
image.brightness(-0.3);
// Subtle brightening
image.brightness(0.1);
const output = await image.encode("png");
await Deno.writeFile("adjusted.png", output);
Use Cases
- Correcting underexposed photos
- Reducing overexposure
- Creating mood effects
- Preparing images for display
Tips
- Use small increments (0.1-0.2) for natural results
- Combine with contrast for better results
- Extreme values (±0.8+) lose detail
Contrast
Adjust the difference between light and dark areas by scaling RGB values around midpoint.
Signature
contrast(amount: number): this
Parameters
amount- Contrast adjustment from -1 to 1-1.0- Minimum contrast (gray)0.0- No change1.0- Maximum contrast
Example
import { Image } from "@cross/image";
const data = await Deno.readFile("photo.jpg");
const image = await Image.decode(data);
// Increase contrast by 30%
image.contrast(0.3);
// Decrease contrast (flatten)
image.contrast(-0.2);
// High contrast look
image.contrast(0.5);
const output = await image.encode("png");
await Deno.writeFile("contrast.png", output);
Use Cases
- Enhancing flat images
- Creating dramatic effects
- Improving readability
- Correcting washed-out photos
Tips
- Positive values increase contrast
- Negative values reduce contrast
- Works well with brightness adjustments
Common Combinations
// Punch up a dull photo
image.brightness(0.1).contrast(0.3);
// Flatten for vintage look
image.brightness(-0.1).contrast(-0.2);
Saturation
Adjust color intensity while preserving luminance.
Signature
saturation(amount: number): this
Parameters
amount- Saturation adjustment from -1 to 1-1.0- Full desaturation (grayscale)0.0- No change1.0- Maximum saturation
Example
import { Image } from "@cross/image";
const data = await Deno.readFile("photo.jpg");
const image = await Image.decode(data);
// Boost saturation by 30%
image.saturation(0.3);
// Reduce saturation (faded look)
image.saturation(-0.5);
// Fully desaturate (equivalent to grayscale)
image.saturation(-1.0);
const output = await image.encode("png");
await Deno.writeFile("saturated.png", output);
Use Cases
- Enhancing vibrant scenes
- Creating muted vintage looks
- Correcting oversaturated images
- Preparing for grayscale conversion
Tips
- Saturation affects only colors, not brightness
- Works in HSL color space internally
- Values near -1 create near-grayscale
Exposure
Photographic exposure adjustment simulating camera exposure compensation. Applies exponential scaling to mimic real exposure.
Signature
exposure(amount: number): this
Parameters
amount- Exposure adjustment in stops from -3 to 3-3.0- Darken by 3 stops (1/8 intensity)0.0- No change1.0- Brighten by 1 stop (2× intensity)3.0- Brighten by 3 stops (8× intensity)
Example
import { Image } from "@cross/image";
const data = await Deno.readFile("photo.jpg");
const image = await Image.decode(data);
// Increase exposure by 1 stop
image.exposure(1.0);
// Decrease exposure by 1.5 stops
image.exposure(-1.5);
// Subtle exposure boost
image.exposure(0.5);
const output = await image.encode("png");
await Deno.writeFile("exposed.png", output);
Use Cases
- Simulating camera exposure compensation
- HDR-style adjustments
- Correcting exposure errors
- Creating high-key/low-key effects
Exposure vs. Brightness
- Exposure: Exponential scaling (photographic, preserves ratios)
- Brightness: Linear addition (simple, uniform change)
// Photographic exposure adjustment
image.exposure(1.0); // Doubles intensity
// Simple brightness adjustment
image.brightness(0.5); // Adds 50% to each channel
Grayscale
Convert image to grayscale using luminance-preserving formula.
Signature
grayscale(): this
Example
import { Image } from "@cross/image";
const data = await Deno.readFile("photo.jpg");
const image = await Image.decode(data);
// Convert to grayscale
image.grayscale();
const output = await image.encode("png");
await Deno.writeFile("grayscale.png", output);
Use Cases
- Black and white photography
- Preparing images for printing
- Reducing file size
- Creating dramatic effects
Implementation
Uses perceptually weighted formula (ITU-R BT.601 standard):
L = 0.299R + 0.587G + 0.114B
This preserves perceived brightness better than simple averaging. Note that modern displays may use different coefficients (like ITU-R BT.709), but this standard provides good results for general use.
Alternatives
// Grayscale via saturation
image.saturation(-1.0); // Same visual result
// Grayscale preserving exposure
image.grayscale().exposure(0.2);
Invert
Invert all RGB color channels (negative effect).
Signature
invert(): this
Example
import { Image } from "@cross/image";
const data = await Deno.readFile("photo.jpg");
const image = await Image.decode(data);
// Create negative
image.invert();
const output = await image.encode("png");
await Deno.writeFile("inverted.png", output);
Use Cases
- Creating negatives
- Artistic effects
- Improving readability (dark mode)
- Special visual effects
Note
Alpha channel is preserved (not inverted).
Sepia
Apply warm sepia tone for vintage photograph effect.
Signature
sepia(): this
Example
import { Image } from "@cross/image";
const data = await Deno.readFile("photo.jpg");
const image = await Image.decode(data);
// Apply sepia tone
image.sepia();
const output = await image.encode("png");
await Deno.writeFile("sepia.png", output);
Use Cases
- Vintage photograph effects
- Warm nostalgic look
- Artistic portraits
- Historical photo simulation
Implementation
Applies classic sepia transformation matrix:
R' = 0.393R + 0.769G + 0.189B
G' = 0.349R + 0.686G + 0.168B
B' = 0.272R + 0.534G + 0.131B
Variations
// Subtle sepia with reduced saturation
image.sepia().saturation(-0.3);
// Aged photo look
image.sepia().brightness(-0.1).contrast(0.2);
Complex Color Workflows
Combine adjustments for professional results:
Portrait Enhancement
const image = await Image.decode(data);
image
.brightness(0.05) // Slight brighten
.contrast(0.1) // Subtle contrast
.saturation(0.15); // Boost colors
await Deno.writeFile("portrait.png", await image.encode("png"));
Landscape Enhancement
const image = await Image.decode(data);
image
.exposure(0.3) // Brighten highlights
.contrast(0.3) // Dramatic contrast
.saturation(0.4); // Vibrant colors
await Deno.writeFile("landscape.png", await image.encode("png"));
Vintage Film Look
const image = await Image.decode(data);
image
.brightness(-0.05) // Slightly darker
.contrast(-0.1) // Reduced contrast
.saturation(-0.3) // Muted colors
.sepia(); // Warm tone
await Deno.writeFile("vintage.png", await image.encode("png"));
High-Key Portrait
const image = await Image.decode(data);
image
.exposure(0.5) // Bright exposure
.contrast(-0.2) // Soft contrast
.saturation(-0.1); // Subtle colors
await Deno.writeFile("highkey.png", await image.encode("png"));
Low-Key Drama
const image = await Image.decode(data);
image
.exposure(-0.5) // Dark exposure
.contrast(0.5) // Strong contrast
.saturation(0.2); // Rich colors
await Deno.writeFile("lowkey.png", await image.encode("png"));
Black and White with Contrast
const image = await Image.decode(data);
image
.grayscale()
.contrast(0.3) // Strong contrast
.brightness(0.1); // Slight lift
await Deno.writeFile("bw.png", await image.encode("png"));
Color Space Notes
All color adjustments work in RGB color space. For saturation, the library temporarily converts to HSL, adjusts, and converts back to RGB.
Performance
All color adjustments are fast operations that process pixels in a single pass. Order doesn't significantly affect performance.