# Adjust brightness, contrast, and saturation
Compare brightness, contrast, and saturation independently against the same original subject.

## APIs demonstrated

- [brightness](/reference/types/filters/) from `@pibbl/core/filters`
- [contrast](/reference/types/filters/) from `@pibbl/core/filters`
- [saturate](/reference/types/filters/) from `@pibbl/core/filters`
- [PibblBrightnessFilterOptions](/reference/types/filters/) from `@pibbl/core/filters`
- [PibblContrastFilterOptions](/reference/types/filters/) from `@pibbl/core/filters`
- [PibblSaturateFilterOptions](/reference/types/filters/) from `@pibbl/core/filters`

## Complete example

[Plain source](/minimal/filters/filter-tone.tsx). Run as a browser module after the document body exists. TSX uses `jsx: "react-jsx"` and `jsxImportSource: "@pibbl/core"`.

```tsx
import { pibbl, Group, Circle, Rectangle, Text } from "@pibbl/core";
import {
  brightness,
  contrast,
  saturate,
  type PibblFilter,
  type PibblBrightnessFilterOptions,
  type PibblContrastFilterOptions,
  type PibblSaturateFilterOptions,
} from "@pibbl/core/filters";

const light: PibblBrightnessFilterOptions = { amount: 1.6 };
const depth: PibblContrastFilterOptions = { amount: 1.8 };
const color: PibblSaturateFilterOptions = { amount: 0.2 };
const comparisons: [string, PibblFilter | undefined][] = [
  ["Original", undefined],
  ["Brightness 1.6", brightness(light)],
  ["Contrast 1.8", contrast(depth)],
  ["Saturation 0.2", saturate(color)],
];
function Subject() {
  return (
    <>
      <Rectangle
        style={{ left: 22, top: 30, width: 60, height: 92, fill: "#277e99" }}
      />
      <Rectangle
        style={{ left: 82, top: 30, width: 60, height: 92, fill: "#dc7764" }}
      />
      <Rectangle
        style={{ left: 142, top: 30, width: 60, height: 92, fill: "#ddb84f" }}
      />
      <Circle style={{ cx: 112, cy: 73, radius: 32, fill: "#23333a" }} />
      <Text
        style={{
          left: 112,
          top: 82,
          textAlign: "center",
          font: "bold 23px sans-serif",
          fill: "#fff",
        }}
      >
        Pibbl
      </Text>
    </>
  );
}
const grid = document.createElement("div");
grid.style.cssText =
  "display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;max-width:480px";
document.body.append(grid);
const controllers = comparisons.map(([label, filter]) => {
  const figure = document.createElement("figure");
  figure.style.margin = "0";
  const caption = document.createElement("figcaption");
  caption.textContent = label;
  const canvas = document.createElement("canvas");
  canvas.width = 224;
  canvas.height = 156;
  figure.append(caption, canvas);
  grid.append(figure);
  return pibbl(
    canvas,
    <>
      <Rectangle style={{ width: 224, height: 156, fill: "#f1f4f5" }} />
      {Array.from({ length: 70 }, (_, i) => (
        <Rectangle
          key={i}
          style={{
            left: (i % 10) * 24,
            top: Math.floor(i / 10) * 24,
            width: 24,
            height: 24,
            fill: (i + Math.floor(i / 10)) % 2 ? "#e0e6e9" : "#f1f4f5",
          }}
        />
      ))}
      <Group style={{ filter }}>
        <Subject />
      </Group>
    </>,
  );
});
window.addEventListener(
  "pagehide",
  () => controllers.forEach((controller) => controller.dispose()),
  { once: true },
);

```

## Usage notes

- Each treatment changes one variable; the checkerboard remains outside the filtered group.

## Documentation version

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.
