Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Recently I have learned how to draw simple stuff with TikZ. I really like it. Now I wonder if it is possible to draw with TikZ on a image. Instead of pasting a image in Illustrator and adding some vectors to point something in the picture I would like to do it using TikZ. Is it possible?

For example, on a picture of a computer (PNG,etc) I would like to draw some arrows and labels saying "Keyboard", "Monitor", etc.

share|improve this question
2  
a couple of years later: Ignasi asked me to add a link to the related answer tex.stackexchange.com/questions/38632/image-with-axis/… –  Christian Feuersänger Jan 25 at 20:04

4 Answers 4

up vote 235 down vote accepted

(The first part of this answer is taken from my answer to a similar—but not identical—question.)

You can put an \includegraphics inside a TikZ node and then draw over it. The following code adds the picture so that the lower left corner is at the origin of the TikZ coordinate system.

\begin{tikzpicture}
    \node[anchor=south west,inner sep=0] at (0,0) {\includegraphics[width=\textwidth]{some_image.jpg}};
    \draw[red,ultra thick,rounded corners] (7.5,5.3) rectangle (9.4,6.2);
\end{tikzpicture}

With a picture from Wikipedia as some_image.jpg, this yields

example

There is a slight problem with this solution: whenever you choose to scale the image differently (e.g. with width=0.9\textwidth), you have to correct the coordinates for your annotations. So it might be useful to introduce coordinates relative to the picture:

\begin{tikzpicture}
    \node[anchor=south west,inner sep=0] (image) at (0,0) {\includegraphics[width=0.9\textwidth]{some_image.jpg}};
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
        \draw[red,ultra thick,rounded corners] (0.62,0.65) rectangle (0.78,0.75);
    \end{scope}
\end{tikzpicture}

Then inside the scope, (0,0) is at the lower left of the picture and (1,1) is at the upper right and scaling the picture automatically scales the annotations (or more correctly, it scales their places; the line width and text size stays the same).

A small warning: If you want to draw circles in the new coordinate system, you have to use a radius with absolute lengths (e.g. [radius=1cm]). Otherwise the circle will become an ellipse (if the image is not square).

share|improve this answer
4  
Great answer! And a cool picture choice, too! –  Jan Hlavacek Jan 23 '11 at 21:49
1  
I didn't now that x={(image.south east)},y={(image.north west)} is possible! Thanks, I used \pgfsetxvec{\pgfpointanchor{image}{south east}}% \pgfsetyvec{\pgfpointanchor{image}{north west}}% so far in my implementation. –  Martin Scharrer Jan 24 '11 at 8:56
    
Great answer. Thanks. –  Geoff Apr 19 '11 at 19:45
2  
@Geoff: I finally got around to implement an option for this. The code is available at the tex-sx bzr repository. To use it, download the onimage.dtx file and run pdflatex on it to obtain the onimage.sty and the documentation. (Eventually the package will be available over CTAN.) –  Caramdir Jul 4 '11 at 12:01
1  
You could also define two additional commands as stated her: kogs-www.informatik.uni-hamburg.de/~meine/tikz, then the coordinates of the drawing over the image can be set in image coordinates, something I used extensively in my PhD-thesis... –  Habi Jul 10 '12 at 14:04

enter image description here

MWE using Asymptote graphic() label:

% igrid.tex
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{figure}
\begin{asy}
import graph;
import math;

defaultpen(fontsize(10pt));
real sc=2;
unitsize(sc*1bp);
real wd=200*sc;
real ht=120*sc;

// Image used from http://upload.wikimedia.org/wikipedia/commons/1/16/Mycena_interrupta.jpg
label(
  shift(wd/2,ht/2)*
  graphic("img.jpg"
  ,"width="+string(wd)+"bp"
  +",height="+string(ht)+"bp"
  +",scale="+string(sc)
  ),(0,0)
);
layer();

draw(((0,0)--(wd,ht)/sc),blue+2pt);

int ngrid=10;
int n=(int)(wd/ngrid/sc);
int m=(int)(ht/ngrid/sc);
add(scale(ngrid)*grid(n,m,yellow));

//xlimits(0,wd/sc,crop=true);
//ylimits(0,ht/sc,crop=true);
xaxis( 0,wd/sc,RightTicks(Step=ngrid));
yaxis(0,ht/sc,LeftTicks(Step=ngrid));

pair[] P={
(66,34),
(70,35),
(76,38),
(80,37),
(84,37),
(87,42),
(90,49),
(91,54),
(92,60),
(93,65),
(97,65),
(100,65),
(103,66),
(105,67),
(101,71),
(97,74),
(95,75),
(92,76),
(94,78),
(98,79),
(101,80),
(103,80),
(103,83),
(100,85),
(96,88),
(91,87),
(86,86),
(82,86),
(78,86),
(74,86),
(70,83),
(69,83),
(67,86),
(65,87),
(59,88),
(54,88),
(51,87),
(47,87),
(42,86),
(38,85),
(34,84),
(31,82),
(29,80),
(29,77),
(33,76),
(35,76),
(36,76),
(36,74),
(35,73),
(33,70),
(33,69),
(36,68),
(40,68),
(41,68),
(44,67),
(46,67),
(47,64),
(47,60),
(49,55),
(52,48),
(55,41),
(58,35),
(63,31),
};
guide g=graph(P,operator..)..cycle;
fill(g,white+opacity(0.8));
draw(g,orange+1bp);
\end{asy}
\end{figure}
\end{document}

% To process it with `latexmk`, create file `latexmkrc`:
% 
%     sub asy {return system("asy '$_[0]'");}
%     add_cus_dep("asy","eps",0,"asy");
%     add_cus_dep("asy","pdf",0,"asy");
%     add_cus_dep("asy","tex",0,"asy");
% 
% and run `latexmk -pdf igrid.tex`.
share|improve this answer
    
Very nice. Thank you! –  In PSTricks we trust Aug 24 '13 at 0:23

For PSTricks fans, the solution is also simple. Unlike Caramdir's and Jake's solutions which use decimal numbers for normalization, I use integer instead. I believe that using integer is better. :-)

There are three steps as follows:

  1. Specify the number of columns and rows. Higher values ease you to determine positions more accurately. Unless you are happy to redo the third step, avoid changing these values after completing the third step.
  2. Specify the scale. Scaling does not affect what you have done in the third step.
  3. Superimposing is done here. To enable the grid, change showgrid from false to top. The grid will be useful to determine positions.
\documentclass[pstricks,border=12pt]{standalone}

\def\M{4}% columns
\def\N{4}% rows
\def\scale{0.25}% scale
\def\filename{mycena_interrupta}% filename


\usepackage{graphicx}
\newsavebox\IBox
\savebox\IBox{\includegraphics[scale=\scale]{\filename}}

\addtopsstyle{gridstyle}
{
    gridcolor=yellow,
    subgridcolor=gray,
    subgriddiv=10,
    griddots=0,
    subgriddots=5,
    gridwidth=0.4pt,
    subgridwidth=0.2pt,
}

\psset
{
   xunit=0.5\dimexpr\wd\IBox/\M,
   yunit=0.5\dimexpr\ht\IBox/\N,
}

\begin{document}
\begin{pspicture}[showgrid=top](-\M,-\N)(\M,\N)
    \rput(0,0){\usebox\IBox}
    \psframe[linecolor=red,linewidth=2pt,dimen=inner,framearc=0.5](0.9,1.2)(2.2,2)
\end{pspicture}
\end{document}

When showgrid=top:

enter image description here

The final result with showgrid=false:

enter image description here

share|improve this answer
7  
Thank you for up voting. Honestly, I want to have an experience of getting more than 99 votes in my life. –  In PSTricks we trust Dec 21 '12 at 15:18
    
I have already experienced it. –  In PSTricks we trust Mar 2 at 5:15
up vote 214 down vote
+100

This is meant to be an addition to Caramdir's answer, but I cannot figure out how to insert line breaks into comments:

To make it easier to find the desired points in the new coordinate system, you can draw a labeled grid on top of the image while you're working on it:

\draw[help lines,xstep=.1,ystep=.1] (0,0) grid (1,1);
\foreach \x in {0,1,...,9} { \node [anchor=north] at (\x/10,0) {0.\x}; }
\foreach \y in {0,1,...,9} { \node [anchor=east] at (0,\y/10) {0.\y}; }

image with grid

share|improve this answer
7  
Very useful addition! –  Caramdir Jan 23 '11 at 18:14
12  
Superb! Brilliant! –  Shashank Sawant May 27 '12 at 8:43
7  
By the way you can insert line beaks in the comments by using Shift+Enter. But I'm glad this isn't a comment so that I can upvote. –  leo Jul 5 '12 at 20:29

protected by percusse Aug 20 '12 at 12:13

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.