6

I want to magnify part of a picture with the TikZ spy library; however, with a scope for using relative coordinates like in #9561 Drawing on an image with TikZ. Provided I'm using the image tux.png - consider this MWE:

\documentclass[%
  12pt,
  journal,
  onecolumn,
  twoside,
  draftcls,
  letterpaper,
]{IEEEtran}

% wget http://i.stack.imgur.com/aVGcn.png -O tux.png

\usepackage[nopar]{lipsum}
\usepackage{xstring}
% https://tex.stackexchange.com/a/26808/2595
\makeatletter
\def\unpacklipsum#1#2#3{%
  \count@=#1\relax
  \advance\count@\m@ne
  \def#3{}%
  \loop\ifnum\count@<#2\relax
    \advance\count@\@ne
    \edef#3{#3\csname lipsum@\romannumeral\count@\endcsname}%
  \repeat}
\makeatother
% https://tex.stackexchange.com/a/168754/2595
\def\loremnchars[#1]#2{%
  \unpacklipsum{#1}{#1}{\myunpacked}%
  \StrMid{\myunpacked}{1}{#2}% same as \StrLeft{\myunpacked}{#2}
}


\usepackage{caption}
\usepackage{tikz}
\usetikzlibrary{shapes}
\usetikzlibrary{spy}

\begin{document}

\begin{center}
  \begin{tikzpicture}[
    spy using outlines={%
      draw=red,
      ellipse,
      red,
      magnification=2,
      connect spies
    }
  ]
    \node [draw=black, anchor=south west, inner sep=0pt] (myimg) at (0,0) {
      \includegraphics[width=0.9\textwidth]{tux.png}
    };
    \begin{scope}[
      x={(myimg.south east)},y={(myimg.north west)},
      spy using outlines={%
        draw=red,
        ellipse,
        red,
        magnification=2,
        connect spies
      }
    ]
      \draw[help lines,xstep=.1,ystep=.1] (0,0) grid (1,1);
      \node[
        draw=red,ellipse,line width=1pt,minimum width=0.9cm,minimum height=5.25cm
      ]
      at (0.53,0.7) {};
      \spy[
        draw=red,ellipse,line width=1pt,minimum width=0.9cm,minimum height=5.25cm
      ]
      on (0.53,0.7) in node [left] at (0.8,0.825);
    \end{scope}
  \end{tikzpicture}
  \captionof{figure}[justmy]{Just my image; \loremnchars[5]{255} ...}
  \label{fig:test}
\end{center}

\end{document}

It produces this image:

test71.png

The first \node ... at (0.53,0.7) is merely to indicate the area that I want to be spied on. Two problems are visible:

  • The same settings as used for that \node, when applied to a \spy, result with an ellipse smaller than the originally requested one
  • Apparently, since a scope is used, the \spy doesn't "see" any graphics (more precisely, image pixels) "below", so it seemingly only zooms in the grid.

Can I use this kind of a setup of \includegraphics and scope inside a tikzpicture, but still obtain a proper \spy, expressed in relative coordinates - and if yes, how?

3

Ok, think I got something for now - hopefully someone will post a more correct answer eventually, though. Anyways, with the code below, I now get this:

test72.png

Caveats:

  • While \node can (and does) adjust itself to the relative coordinates as per the scope, \spy apparently cannot (and doesn't)
    • However, \spy can refer to nodes, so we can set named \node and/or \coordinate (in respect to the scope relative coordinates), and feed them as inputs to \spy just fine
  • Apparently, the size options entered for \spy are for the final, the "in node" display - not for the "peeker" on (node); so do modify the size of the "peeker", we have to multiply the size options by the magnification
  • Only include spy using outlines on the element/"layer" that is being spied (i.e. if it is added to the scope, then the pixels of the image will be unavailable; it should only be added to the tikzpicture, because it is the one "hosting" the \includegraphics and its pixels).

With that in mind, below is the modified portion of the MWE in OP that makes it work (only the document part without preamble, as changes are made only there). Note that \magnif is where the magnification is now stored; and since \spy seems to choke on expandability of lengths, lengths are \def'd instead (and \global\def'd at that, otherwise \spy cannot see them); and finally, with all this, now I have no idea what controls the line width of the "peeker" anymore (but I can control the line width of the indicator node, which works just as well). Anyways, here's the code:

\begin{document}

\global\def\magnif{2}

\begin{center}
  \begin{tikzpicture}[
    spy using outlines={%
      draw=blue,
      ellipse,
      red,
      magnification=\magnif,
      line width=2pt,
      connect spies
    }
  ]
    \node [draw=black, anchor=south west, inner sep=0pt] (myimg) at (0,0) {
      \includegraphics[width=0.9\textwidth]{tux.png}
    };
    \begin{scope}[
      x={(myimg.south east)},y={(myimg.north west)},
      % enabling spy using outlines here makes the pixels unreadable; so skip it:
    ]
      \draw[help lines,xstep=.1,ystep=.1] (0,0) grid (1,1);
      % must have \global for \spy!
      % lengths may not be expandable: http://tex.stackexchange.com/a/18302/2595
      % better use \edef here, in case you need {0.5\somelength}, else \spy will not pick it up
      \global\edef\mw{0.9cm} %\newlength{\mw}\setlength{\mw}{0.9cm}
      \global\edef\mh{5.25cm} %\newlength{\mh}\setlength{\mh}{5.25cm}
      \node[
        draw=red,ellipse,line width=1pt,minimum width=\mw,minimum height=\mh,
      ]
      (lookhere) at (0.53,0.7) {};
      \coordinate (lookherenext) at (0.8,0.825);
      % line width here has no effect;
      % also, coordinates for \spy are not scaled!
      \spy[
        draw=green,ellipse,line width=4pt,minimum width=\magnif*\mw,minimum height=\magnif*\mh,
      ]
      %on (0.53,0.7) in node [left] at (0.8,0.825);
      on (lookhere) in node [left] at (lookherenext);
    \end{scope}
  \end{tikzpicture}
  \captionof{figure}[justmy]{Just my image; \loremnchars[5]{255} ...}
  \label{fig:test}
\end{center}

\end{document}
  • THanks, I ran into the same problem, when using a similar idea in beamer and there - your solution also applies. – Ronny May 9 '14 at 9:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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