🎨 Image Color Picker
Pick colours from a photo as HEX, RGB and HSL. Samples an area rather than one noisy pixel, averages correctly, and gives the WCAG contrast for text.
Choose an image, or drop it here
Read in this tab — the image is never uploaded.
What Image Color Picker Does
Sampling a colour from a photograph is not as simple as reading the pixel under the cursor, and the difference between a good eyedropper and a frustrating one is entirely in what it does about that. JPEG stores colour information at half resolution, camera sensors add noise, and every edge in the image is antialiased — so the exact pixel you clicked can be several units away from the colour you can plainly see. Professional editors expose a sample-size control for this reason, and so does this.
The averaging itself has a correct and an incorrect way to do it, and most tools do it incorrectly. sRGB values are gamma-encoded: they are not proportional to light, they are proportional to a perceptual curve. Averaging them arithmetically biases the result dark. Across a black-and-white boundary the naive mean is 128, while the value that actually corresponds to averaging the light is 188 — a difference nobody would call subtle. Converting to linear light, averaging there, and converting back is what this does.
And because the question immediately after "what colour is this?" is almost always "can I put text on it?", the WCAG contrast ratio against both white and black is computed and shown. That one has a defined answer rather than being a matter of taste: 4.5:1 for body text, 3:1 for large text.
The image is read into a canvas in your browser and sampled there. Nothing is transmitted, which matters when the thing you are pulling colours out of is a screenshot of something private.
How to Use Image Color Picker
- Add an image, or drop it onto the box
- Set the sample area — 5 × 5 for photographs, 1 × 1 for flat graphics
- Click anywhere on the image to sample
- Copy the HEX, RGB or HSL value, and check the contrast figures before putting text on it
Formula Used by Image Color Picker
Averaging colour correctly
mean = toSrgb( Σ toLinear(cᵢ) / n ) where toLinear(s) = s ≤ 0.04045 ? s/12.92 : ((s+0.055)/1.055)^2.4
- cᵢ
- each sampled channel value, 0–255
- toLinear
- the sRGB transfer function, undoing the gamma encoding
- 12.92 / 0.04045
- the linear segment the sRGB standard defines near black
Worked example
Two pixels on a hard edge: pure black and pure white.
- Naive average in sRGB: (0 + 255) ÷ 2 = 128
- Correct: toLinear(0) = 0, toLinear(255) = 1, mean = 0.5
- Back to sRGB: 1.055 × 0.5^(1/2.4) − 0.055 = 0.7354
- 0.7354 × 255 = 188
Result: 188, not 128. A 60-unit error, which is why a tool that averages gamma-encoded values reads consistently dark on any textured or edged area.
WCAG contrast ratio
(L₁ + 0.05) ÷ (L₂ + 0.05), L = 0.2126·R + 0.7152·G + 0.0722·B in linear light
- L₁, L₂
- the lighter and darker relative luminances
- 0.2126 / 0.7152 / 0.0722
- the luminance weights — green dominates, which is why green text on white is harder than it looks
Worked example
Black text on a white background.
- L(white) = 1.0, L(black) = 0.0
- (1.0 + 0.05) ÷ (0.0 + 0.05) = 21
Result: 21:1, the maximum possible. Thresholds are 4.5:1 for body text and 3:1 for large text.
Choosing a sample size
| Size | Use for |
|---|---|
| 1 × 1 | Flat graphics, screenshots, UI — where you want the literal stored value |
| 3 × 3 to 5 × 5 | Photographs — the default, and what most editors use |
| 9 × 9 or larger | Noisy, grainy or heavily compressed photos, and skin tones |
How to Read Your Result
Two tools disagreeing is usually the sample size
A tool reading a single pixel where this reads a 5 × 5 mean will differ on any photograph, and one averaging in gamma-encoded sRGB will read darker than this. On a flat graphic at 1 × 1 they should agree exactly — if they do not, something else is wrong.
A colour picked from a photo is a starting point
Photographs carry the colour of their lighting. A brand colour sampled from a product photo taken under warm light will be warmer than the real thing. Sample several places and reconcile, or get the value from the source rather than from a picture of it.
Check the contrast before committing to a colour
A brand colour that fails 4.5:1 against both white and black is going to cause problems everywhere text sits on it. Finding that out at the picking stage is much cheaper than finding out during an accessibility audit.
Limitations & Accuracy Notes
- Colour profiles are not applied. A wide-gamut image tagged Display P3 is read as sRGB, so very saturated colours will differ from what a colour-managed editor reports.
- Values come from the decoded image, so a JPEG’s compression artefacts are part of what you sample — which is exactly why the area average exists.
- No zoom. On a very large image, fine positioning is limited by how big the preview is on screen.
- No palette extraction — this samples where you click rather than proposing a scheme.
- The contrast figures cover text on this colour as a solid background. Text over a photograph varies pixel by pixel and needs a different treatment entirely.
Frequently Asked Questions
Why sample an area instead of a single pixel?
What does "averaged in linear light" mean and why should I care?
Why show a contrast ratio?
Is my photo uploaded?
Why do I get a slightly different value from another tool?
References & Further Reading
- WCAG 2.2 — Contrast (Minimum) — The 4.5:1 and 3:1 thresholds and the contrast formula
- WCAG — relative luminance definition — The luminance weights and the linearisation step used here
- MDN — CanvasRenderingContext2D.getImageData() — How the pixels are read back for sampling