Can \includegraphics be used to change an image color?

(Importantly, this does not work with XeTeX. I mostly tested using pdfTeX, but things also seem to work in LuaTeX.)

In a pdf file, colors of an included image can be affected by a /Decode array. This is accessed via the decodearray keyword of \includegraphics.

However: this fails in some cases when the color model is cmyk; and this does not allow to change the color space from whatever color space the image has. My impression is that changing the color space from within pdfTeX (i.e. turn grayscale to rgb, or rgb to cmyk, etc.) is impossible.

Grayscale is the easiest. Say we want to reduce contrast and make the image overall darker. We'll map black (0) to some dark gray (0.2) and white (1) to some lighter gray (0.5). This is done using decodearray={0.2 0.5} (braces can be omitted).

\documentclass{article}
\usepackage{graphicx}
\begin{document}
\includegraphics{example-image.jpg}

\includegraphics[decodearray={0.2 0.5}]{example-image.jpg}
\end{document}

For an rgb example we can use hacker.jpg from the ConTeXt examples. For a cmyk example, create a copy of example-image.jpg with this color space; I used the convert command-line tool from imagemagick:

convert `kpsewhich example-image.jpg` -colorspace cmyk /tmp/example-image-cmyk.jpg

letting kpsewhich do the job of finding where example-image.jpg is. Then, try

\documentclass{article}
\usepackage{graphicx}
\begin{document}
\includegraphics{hacker.jpg}

\includegraphics[decodearray={0.2 0.3 1 0 1 0.8}]{hacker.jpg}

\includegraphics{example-image-cmyk.jpg}

\includegraphics[decodearray={0.2 0.2 1 0 1 0.8 1 0}]{example-image-cmyk.jpg}
\end{document}

Note that for the rgb color profile the /Decode array contains 6 numbers, and for cmyk, 8 numbers. Each pair of numbers describes the linear transformation to operate on the corresponding channel. The first array thus imposes the amount of red, inverts the amount of green light, and puts lots of blue.

The second array should fix the amount of cyan, inverts magenta, puts lots of yellow, and inverts the amount of black ink. It doesn't. Why? Looking at the pdf file, I note that there are two /Decode entries in the same dictionary, one of the form /Decode[0.2 0.2 1 0 1 0.8 1 0] and one of the form /Decode [1 0 1 0 1 0 1 0]. The second entry takes precedence, at least on viewers I tried (perhaps this is mandated by the standard), and it inverts all channels (see below for why). If we edit the pdf file to replace the second /Decode [...] by any other key of the same length (being lazy, I do /Decode/xxxxxx), our /Decode array takes effect, and the result is as wanted.

Why is the second /Decode array there? Well, there appear to exist two types of cmyk, with slightly different conventions on whether white should be all zeros or all ones, and pdfTeX is clever enough to detect things and insert the appropriate /Decode array: without it, (some?) jpg images in the cmyk color space would be displayed and printed with inverted colors.

Anyhow, I'm going to ask a question about how to avoid this second /Decode array, since editing the pdf file is not pretty.

NB: In general, it is better practice not to include the file extension in the argument of \includegraphics, but since there is a need here to know color spaces precisely, so I don't want to worry about getting a png instead of jpg, or whatever.


No, \includegraphics can't change the image color. You need to use an external image editor. The graphics/graphicx packages are more or less just interfaces which pass the image to the output driver, like dvips or pdftex. Therefore you are limited to the features provided by these drivers. Image manipulation is not part of these drivers and even if it would be very difficult to have an identical interface for these in graphics/graphicx.

For anything except resizing, trimming/clipping and rotating you need to use an external image editor. However, using PGF/TikZ you can place some overlays before and behind the image. If the image has transparent parts you could add a background color etc.


Interestingly, for the vector graphics that I've tried it on, \color command actually changes all the black into whatever color was given.