Can someone explain the algorithm behind the "Black and White" adjustment layer in photoshop?

Photoshop screenshot

I have to reproduce it using C++ for an application that emphasizes non-red/magenta(ish) pixels from an image (with a percent-like configurable tolerance), and this resource showed the behavior I'm expecting.

Update: Still couldn't reproduce it, but I found a clue:

Each pixel is defined by up to two controls, one additive (RGB) and one subtractive (CMY).

  • $\begingroup$ Did you ever get any closer to figuring out the algorithm? I'm trying to figure this out as well. $\endgroup$
    – pizzafilms
    Commented May 15, 2013 at 16:26
  • $\begingroup$ No, i didn't :/ $\endgroup$
    – Blamoo
    Commented May 16, 2013 at 16:58

2 Answers 2


I replicated the algorithm perfectly in MATLAB (Based on @Ivan Kuckir answer):

function [ mO ] = ApplyBlackWhiteFilter( mI, vCoeffValues )

FALSE   = 0;
TRUE    = 1;

OFF = 0;
ON  = 1;

numRows = size(mI, 1);
numCols = size(mI, 2);
dataClass = class(mI);

numCoeff    = size(vCoeffValues, 1);
hueRadius   = 1 / numCoeff;
vHueVal     = [0:(numCoeff - 1)] * hueRadius;

mHsl = ConvertRgbToHsl(mI);
mO = zeros(numRows, numCols, dataClass);

vCoeffValues = numCoeff * vCoeffValues;

for jj = 1:numCols
    for ii = 1:numRows
        hueVal = mHsl(ii, jj, 1);
        lumCoeff = 0;
        % For kk = 1 we're dealing with circular distance
        diffVal     = min(abs(vHueVal(1) - hueVal), abs(1 - hueVal));
        lumCoeff    = lumCoeff + (vCoeffValues(1) * max(0, hueRadius - diffVal));
        for kk = 2:numCoeff
            lumCoeff = lumCoeff + (vCoeffValues(kk) * max(0, hueRadius - abs(vHueVal(kk) - hueVal)));
        mO(ii, jj) = mHsl(ii, jj, 3) * (1 + lumCoeff);


Pay attention that the conversion from vPhotoshopValues to vCoeffValues should be done as vCoeffValues = (vPhotoshopValues - 50) ./ 50.
As Photoshop values are in [-200, 300] and should be linearly mapped into [-5, 5] with 50 -> 0.

Here is a comparison to Photoshop:

enter image description here

The maximum error is less than 1 in [0, 255] range.

The MATLAB code is available at my StackExchange Signal Processing Q29041 GitHub Repository (Look at the SignalProcessing\Q688 folder).


Each (color) image is composed of RGB components. when you add (or reduce) a constant value to all pixels only in RED components you will see the effect equivalent to moving the RED tab towards the right, and same way reducing the RED component by a constant will have the reverse effect.

Like wise you can increment/decrement each component by a fixed value as described. If you increase/decrease ALL RGB components by a same value this will be equivalent to change in brightness (basically you are adding/removing WHITE color).

The Cyan, Blue, Magenta - corresponds to such transformation in CMYK color space. (But i guess, Blue in this color space corresponds to mix of Cyan and Yellow. So that's a bit tricky. The transformation is essentially same for all.

The last element Tint: { Hue and Saturation } corresponds to same operations but here, the images is first transformed in HSV model and then HUE and Saturation is added/subtracted independently.

I don't know about the exact relationships of markers of the dial to the corresponding numbers but that you can figure out by trying out practical values.

  • 1
    $\begingroup$ There is RGB and CMY, so all you need to do is transform to any of the two color spaces and you can adjust as much as you want. Just don't forget to update the other triplet once you're done adjusting. $\endgroup$
    – Jonas
    Commented Nov 23, 2011 at 17:13
  • $\begingroup$ I believe this answer is incorrect and incomplete. 1. In the PS implementation, sliding the "blue" slider doesn't affect the brightness of cyan-ish pixels and sliding the "cyan" slider doesn't afffect the brightness of blue-ish pixels. This approach described in this answer wouldn't work like that. 2. you don't describe how, after RGBCMY components are manipulated, they're converted to grayscale (although it's probably a dotProduct(color, vec3(0.2989, 0.5870, 0.1140) operation). 3. Blue doesn't "correspond to a mix of cyan and yellow" in any color space. $\endgroup$ Commented Jan 11, 2017 at 21:09
  • $\begingroup$ 4. You don't mention that the tint operation is performed after the conversion to grayscale and not before that. $\endgroup$ Commented Jan 11, 2017 at 21:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.