RGB to LCH converter
Describe an RGB color the way people adjust it: lightness from 0 for black to about 100 for white, chroma as colorfulness and hue as an angle from 0 up to 360°. Change one without disturbing the others. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Resistance (Ω)
- 255
- G
- 128
- B
- 0
- L
- 67.0548169961
- C
- 85.5142055704
- H
- 59.9466748349
- L star
- 67.0548169961
This RGB to LCH converter takes three sRGB channel intensities—red, green, and blue—each as an integer from zero through two hundred fifty-five, and returns CIE LCH coordinates (lightness L*, chroma C*, and hue angle h° in degrees) computed under the standard D65 white point used in web and print workflows. Designers, accessibility engineers, and students use LCH when a palette lives in eight-bit channels but the task needs a perceptually structured space where lightness, chroma, and hue can be edited independently without the rectangular a* and b* axes of Lab. The engine is fully deterministic: it inverse-compands each channel, multiplies by the D65 sRGB-to-XYZ matrix, normalizes by the D65 reference white, forms CIE Lab, then derives C* as the hypot of a* and b* and h° from atan2 of b* and a*—never calling the network, sampling randomness, or depending on the clock.
How RGB becomes lightness, chroma and hue
In the eight-bit sRGB model used by CSS and most web graphics, each of red, green, and blue is an integer channel from zero through two hundred fifty-five. CIE LCH is the polar form of CIE L*a*b*: the same stimulus is expressed as lightness L* (roughly zero for black through about one hundred for diffuse white), chroma C* measuring distance from the neutral axis, and hue h° as an angle around that axis in degrees from zero up to but not including three hundred sixty.
Conversion first scales each channel by dividing by two hundred fifty-five, then undoes sRGB gamma (the IEC six-one-nine-six-six inverse companding curve) so the values become linear light. Those linear channels pass through a fixed three-by-three matrix into CIE XYZ under illuminant D65; each tristimulus component is divided by the D65 reference white, then the CIE pivot function f is applied—cube root above a small threshold, linear branch below—to form L*, a*, and b*.
From Lab the cylindrical step is closed-form: C* equals the Euclidean length of the a*b* vector, and h° equals the two-argument arctangent of b* and a* converted to degrees and wrapped into the half-open interval from zero to three hundred sixty. When chroma is effectively zero the hue is undefined geometrically, so this calculator defines h° as zero for achromatic colors such as pure black, pure white, and neutral grays.
There is no path that accepts percentages or floating-point channels as input, and no silent clamp of two hundred fifty-six down to two hundred fifty-five.
Where RGB-to-LCH conversion fits in design, study, and software
Designers meet this mapping when a brand guide lists RGB swatches and a production or perceptual-editing workflow expects LCH targets, when lightness must stay fixed while hue rotates for tints and shades, or when a design system documents both screen RGB and LCH reference values side by side for ramp generation.
Accessibility engineers use L* and C* when reasoning about perceived lightness separately from chromatic strength, when checking that two UI states remain distinguishable after hue shifts, or when preparing notes that will later feed formal delta-E checks in Lab before re-expressing the same color as LCH for authoring.
Students see it in computer-graphics and color-science courses that introduce XYZ, Lab, and then the cylindrical LCH form, in digital photography classes that move between channel sliders and hue-chroma controls, and in interview warm-ups that ask for a mental convert of a short triple into polar Lab coordinates. Pair it with multi-format color tools when you need hex or CMYK, with the Lab converter when you need rectangular a* and b* only, and with other free deterministic converters when you are building a small lab for design-system hygiene.
What you can do with it
Perceptual editing with independent hue and chroma
Turn brand RGB triples into CIE LCH so designers can rotate hue or scale chroma while holding lightness fixed for ramps and variants.
Homework and teaching demos
Check student sRGB-to-LCH work and live-demo XYZ, Lab, and polar LCH without opaque calculator apps.
FAQ
What does the RGB to LCH converter cost?
It is free in your browser on this page.
What range is allowed for r, g, and b?
Each channel must be an integer from 0 to 255 inclusive.
What white point and path does this use?
The chain is sRGB → linear → XYZ → Lab → LCH.
How are C* and h° defined from Lab?
C* is hypot(a*, b*). Hue h° is atan2(b*, a*) in degrees, wrapped to [0, 360). When C* is effectively zero (achromatic), h° is defined as 0.
Why does a gray get a hue of 0?
Gray, black and white have no chroma, so their hue angle is undefined. The converter sets it to 0 as a fixed convention, so the same neutral color always gives the same result.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/color/rgb-lch \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"r":255,"g":128,"b":0}'const res = await fetch("https://api.kit.forhosting.com/color/rgb-lch", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"r": 255,
"g": 128,
"b": 0
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/rgb-lch",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"r": 255,
"g": 128,
"b": 0
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/rgb-lch", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"r":255,"g":128,"b":0}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"r":255,"g":128,"b":0}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/rgb-lch", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"r": 255,
"g": 128,
"b": 0
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.rgb_lch",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
min_channel | 0 |
max_channel | 255 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Channels outside zero through two hundred fifty-five are rejected with a clear invalid_input error rather than silently clamped.
What RGB-to-LCH conversion means and what the response contains
The response returns the validated integers r, g, and b; L, C, and H (with aliases L_star, C_star, and h_deg); intermediate Lab a* and b* as a, lab_b, a_star, and b_star so Lab b* never collides with the RGB blue channel; intermediate X Y Z; rgb, lch, and lab summary strings; white_point set to D65; a method tag rgb_to_lch; and a short formula reminder. The engine either builds an exact LCH triple for three legal channels or rejects the request with invalid_input. Rejected cases include a missing r, g, or b field, empty strings after trimming, non-integer numbers, non-numeric text, Infinity or NaN, and any channel strictly below zero or above two hundred fifty-five.
How r, g, and b are read and how LCH stays reproducible
Outer whitespace on string channels is trimmed; an optional leading plus is allowed only when the remaining characters are decimal digits that parse to an integer in range. A bare JavaScript number is accepted only when it is a finite integer inside zero through two hundred fifty-five; values such as one hundred twenty-eight point five fail validation rather than being rounded, and negative or two-hundred-fifty-six-plus values fail with a message that names the channel and states that it must stay inside zero through two hundred fifty-five. Pure red maps to a moderate L* with large C* and a hue near forty degrees; pure white and pure black map to zero chroma with h° defined as zero; saturated greens and blues land at the expected hue sectors of the Lab plane. The preferred fields are r for red, g for green, and b for blue, but aliases red and capital R for red, green and capital G for green, and blue and capital B for blue are accepted so spreadsheets, query strings, and typed forms can reuse the same contract without renaming columns. After validation, conversion uses only closed-form arithmetic on the linear channels, the D65 white point, Lab identities, and polar chroma-hue transforms, then rounds floating components to a fixed decimal width so JSON goldens and CI assertions stay stable across platforms. Pair the free browser run on this page with the priced API when you need the identical mathematical result inside an automated pipeline without re-implementing inverse gamma, D65 normalization, and Lab-to-LCH polar conversion yourself.
Where RGB-to-LCH conversion fits in design, study, and software
On this page the work runs entirely in your browser; through the API each successful lookup costs $0.002, failed validation is not charged, and nothing is stored after the response returns. That split—free interactive exploration and a priced, identical API—matches the rest of the KIT tier-A catalog and lets you move from a classroom demo or design review to an automated pipeline without changing the mathematical result.
Integration use cases
Deterministic test fixtures
Generate reproducible LCH results for unit tests, property checks, and CI assertions on color helpers and design tokens.
Technical questions
Why is 256 rejected instead of clamped?
Silent clamping hides data errors. Out-of-range channels fail with invalid_input so callers fix the source values instead of publishing the wrong color.