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.