Original
Left: source image
Filtered
Right: result
Filter formulae
Grayscale:
R' = G' = B' = 0.299*R + 0.587*G + 0.114*B
Sepia:
R' = 0.393*R + 0.769*G + 0.189*B
G' = 0.349*R + 0.686*G + 0.168*B
B' = 0.272*R + 0.534*G + 0.131*B
Invert:
R' = 255 - R
G' = 255 - G
B' = 255 - B
Brightness (amount: -255..+255):
R' = clamp(R + amount, 0, 255)
G' = clamp(G + amount, 0, 255)
B' = clamp(B + amount, 0, 255)
Contrast (amount: -255..+255):
factor = (259*(amount + 255)) / (255*(259 - amount))
R' = clamp(factor*(R - 128) + 128, 0, 255)
G' = clamp(factor*(G - 128) + 128, 0, 255)
B' = clamp(factor*(B - 128) + 128, 0, 255)
Saturation (amount: -100..+100):
Let gray = 0.299*R + 0.587*G + 0.114*B
factor = 1 + amount/100
R' = clamp(gray + (R - gray)*factor, 0, 255)
G' = clamp(gray + (G - gray)*factor, 0, 255)
B' = clamp(gray + (B - gray)*factor, 0, 255)
Hue Rotate (degrees: -180..+180):
Convert RGB -> HSL, H' = (H + degrees) mod 360, convert back HSL -> RGB.
Vignette (strength: 0..100):
For pixel at normalized distance d from center (0..1):
falloff = 1 - strength*(d^2)
R' = clamp(R * falloff)
G' = clamp(G * falloff)
B' = clamp(B * falloff)
Black Point (black: 0..255):
For each channel:
if v <= black: v' = 0
else v' = clamp( (v - black) * 255 / (255 - black) )
White Point (white: 0..255):
For each channel:
if v >= white: v' = 255
else v' = clamp( v * 255 / white )
Rotate (90° steps):
Spatial transform — image is rotated by 0/90/180/270 degrees.
Rotate (any angle):
Spatial transform — image is rotated by any angle in degrees. Output dimensions are the rotated bounding box.
Flip X (horizontal):
Spatial transform — pixel at (x,y) maps to (width-1-x, y)
Flip Y (vertical):
Spatial transform — pixel at (x,y) maps to (x, height-1-y)
Notes:
- All equations operate per pixel (unless the filter is a spatial transform).
- clamp(x,0,255) ensures values are valid 8-bit integers.