Last month I wrote about a color gamut mapping course that I took at the Color Imaging Conference in Portland, Oregon. I showed a couple of images in that post, in which I promised to post the code I used to create them. So today let me show you how I did it.
First, let me remind you of a couple of definitions I gave last time.
Colour gamut: a range of colours achievable on a given colour reproduction medium [...] under a given set of viewing conditions - it is a volume in colour space.
Gamut mapping: mapping of the colour-space coordinates of the elements of a source image to colour-space coordinates of the elements of a reproduction to compensate for differences in the source and output medium colur gamut capability.
The Image Processing Toolbox supports color transformations based on ICC color profiles, which are files containing information about the color characteristics of input, display, and output devices. The most relevant functions are iccread, makecform, and applycform.
If you have two profile files, for a source device and a destination device, you can convert from source device colors to destination colors using a sequence like this:
src_profile = iccread(src_profile_filename); dest_profile = iccread(dest_profile_filename); cform = makecform('icc', src_profile, dest_profile); dest_colors = applycform(src_colors, cform);
The color conversion steps embedded in ICC profile include gamut mapping when necessary. In fact, they often include multiple gamut mapping methods. That's because there are many methods that can be used for gamut mapping, and which one you choose depends on what you're trying to accomplish.
The ICC profile standard defines four general gamut mapping purposes, called rendering intents. They are:
- Perceptual - Optimizes gamut mapping to achieve the most aesthetically pleasing result. In-gamut colors might not be maintained.
- Absolute colorimetric - Maps out-of-gamut colors to the nearest gamut surface. Maintain relationship of in-gamut colors. Renders colors with respect to a perfect diffuser.
- Relative colorimetric - Maps out-of-gamut colors to the nearest gamut surface. Maintain relationship of in-gamut colors. Renders colors with respect to the white point of the device or output media.
- Saturation - Maximizes saturation of device colors, possibly at the expense of shifting hue. Intended for simple graphic charts and graphs rather than images.
We can use ICC profiles, with the right choice of rendering intents, to implement a process called soft proofing. Soft proofing simulates on a computer monitor the appearance that a color image would have if printed. One way to do soft proofing is to convert from monitor colors to destination colors using the perceptual rendering intent, and then convert those back to monitor colors using the absolute colorimetric rendering intent. That's how I generated the image shown in my November gamut mapping post. I used the sRGB.icm profile that ships with the Image Processing Toolbox, together with a newsprint profile (SNAP 2007) that I obtained from the ICC profile registry.
Below is the code. I'll add one step that I didn't do last time - I'll put a white border around the original image. That way, you'll be able to see the "newsprint white" in the soft proof, and the overall newsprint image will a bit more sense. (Thanks for the suggestion, Jeff.)
rgb = imread('peppers.png'); rgb = padarray(rgb, [30 30], 255, 'both'); % Put a thin gray border around the padded image. rgb = padarray(rgb, [2 2], 230, 'both'); imshow(rgb)
Read in both profiles, and use makecform to make a cform structure used by the first color conversion step. Use the perceptual rendering intent.
p_rgb = iccread('sRGB.icm'); p_snap = iccread('SNAP2007.icc'); cform = makecform('icc', p_rgb, p_snap, ... 'SourceRenderingIntent', 'Perceptual', ... 'DestRenderingIntent', 'Perceptual'); newsprint_image = applycform(rgb, cform); size(newsprint_image)
ans = 448 576 4
Notice that the third dimension of the newsprint image is 4, not 3. That's because the newsprint image is in CMYK space.
Now construct another cform structure for converting back to sRGB space, using the absolute colorimetric rendering intent.
cform2 = makecform('icc', p_snap, p_rgb, ... 'SourceRenderingIntent', 'AbsoluteColorimetric', ... 'DestRenderingIntent', 'AbsoluteColorimetric'); soft_proof = applycform(newsprint_image, cform2); imshow(soft_proof)
Doesn't the garlic in the lower right of the image look whiter than the padding, which is supposed to be "newsprint white"? It does to me anyway, and it made me worry that I had done something wrong. But it turns out to be an optical illusion. I used imtool to verify that the brightest part of the garlic is actually the same color as the padding.
To leave a comment, please click here to sign in to your MathWorks Account or create a new one.