27

I have a graphic in PDF format (originally converted from an SVG) that is monochromatic (black on white). Is it possible using TikZ or PSTricks but not (Illustrator or Inkscape) to include this image in a different color?

Example:

enter image description here

While it lasts (there seems to be no long term way to host a pdf), you can download the above image as a PDF.

Edit: Simple was perhaps a bit of a misnomer - the pdfs are cropped and monochromatic, but to intricate to redraw on my own. The above example is a character from a font (which I can recolor), but it gives a good example of what shapes I am talking about.

3
  • Related: Switching color and grayscale mode for \includegraphics
    – Werner
    Sep 25, 2012 at 17:37
  • Well if you are willing to determine the coordinates you could use tikz to draw over the image, or fill regions in color. Depending on how simple these images are, it might be better to just redo them in TikZ. So, without seeing what the figures look like it is difficult to recommend an appropriate solution. You mention that there are thousands of these, if they have a specific repeating pattern of where you would like to add the color than using tikz would work well. Sep 25, 2012 at 18:48
  • @PeterGrill I've added an example with the pdf from an external host.
    – Hooked
    Sep 25, 2012 at 19:58

2 Answers 2

38

PDF without color operators

If you are lucky and the PDF image does not contain any color operators and you are using pdfTeX/LuaTeX, then a simple \textcolor works:

\textcolor{red}{\includegraphics{myimage.pdf}}

PDF with color operators

The color operators can be indentified and removed from the PDF file. Usually the page contents streams are compressed. pdftk can uncompress them:

pdftk myimage.pdf output temp.pdf uncompress

Then you need to find the page object. Look for /Page (not /Pages), e.g.:

4 0 obj <<
/Type /Page
/Contents 5 0 R
/Resources 3 0 R
/MediaBox [0 0 595.276 841.89]
/Parent 7 0 R
>> endobj

Then the number after /Contents is the object number for the page contents stream. In this case the number is 5 and we search for 5 0 obj:

5 0 obj <<
/Length 254       
>>
stream
0 g 0 G
1 0 0 1 14.944 500.863 cm
q
10 0 0 10 0 0 cm
...
endstream

Now we have 254 bytes between stream and endstream to scan for color operators. The operators follows the operands (postfix notation). The main color operators (<n> is a number between 0 and 1):

  • <n> G, <n> g for gray color model
  • <n> <n> <n> RG, <n> <n> <n> rg for RGB color model
  • <n> <n> <n> <n> K, <n> <n> <n> <n> k for CMYK color model
  • others are CS, cs, SC, sc, SCN, scn with parameters each.

In the case of the monochrome black image, I would expect 0 g and 0 G near the beginning of the stream. The above example contains the two operations: 0 g 0 G.

If the PDF file is edited great care is needed the size of the object is not changed. First the length of the stream is given in the /Length entry. And the file offsets of the objects are written in the xref table of the PDF file. Therefore the color operations are deleted by overwriting. Also the editor should not do its own editing by changing line end characters, for example.

If the color operations are on a line by its own, then it is enough to replace the first character with the percent char, that is also a comment char in PostScript and PDF, in the example above:

% g 0 G

Or overwrite the entry by spaces (     , ordinary spaces with character code 32).

The the file is recompressed:

pdftk temp.pdf output myimage-colorless.pdf compress

And the trick with pdfTeX will work:

\textcolor{red}{\includegraphics{myimage-colorless.pdf}}

Low level editing of color operations via PostScript

If it is difficult to edit the PDF file directly (compressed, size requirements, editor requirement, adding colors, …), then the PDF can be converted to PostScript. My first choice is pdftops from xpdf:

pdftops -eps myimage.pdf myimage.eps

It uses the same operator names as in the PDF file. In case of pdftops the page starts after %%EndSetup (with pdfStartPage). PostScript is a programming language, in general it can be difficult to locate the color operators: setgray, setrgbcolor, setcmykcolor. In case of pdftops, new operators are defined with the same names as the PDF operators. Thus the same can be done as described in the previous section. However, the size of the file can easily change, also the line endings are less critical and new color operations can be inserted.

Then the file is reconverted to PDF, e.g.:

ps2pdf myimage.eps myimage-changedcolors.pdf

This way can also be used, if later a different driver than pdfTeX/LuaTeX is used that always ensure the black is the default color. Then the color is changed in the PostScript file.

2
  • 1
    Very illustrative answer! Sep 25, 2012 at 20:26
  • Since I don't want to manually edit PDF sources every time, I asked over on graphicdesign.SE on how to get a "colorless" PDF out of inkscape.
    – Raphael
    Sep 5, 2017 at 13:51
33

Edit: a simpler (and may be better) version to explain the details.

The fadings TikZ library allows to use a picture as a mask. Here, your picture is the mask (the fading).

Given any point of the fading, the transparency of this point is determined by the luminosity of the fading picture at the same position. The luminosity of a point determines “how bright” the point is. The brighter the point in the fading picture, the more opaque is the point in the fading. In particular, a white point of the fading picture is completely opaque in the fading and a black point of the fading picture is completely transparent in the fading. (pgfmanual - section "Fadings")

In the following example, there are three steps:

  1. Create the fading (with name border41).
  2. Fill a region in red.
  3. Fill the same region with yellow but using border41 fading as mask.

The result:

enter image description here

The red line at bottom is an artifact of anti-aliasing. See TikZ borders showing through when they shouldn't (overlapping circles)

The code (with comments):

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fadings}

% use border_41.pdf to make a fading (a mask)
\begin{tikzfadingfrompicture}[name=border41,inner sep=0]
  \node [fill=transparent!0]
  {\includegraphics[width=43mm,height=32.8mm]{border_41}};
\end{tikzfadingfrompicture}

\begin{document}
\begin{tikzpicture}[inner sep=0]
  % fill a region with red
  \node[fill=red,minimum width=43mm,minimum height=32.8mm](a){};
  % fill the same region with yellow but using a fading as mask
  \path[scope fading=border41,fit fading=false];
  \node[fill=yellow,minimum width=43mm,minimum height=32.8mm]{};
\end{tikzpicture}
\end{document}

First answer: Here is a solution using tikzfadingfrompicture:

enter image description here

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fadings}

\begin{tikzfadingfrompicture}[name=tikz]
  \node [fill=transparent!0,draw=none]
  {\includegraphics[width=43mm,height=32.8mm]{border_41}};
\end{tikzfadingfrompicture}

\begin{document}
\begin{tikzpicture}
  \node[left color=red,right color=yellow,minimum width=43mm,minimum height=32.8mm]{};
  \path[scope fading=tikz,fit fading=false];
  \node[fill=gray,minimum width=43mm+1mm,minimum height=32.8mm+1mm]{};
\end{tikzpicture}
\end{document}
1
  • Very nice! Does this require the fadings tikz library? If not, is there a more minimal working example (MMWE?) that simply changes (for ex.) from black to red? I really like this example, I just want to make sure I understand how TikZ knows where the shape begins and ends. Is it in the scope fading?
    – Hooked
    Sep 25, 2012 at 20:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .