Why convert CMYK to HSV?
HSV (often labelled HSB in design apps) splits a color into hue, saturation and brightness, which is much easier to adjust by eye than four ink percentages. Converting a print color like 20, 0, 60, 10 gives hsv(80, 60%, 90%), a yellow-green you can now nudge with sliders. The tool converts through RGB at full precision and rounds only the final values.
A typical case: you've inherited a print palette defined in CMYK and want to build lighter and darker variants for a web or app interface. Doing that in ink percentages is guesswork, while in HSV it's a matter of moving one number.
How the tool gets from ink to HSV
There's no direct CMYK-to-HSV formula in common use, so the converter chains two well-known ones:
- CMYK to RGB with the naive formula from the W3C's CSS Color Module Level 5 draft: R = 255 × (1 − C) × (1 − K), and the same for green with M and blue with Y.
- RGB to HSV: value is the largest channel, saturation is (largest − smallest) / largest, and hue is the angle set by which channel leads.
No rounding happens between the two steps. That's why 0, 35, 85, 0 returns hsv(35.3, 85%, 100%) here, while going through the rounded rgb(255, 166, 38) first would give hsv(35.4, 85.1%, 100%).
What black ink does to HSV
The ink math produces a neat pattern worth knowing. Because K multiplies all three RGB channels by the same (1 − K), it can't change their ratios. Hue and saturation depend only on C, M and Y, and K only pulls value down:
| CMYK | HSV |
|---|---|
| 82, 44, 0, 0 | hsv(212.2, 82%, 100%) |
| 82, 44, 0, 30 | hsv(212.2, 82%, 70%) |
| 82, 44, 0, 60 | hsv(212.2, 82%, 40%) |
Two shortcuts fall out of the algebra, using fractions:
- V = (1 − K) × (1 − smallest of C, M, Y). In the rows above the smallest ink is 0, so V is simply 100% minus K.
- S = 1 − (1 − largest ink) / (1 − smallest ink). With the smallest ink at 0, S equals the largest ink, which is why 82% cyan gives 82% saturation.
So a CMYK color that uses only two colored inks plus black maps very cleanly: the stronger ink becomes saturation, black becomes darkness, and the ratio between the two colored inks sets the hue.
Worked example
Take C20 M0 Y60 K10:
- RGB fractions: red = 0.80 × 0.90 = 0.72, green = 1.00 × 0.90 = 0.90, blue = 0.40 × 0.90 = 0.36.
- Value = largest = 0.90, so V = 90%. (Shortcut check: (1 − 0.10) × (1 − 0) = 0.90.)
- Saturation = (0.90 − 0.36) / 0.90 = 0.60, so S = 60%. (Shortcut: largest ink is 60%.)
- Green leads, so hue = 60 × ((blue − red) / 0.54 + 2) = 60 × (−0.667 + 2) = 80°.
Result: hsv(80, 60%, 90%).
Building a tint and shade ladder
Here's a practical way to use the output:
- Convert your base print color here and note the hue.
- In your design app's HSB picker, keep that hue fixed.
- For shades, lower V in even steps (90, 75, 60, 45).
- For tints, lower S while keeping V high.
- If any variant needs to go back to print, convert it with HSV to CMYK and get a proof, since the naive formulas ignore your printer's ICC profile.
Limits and edge cases
Input is four numbers from 0 to 100 in C, M, Y, K order, with commas, spaces, hyphens, percent signs or a cmyk() wrapper. Fewer than four numbers or anything out of range shows "Enter valid CMYK percentages (0-100)". A list of 0-1 fractions such as 0.2, 0, 0.6, 0.1 (no % signs, every value 1 or less, at least one decimal) gets a hint to enter percentages instead, since reading it as 0.2% would give a near-white result; add % signs if you really mean values that small.
Equal C, M and Y produce a gray: 50, 50, 50, 0 gives hsv(0, 0%, 50%). Hue is meaningless there and reported as 0. Any color with K at 100 returns hsv(0, 0%, 0%), so rich blacks such as 60, 40, 40, 100 can't be told apart.
Keep in mind that all of this is ideal-ink arithmetic. Printed cyan is not the hsv(180, 100%, 100%) that 100, 0, 0, 0 produces here.
For the screen color itself, CMYK to RGB or CMYK to HEX gives a value you can use in code. If your palette is defined as Pantone references, Pantone to HSV works from those instead.
Last updated