Recolouring white, grey and black clothing

Garment recolouring is the most requested thing this operation is asked for, and neutral garments are where it stops behaving the way people expect. The reason is one number, and it is not a setting.

The floor, and what sits under it

A colour in OKLCH is three numbers: lightness, chroma and hue. Chroma is how much colour is present and hue is which colour it is, and the second of those is only meaningful while the first is not near zero. On a pixel with a chroma of four thousandths the hue angle is decided by rounding in the last bit of two channels: move one count and the angle can swing a hundred degrees. It is not a colour with a hue you could name. It is a grey with a rounding error.

This tool draws the line at about 0.02 in OKLCH and calls everything below it neutral. The figure is a working value rather than a measured one, and it decides more of the behaviour on this page than any control does. Above it, an operation has a hue to rotate and a chroma to scale. Below it, hue shift has nothing to act on, the chroma term in the selection does the separating instead of the hue term, and the rail says so in a note under the swatch rather than letting you find out by pressing the button.

Three garments, measured rather than described
GarmentRoughly, in OKLCHWhat hue shift can do
a white shirtL 0.93, C 0.008nothing
a mid grey coatL 0.55, C 0.010nothing
a navy jumperL 0.32, C 0.075a great deal

What absolute replace does instead

The second mode is not a lesser version of the first. It answers a different question. Hue shift asks what this colour would look like if it were a different colour; absolute replace asks what this region would look like if it were made of a different material of one colour. For a photographed painted surface the first question is the right one. For a neutral garment the first question has no content, and the second one does.

Mechanically it takes the target colour and modulates its lightness by the ratio of each pixel’s lightness to the weighted mean lightness of the selection. A crease that sat at seventy percent of the mean comes out at seventy percent of the target lightness; a highlight at a hundred and thirty percent comes out brighter. The chroma is the target’s chroma throughout, and the hue is the target’s hue throughout. That is why a white shirt done this way reads as a shirt of one colour with the original folds intact, and why the same operation on a photographed car reads as paint sprayed over a photograph.

Selecting a garment without a region tool

The harder half of this is not the remap, it is the selection. A white shirt and a white wall behind it are the same three numbers, and no tolerance setting will ever separate them, because there is nothing to separate: they are the same colour. This build has no painted region to intersect the selection with, so a neutral garment in front of a neutral background is outside what it can do. When the background is coloured — a white shirt against foliage, or a grey coat on a red brick street — the chroma tolerance does the whole job on its own, and a tight chroma with a wide lightness is the setting that works.

The practical sequence is: sample in the middle of the fabric with the 5 by 5 average, set chroma tight, open lightness until the shaded folds join the selection, and watch the coverage figure for the moment the background arrives. That moment is usually abrupt, and it is usually the wall.

Asked and answered

Why does hue shift do nothing at all to a white shirt?
Because there is nothing for it to rotate. Hue shift takes each selected pixel, replaces its hue angle with the target angle and scales its chroma by one factor. A pixel with a chroma of three thousandths, scaled by even the maximum factor of 1.6, still has a chroma of five thousandths — which is white. The operation ran correctly and produced a result indistinguishable from its input, which is the honest outcome rather than a failure.
So which mode does work on a white shirt?
Absolute replace. It writes the target colour across the selection and varies it only by how light each pixel already was relative to the selection's mean. On a white or light grey garment that works well, because the folds, the creases and the shading are all held in the lightness channel and the lightness channel is what it preserves. What it cannot do is invent saturation variation that was never there, so the result is a garment of one colour with real shading rather than a photographed dyed garment with colour variation in it.
Can a black jacket become a yellow one?
No, and it is worth being plain about why rather than offering a setting that pretends otherwise. Yellow is a light colour: it exists only at high lightness. A black garment in a photograph typically occupies a band eight to fifteen counts wide near zero, and there is no way to place a light colour there without raising the lightness of the region, which means inventing pixel values rather than remapping them. The tool will let you apply the operation and what comes back is a very dark olive smear with the folds gone. A dark blue or a deep burgundy is the realistic version of the same request, because both exist at the lightness the garment actually has.
What about a mid grey?
A mid grey is the best of the three. It has a full lightness range, enough of it in the middle for a saturated target to sit at, and no existing hue to argue with. Absolute replace on a mid grey garment is the case where this operation looks most like a real dye job. Set the target a little lighter than you think you want: the mean-relative modulation will carry the shading down from wherever you put it.

The general shape of the limit is worth stating once more without the specifics. Recolouring moves colour around; it does not create the range a colour needs to exist in. Where the lightness range is present and the hue is absent, assigning a hue works. Where the lightness range is absent, nothing works, and a tool that offers a control for it is offering a control that produces mud.

Back to the swatches

Every pixel is remapped locally — this page has no server to send to.