Steve Eddins retired from MathWorks in 2024 after 30 years of service. He can now be found at MATLAB Central and at Matrix Values, where he continues to write about MATLAB and related topics. His MathWorks career included image processing, toolbox development, MATLAB development and design, development team management, and MATLAB design standards. He wrote the Steve on Image Processing blog for 18 years and is a co-author of Digital Image Processing Using MATLAB.
An amateur musician and French horn enthusiast, Steve is a member of Concord Orchestra and Melrose Symphony Orchestra, as well as a member of the board of directors for Cormont Music and the Kendall Betts Horn Camp. He blogs about music and French horn at Horn Journey.
I was looking today at an old post, "A Lab-based uniform color scale" (09-May-2006). I wanted to provide an update to illustrate that it is easier to convert from Lab to RGB colors now than it was then. When I reread the original post, though, I realized that I was naive back then about the possibility that constructing a colormap using a path in Lab space could result in out-of-gamut colors when converting to sRGB.
After thinking it over, I think I'd like to do two (or maybe three) follow-up posts. The first follow-up post, today, will focus on some ways to visualize where a curve in Lab space goes out-of-gamut for sRGB. Next, I'll explore ways to modify the technique I demonstrated previously in order to avoid out-of-gamut colors.
Here is the colormap I showed in the 09-May-2006 post:
What I didn't realize when writing that 2006 post is that some of those Lab colors are not in the gamut of the sRGB color space. We can determine that by looking at the color component values in rgb to see if there are any that are outside the range $[0,1]$.
rgb = lab2rgb(lab);
max(rgb(:))
ans = 1.1271
min(rgb(:))
ans = -0.1144
This led me to explore different ways to visualize which colors in a Lab curve are out of gamut. (Note that this discussion assumes that we are talking about sRGB, which is the default color space used by lab2rgb.) The first thing I tried was to add marks to the displayed colormap to indicate which colors are out-of-gamut. This next block of code finds all the contiguous segments of out-of-gamut colors in the colormap.
The values of first and last above mean that the Lab colors lab(1:61,:) and lab(211:256,:) are out of the sRGB gamut. Now use these numbers to add gamut alarm indicators (red bars) to the displayed colormap.
hold on
y = [1.25 1.25];
for k = 1:length(first)
x1 = first(k) - 1;
x2 = last(k);
x = [x1 x2];
plot(ax,x,y,"r",LineWidth = 5)
end
hold off
Another visualization approach is to plot the red, green, and blue color component values returned by lab2rgb and show where those values are too high or too low.
figure
hold on
plot(rgb(:,1),'r')
plot(rgb(:,2),'g')
plot(rgb(:,3),'b')
xlim([1 - 0.05*height(rgb), 1.05*height(rgb)]);
y1 = min(-0.2,ax.YLim(1));
y2 = max(1.2,ax.YLim(2));
ylim([y1 y2]);
grid("on")
yline(0, LineWidth = 5, Color = [0.7 0.7 0.7])
yline(1, LineWidth = 5, Color = [0.7 0.7 0.7])
too_high = any(rgb > 1,2);
k = find(too_high);
if ~isempty(k)
plot(k,ones(size(k)),'r*',MarkerSize = 6)
end
too_low = any(rgb < 0,2);
k = find(too_low);
if ~isempty(k)
plot(k,zeros(size(k)),'r*',MarkerSize = 6)
end
hold("off")
title("RGB values with gamut alarm")
Next I want to show the a and b values for the out-of-gamut Lab curve colors.
plot(lab(:,2),lab(:,3));
axis equal
xlim([-110 110])
ylim([-110 110])
ax = gca;
ax.XAxisLocation = "origin";
ax.YAxisLocation = "origin";
xlabel("a")
ylabel("b")
hold on
for k = 1:length(first)
j1 = first(k);
j2 = last(k);
x = lab(j1:j2,2);
y = lab(j1:j2,3);
plot(x,y,"r",LineWidth = 5)
end
hold off
grid(ax,"on")
title("a-b values with gamut alarm")
Finally, I want to show the L values for the out-of-gamut Lab curve colors.
plot(lab(:,1));
xlim([1 - 0.05*height(lab), 1.05*height(lab)]);
ylim([-10 110])
hold on
for k = 1:length(first)
j1 = first(k);
j2 = last(k);
x = j1:j2;
y = lab(j1:j2,1);
plot(x,y,"r",LineWidth = 5)
end
hold off
grid on
title("L values with gamut alarm")
I created some utility functions that generate these different plots. They are at the end of this post. I'll finish up by using tiledlayout to combine all four plots in a single figure.
Comments
To leave a comment, please click here to sign in to your MathWorks Account or create a new one.