The task I want to achieve is to replicate Photoshop RGB to LAB conversion.
For simplicity, I will describe what I did to extract only the L Channel.
Extracting Photoshop’s L Channel
Here is RGB Image which includes all RGB colors (Please click and download):
In order to extract Photoshop’s LAB what I did is the following:
- Loaded the image into Photoshop.
- Set Mode to LAB.
- Selected the L Channel in the Channel Panel.
- Set Mode to Grayscale.
- Set mode to RGB.
- Saved as PNG.
This is the L Channel of Photoshop (This is exactly what seen on screen when L Channel is selected in LAB Mode):
sRGB to LAB Conversion
My main reference is Bruce Lindbloom great site.
Also known is that Photoshop is using D50 White Point in its LAB Mode (See also Wikipedia’s LAB Color Space Page).
Assuming the RGB image is in sRGB format the conversion is given by:
sRGB -> XYZ (White Point D65) -> XYZ (White Point D50) -> LAB
Assuming data is in Float within the [0, 1] range the stages are given by:
- Transform sRGB into XYZ.
The conversion Matrix is given by RGB -> XYZ Matrix (See sRGB D65). - Converting from XYZ D65 to XYZ D50
The conversion is done using Chromatic Adaptation Matrix. Since the previous step and this are Matrix Multiplication they can be combined into one Matrix which goes from sRGB -> XYZ D50 (See the bottom of RGB to XYZ Matrix). Note that Photoshop uses Bradford Adaptation Method. - Convert from XYZ D50 to LAB
The conversion is done using the XYZ to LAB Steps.
MATLAB Code
Since, for start, I’m only after the L Channel things are a bit simpler. The images are loaded into MATLAB and converted into Float [0, 1] range.
This is the code:
%% Setting Enviorment Parameters
INPUT_IMAGE_RGB = 'RgbColors.png';
INPUT_IMAGE_L_PHOTOSHOP = 'RgbColorsL.png';
%% Loading Data
mImageRgb = im2double(imread(INPUT_IMAGE_RGB));
mImageLPhotoshop = im2double(imread(INPUT_IMAGE_L_PHOTOSHOP));
mImageLPhotoshop = mImageLPhotoshop(:, :, 1); %<! All channels are identical
%% Convert to L Channel
mImageLMatlab = ConvertRgbToL(mImageRgb, 1);
%% Display Results
figure();
imshow(mImageLPhotoshop);
title('L Channel - Photoshop');
figure();
imshow(mImageLMatlab);
title('L Channel - MATLAB');
Where the function ConvertRgbToL()
is given by:
function [ mLChannel ] = ConvertRgbToL( mRgbImage, sRgbMode )
OFF = 0;
ON = 1;
RED_CHANNEL_IDX = 1;
GREEN_CHANNEL_IDX = 2;
BLUE_CHANNEL_IDX = 3;
RGB_TO_Y_MAT = [0.2225045, 0.7168786, 0.0606169]; %<! D50
Y_CHANNEL_THR = 0.008856;
% sRGB Compensation
if(sRgbMode == ON)
vLinIdx = mRgbImage < 0.04045;
mRgbImage(vLinIdx) = mRgbImage(vLinIdx) ./ 12.92;
mRgbImage(~vLinIdx) = ((mRgbImage(~vLinIdx) + 0.055) ./ 1.055) .^ 2.4;
end
% RGB to XYZ (D50)
mY = (RGB_TO_Y_MAT(1) .* mRgbImage(:, :, RED_CHANNEL_IDX)) + (RGB_TO_Y_MAT(2) .* mRgbImage(:, :, GREEN_CHANNEL_IDX)) + (RGB_TO_Y_MAT(3) .* mRgbImage(:, :, BLUE_CHANNEL_IDX));
vYThrIdx = mY > Y_CHANNEL_THR;
mY3 = mY .^ (1 / 3);
mLChannel = ((vYThrIdx .* (116 * mY3 - 16.0)) + ((~vYThrIdx) .* (903.3 * mY))) ./ 100;
end
As one could see the results are different.
Photoshop is much darker for most colors.
Anyone knows how to replicate Photoshop’s LAB conversion?
Anyone can spot issue in this code?
Thank You.
2
Answers
Latest answer (we know that it is wrong now, waiting for a proper answer)
Photoshop is a very old and messy software. There’s no clear documentation as to why this or that happens to the pixel values when you are performing conversions from a mode to another.
Your problem happens because when you are converting the selected L* channel to Greyscale in Adobe Photoshop, there’s a change in gamma. Natively, the conversion uses a gamma of 1.74 for single channel to greyscale conversion. Don’t ask me why, I would guess this is related to old laser printers (?).
Anyway, this is the best way I found to do it:
Open your file, turn it to LAB mode, select the L channel only
Then go to:
Edit > Convert to profile
You will select “custom gamma” and enter the value 2.0 (don’t ask me why 2.0 works better, I have no idea what’s in the mind of Adobe’s software makers…)
This operation will turn your picture into a greyscale one with only one channel
Then you can convert it to RGB mode.
If you compare the result with your result, you will see differences up to 4 dot something % – all located in the darkest areas.
I suspect this is because the gamma curve application does not appy to LAB mode in the dark values (Cf. as you know, all XYZ values below 0.008856 are linear in LAB)
CONCLUSION:
As far as I know, there is no proper implemented way in Adobe Photoshop to extract the L channel from LAB mode to grey mode!
Previous answer
this is the result I get with my own method:
It seems to be exactly the same result as the Adobe Photoshop one.
I am not sure what went wrong on your side since the steps that you are describing are exactly the same ones that I followed and that I would have advised you to follow. I don’t have Matlab so I used python:
the Syn library is my own stuff, here are the functions (sorry for the mess):
All conversions between colour spaces in Photoshop are through CMM, which is sufficiently fast on circa 2000 hardware, and not quite accurate. You can have a lot of 4-bit errors and some 7-bit errors with Adobe CMM if you check “round robin” – RGB -> Lab -> RGB. That may cause posterisation. I always base my conversions on formulae, not on CMMs. However the average deltaE of the error with Adobe CMM and Argyll CMM is quite acceptable.
Lab conversions are quite similar to RGB, only the non-linearity (gamma) is applied at the first step; something like this:
normalize XYZ to white point
bring the result to gamma 3 (keeping shadow portion linear, depends on implementation)
multiply the result by [0 116 0 -16; 500 -500 0 0; 0 200 -200 0]’