Hits
4 min read (667 words)

Have you ever wondered why we perceive slight differences in the colors between two identical images, when one is viewed on a Mac and the other on an LG display? Although both images were captured of the same object or scene, and with the same camera hardware, what exactly results in the differences in colors during viewing? In this post, I would like to explore this technical phenomenon.

The color of an image is an indispensable element of its visual appearance. Manufacturers of imaging, printing, and display hardware take great care in the color representation capability of their products. Consistency in colors is a must, as it speaks volumes about the quality of the product [1]. Skilled digital content creators, video and photo editors, who understand the gist of color science, can manipulate the picture production process to achieve aesthetically pleasing outputs.

Field experts refer to ICC profiles [2] to characterize the color attributes of a particular device, whether it’s input or output. It is principally a mapping between the source and target device, as well as the (intermediate) profile connection space (on which I recommend referring to [3] for more information). Manufacturers of the device can either utilize one of the openly available ICC profiles or develop their own. For instance, sRGB is a commonly accepted, ubiquitous standard, assuming no color profile information was originally embedded or tagged.

Fig. 1. Color gamut of the ICC profiles
Fig. 1. Color gamut of the ICC profiles

In the picture above, we can see the color gamut belonging to each profile. It was obtained using ColorSync Utility, which is available on Mac. The ICC profiles can be downloaded from here [5]. As we can observe, both the ProPhoto and WideGamut color profiles have the widest trichromatic gamuts, visualized as color triangles. They can encompass a larger range of colors, making them suitable for high-quality imaging applications, such as those from digital cameras. ProPhoto is commonly used in professional photography workflows, especially when working with RAW image files. AppleRGB has the smallest gamut size, similar to sRGB, but with slightly different color primaries. It is not as widely used as ProPhoto RGB but may be encountered in workflows involving Apple devices and software. Adobe RGB has a larger gamut than AppleRGB but is still smaller compared to ProPhotoRGB. Developed by Adobe Systems, it is widely used in the printing industry and is suitable for preserving color accuracy when images are being printed, as long as printers can reproduce colors within the AdobeRGB gamut.

Fig. 2. Visual comparison of the images after applying ICC profile
Fig. 2. Visual comparison of the images after applying ICC profile

Next, I have created a figure to demonstrate the effect of various ICC profiles side-by-side. While it may not be immediately noticeable, upon closer inspection, the ProPhoto profile exhibits distinctions. More vibrant and saturated colors are observable in this ICC profile, as expected. I believe this can serve as another tip to achieve a slightly higher quality representation of color: by selecting the ProPhoto ICC profile mode in photo editing software.

\[\begin{bmatrix} X \\ Y \\ Z \end{bmatrix} = \begin{bmatrix} M \end{bmatrix} \begin{bmatrix} R \\ G \\ B \end{bmatrix}\]

Since there is a variety of ICC color profiles, a fundamental step in color management is to be able to convert images from the RGB working space into the XYZ color space (as shown in the equation above). The XYZ color space is an absolute, device-independent color model [6]. It represents color spectra from a physical perspective, closer to how human eyes perceive them. Converting from RGB to XYZ allows us to work with colors in a standardized manner, ensuring consistency and predictability in color transformations. Thanks to Bruce Lindbloom’s derived RGB/XYZ matrices [7], which are summarized below for the ICC profiles used.

Table. 1. Summary of transformation matrices for the ProPhoto, AdobeRGB, AppleRGB and WideGamut ICC profiles
Table. 1. Summary of transformation matrices for the ProPhoto, AdobeRGB, AppleRGB and WideGamut ICC profiles

For the hands-on part of this post, I recommend referring to the Appendix section. In the first example, a simple script illustrates how to save an image using a specific ICC profile. This script can be used for similar tasks, such as the one presented in Figure 2. Another example demonstrates the conversion process from the RGB color space into the XYZ. With the transformation matrix values from Table 1 above, we can manually reproduce the XYZ output and compare it with the results from one of the libraries.

How to cite

Askaruly, S. (2023). Understanding ICC profiles. Tuttelikz blog: https://tuttelikz.github.io/blog/2023/12/icc/

References

[1] Harold, R. M. “An introduction to appearance analysis.” Gatfworld 13.3 (2001): 5-12.
[2] International Color Consortium. “ICC Profile Format Specification.” ICC. Vol. 1. 1997.
[3] International Color Consortium. “Introduction to the ICC profile format”, https://www.color.org/iccprofile.xalter
[4] Nielsen, Mary, and Michael Stokes. “The creation of the sRGB ICC profile.” Color and Imaging Conference. Vol. 1998. No. 1. Society for Imaging Science and Technology, 1998.
[5] Chromasoft. “ICM Porfiles”, https://sites.google.com/site/chromasoft/icmprofiles
[6] Graphic Quality Consultancy. “Introduction to Colour Models (‘Spaces’)”, https://www.colourphil.co.uk/xyz_colour_space.shtml#%3A~%3Atext%3DThe%20CIE%20XYZ%20colour%20model%20is%20a%20%27device-independent%27%2Cits%20own%20version%20of%20RGB
[7] Lindbloom, Bruce. “RGB/XYZ Matrices”, Revised 07 Apr. 2017, http://www.brucelindbloom.com/index.html?ColorCalculator.html

Appendix

A1. Writing image using following ICC profile

# "AdobeRGB.icc" can be downloaded from https://sites.google.com/site/chromasoft/icmprofiles
from PIL import Image, ImageCms

img = Image.open("autumn.jpg")
icc = ImageCms.getOpenProfile("AdobeRGB.icc")
img.save("autumn_adobergb.jpg", icc_profile=icc.tobytes())

A2. Converting RGB to XYZ: using library and manually

# Conversion formula from https://www.easyrgb.com/en/math.php
# python-colormath module: https://python-colormath.readthedocs.io/en/latest/index.html
import numpy as np
from colormath.color_objects import XYZColor, AdobeRGBColor
from colormath.color_conversions import convert_color

_gf = lambda a: a**gamma
_rf = lambda a: round(a, 4)

r, g, b, gamma = 0.1, 0.2, 0.3, 2.2
rgb_obj = AdobeRGBColor(r, g, b)

xyz = convert_color(rgb_obj, XYZColor, through_rgb_type=AdobeRGBColor, target_illuminant='d65')

# Refer to Table 1 -> AdobeRGB
M = np.array([
    [0.5767309, 0.1855540, 0.1881852],
    [0.2973769, 0.6273491, 0.0752741],
    [0.0270343, 0.0706872, 0.9911085]
])

XYZ = np.dot(M, np.array([[_gf(r)],[_gf(g)], [_gf(b)]])).squeeze()

assert _rf(xyz.xyz_x) == _rf(XYZ[0]), "x values are correctly reproduced"
assert _rf(xyz.xyz_y) == _rf(XYZ[1]), "y values are correctly reproduced"
assert _rf(xyz.xyz_z) == _rf(XYZ[2]), "z values are correctly reproduced"