Filters

Brightness, contrast, saturation, sharpness, grayscale, sepia — applied identically to the live preview and the exported image.

FilterTypeValid valuesDefault
brightnessnumber>= 0 (1 = unchanged)1
contrastnumber>= 0 (1 = unchanged)1
saturationnumber>= 0 (1 = unchanged)1
sharpnessnumber>= 0 (1 or below = unchanged; higher sharpens)1
grayscalebooleantrue, falsefalse
sepiabooleantrue, falsefalse

sharpness works differently from the others: unlike brightness/contrast/saturation, it isn't a native CSS filter — CSS has no sharpen() function. Kiri generates a small SVG feConvolveMatrix filter (an unsharp-mask kernel) per instance and references it via a url(#id) appended to the same filter string, so it's still just one filter string driving both the live preview and the export — see Architecture for how.

Setting filters

// initial, via the constructor
new Kiri(container, { filters: { sepia: true } });

// afterward — merges into the current filters
cropper.setFilters({ brightness: 1.2, grayscale: true });

setFilters() merges a partial update into the current filters (fields you don't pass are left as they are), and clamps numeric values to >= 0.

Why the preview and export always match

Both the live preview and the canvas export apply the exact same CSS filter string — the preview via the image element's style.filter, the export via the canvas 2D context's ctx.filter before drawing. Reusing the browser's own filter implementation for both means they're guaranteed to match pixel-for-pixel, with no separately hand-rolled brightness/contrast/saturation/sharpness pixel math to get subtly wrong — including sharpness's SVG filter, since both style.filter and ctx.filter support the same url(#id) reference syntax identically.

Next: Architecture.