# Positioning a tikz callout box relative to image

I want to annotate an image using tikz callout boxes, but the final size of each image is unknown. Therefore, I would like to be able to adjust the image size and have the tikz callout box still ‘point’ to the correct place.

This MWE explains my problem.

\documentclass[a4paper,10pt]{scrreprt}
\usepackage{tikz}
\usetikzlibrary{calc,shapes.callouts}

\begin{document}
{\huge a}
\newline
\begin{tikzpicture}
\node[] at (3.4,-2.) {\includegraphics[]{example-image}};
\node[draw, fill=red!20,ellipse callout] {Example text};
\end{tikzpicture}

{\huge b}
\newline
\begin{tikzpicture}
\node[] at (3.4,-2.) {\includegraphics[width=5cm]{example-image}};
\node[draw, fill=red!20,ellipse callout] {Example text};
\end{tikzpicture}
\end{document}


In a, the callout box points to the desired position (the top of the I).

In b, I have resized the image but the callout box stays relative to its original positions.

• – Rmano Oct 7 '16 at 11:37

Here a transformation to a (named) node containing the image is used to scale the coordinate system used by the coordinate for the callout which is specified as a fraction of the node width and height.

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{calc,shapes.callouts}
\tikzset{scale to node/.style={shift=(#1.south west),
x=($(#1.east)-(#1.west)$), y=($(#1.north)-(#1.south)$)}}
\begin{document}
\begin{tikzpicture}
\foreach \i [count=\j, evaluate={\w=12/\j;}] in {red, green, blue}{
\node (img\j) at (0, -\j*5) {\includegraphics[width=\w cm]{example-image}};
\node [draw, fill=\i!20, ellipse callout, anchor=pointer]
at ([scale to node=img\j]0.30, 0.61) {Example 1};
\node [draw, fill=\i!20, ellipse callout,
callout absolute pointer={([scale to node=img\j]0.30, 0.45)}]
at (img\j.south west) {Example 2};
}
\end{tikzpicture}
\end{document}


• Awesome thanks a lot! I was wondering one more thing, which was almost answered buy your post too. Is there a way to specify where the callout text goes relative to its point? I can see the default one, and ones that snap it to an extreme end of the image depending where you have set (e.g. south west, north). But could I say have the point at the top of the I, and the callout box over the 'e' for instance? Thanks. – Steve Hatcher Oct 10 '16 at 0:05
• @SteveHatcher The [scale to node...] syntax can be used in the at coordinate, for example, \node [...] at ([scale to node=img\j]0.65, 0.55) {text}; – Mark Wibrow Oct 13 '16 at 12:35
• For this solution you need the pgfplots package.
• You can place your image inside an axis environment, using \addplot graphics[xmin=0, xmax=100, ymin=0, ymax=80] {example-image};. Change the xmax, ymax according to the size of your image.
• You can set the pointer of the callout box to an absolute position in the graph using: callout absolute pointer={(axis cs:29,50)}.
• Because you place it in a graph you can easily define the positions of the callout box and the pointer.
• Finally hide the axis using hide axis.

## MWE

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.14}
\usetikzlibrary{calc,shapes.callouts}
\pgfplotsset{
clip=false,
hide axis,
enlargelimits=false,}
\tikzset{
note/.style={ellipse callout,
fill=red!20, draw,
callout absolute pointer={(axis cs:29,50)}}
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[width=7 cm, name=large]
\addplot graphics[xmin=0, xmax=100, ymin=0, ymax=80] {example-image};
\node[note] at (axis cs: 20, 70) {Example text};
\end{axis}

\begin{axis}[width=5 cm, anchor=north west, at={(large.south west)}, yshift=-0.7cm]
\addplot graphics[xmin=0, xmax=100, ymin=0, ymax=80] {example-image};
\node[note] at (axis cs: 20, 70) {Example text};
\end{axis}
\end{tikzpicture}
\end{document}

• Thanks, that is a clever way of using pgfplots to do this. – Steve Hatcher Oct 10 '16 at 0:01