26

I need to plot some data in a file (10000 records of 2 points each one) but PGFPlots is very very slow rendering it. So I'm trying to use MatLab to plot the data, capture the image without axis and in a tikzpicture render the image with axis.

Here is my test with an 96 x 96 PNG image:

enter image description here

\documentclass{article}

\usepackage{pgfplots}

\begin{document}
  \pgfdeclareimage[width=5cm]{fondo}{avatarMSM.png}
  \begin{tikzpicture}
    \draw node[anchor=south west] (nodoFondo) at (axis cs:0,0) {\pgfuseimage{fondo}};
    \begin{axis}[
        width=5cm,
        scale only axis,
        enlargelimits=false,
        xmin=0,
        xmax=96,
        ymin=0,
        ymax=96,
        axis equal=true
        ]

      \addplot[thick,blue] (0,0) -- (axis cs:96,96);
    \end{axis}
  \end{tikzpicture}
\end{document}

enter image description here

The result has white margins around the image and I can't fit the axis.

4 Answers 4

37

Since you are using pgfplots to generate the axis, you can use its built-in method \addplot graphics to align the axis on top of the graphics.

What you need is to define the lower-left and the upper-right corner of the axis -- if your image has a tight bounding box, that's all. If it does not have a tight bounding box, you may want to consult the pgfplots manual section "Using External Graphics as Plot Sources" for more information.

The result looks like this:

\documentclass{article}

\usepackage{pgfplots}

\begin{document}
  \begin{tikzpicture}
    \begin{axis}[
        axis on top,% ----
        width=5cm,
        scale only axis,
        enlargelimits=false,
        xmin=0,
        xmax=96,
        ymin=0,
        ymax=96,
        axis equal=true
        ]

      \addplot[thick,blue] graphics[xmin=0,ymin=0,xmax=96,ymax=96] {Dad64.png};
    \end{axis}
  \end{tikzpicture}
\end{document}

enter image description here

With this setup, you can rescale the axis -- and the \addplot graphics command will automatically rescale the graphics to fit between the designated coordinates.

The feature also supports 3d graphics + 3d axes (with much more input from your side, however).


To make the axis automatically resize to fit the picture while respecting the aspect ratio of the image, you should set axis equal image. Specifying a width or height for the axis will scale the axis and image. In addition to drawing an axis, you can also use this setup to place other TikZ nodes and paths using the image coordinate system. Coordinates specified using (axis cs:<x>,<y>) refer to the image coordinate system:

\documentclass{article}
\usepackage{pgfplots}


\begin{document}
\begin{tikzpicture}
\begin{axis}[enlargelimits=false, axis on top, axis equal image]
\addplot graphics [xmin=0,xmax=96,ymin=0,ymax=96] {Dad64};
\node at (axis cs:49,30) [
    circle,
    draw,
    red,
    thick,
    minimum size=3ex,
    pin={[pin edge=thick]-10:Nose}
] {};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[enlargelimits=false, axis on top, axis equal image, width=6cm]
\addplot graphics [xmin=0,xmax=96,ymin=0,ymax=96] {Dad64};
\end{axis}
\end{tikzpicture}
\end{document}
3
  • Great, but there are white margins on both sides. I need an axis fitted to the image. Commented Dec 17, 2011 at 21:33
  • Christian, may be you can consider including some reference to this answer in Drawing on an image with TiKZ.
    – Ignasi
    Commented Jan 23, 2014 at 7:27
  • Can someone tell me how on this put a \node or a label like "Nose" but over the top line in x dimension?
    – Katharina
    Commented Jan 10, 2020 at 12:13
9

See section 4.2.8 Using External Graphics as Plot Source in the PGFplots manual.

\documentclass{article}
\usepackage{pgfplots}
\begin{document}
  \begin{tikzpicture}
    \begin{axis}[
        width=5cm,
        scale only axis,
        enlargelimits=false,
        axis on top]
      \addplot graphics[xmin=0,xmax=96,ymin=0,ymax=96] {Dad64};
    \end{axis}
  \end{tikzpicture}
\end{document}

enter image description here

This does have the problem of the image not having the correct aspect ratio (see comments). A not optimal workaround is to specify the height of the plot as well, i.e., add height=<length> as an option to the axis. For a quadratic image as this it's easy enough, but it as a little more inconvenient for non-quadratic images, as one have to calculate the height based on the image dimensions.

4
  • Thanks, but the aspect ratio is changed without axis equal=true. Commented Dec 17, 2011 at 21:31
  • A (bad) workaround is to specify the height of the plot as well. Bad, as you would have to, for non quadratic images, calculate the height based on the image dimensions. Commented Dec 17, 2011 at 21:48
  • 1
    @FernandoNadal I confess I'm a little confused. Why post that comment on my answer, and accept Christian's answer? Not that it matters, it just seemed a little weird ... Commented Dec 17, 2011 at 22:25
  • Concerning the aspect ratio: it is correct that pgfplots rescales the image. An alternative would be to specify the unit vector ratio option - this might lead to better results than changing the height. But I see only two exclusive choices: either white-space or choosing a suitable width/height. And yes: pgfplots does not tell you the image's aspect ratio. Commented Dec 18, 2011 at 15:41
4

Another method is following. This demo also shows how to customize axis and styles as well.

  • Create empty axis using pgfplots
  • Insert image with \node using rel axis cs.

Below is working code. You can get the working example from this folder.

\documentclass[crop]{standalone}
%\usepackage[a4paper,landscape]{geometry}
\usepackage{tikz}
\usepackage{pgfplots}
\usepgfplotslibrary{polar}
\usetikzlibrary{positioning}
\begin{document}

\begin{tabular}{c c}
    Bear & Polar Bear \\
\begin{tikzpicture}[ ]
\begin{axis}[
        grid = both
        , minor tick num=5
        , grid style={draw=gray!10,line width=.1pt}
        , major grid style={line width=0.5pt,draw=gray!50}
        , axis line style={latex-latex}
        , xticklabels = \empty
        , yticklabels = \empty
        , draw=blue!20
    ]

        \addplot[draw=none] coordinates {(2,2)};
        \node[] (image) at (rel axis cs:0.5,0.5) {\includegraphics[width=5cm]{./bear.png}};
    \end{axis}
\end{tikzpicture} &
\begin{tikzpicture}[]
    ]
    \begin{polaraxis}[
        grid = both
        , minor tick num=5
        , grid style={draw=gray!10,line width=.1pt}
        , major grid style={line width=0.5pt,draw=gray!50}
        , axis line style={latex-latex}
        , xticklabels = \empty
        , yticklabels = \empty
        , draw=blue!20
    ]
        \addplot[draw=none] coordinates {(1,1)};
        \node[] at (rel axis cs:0,0) {\includegraphics[width=5cm]{./bear.png}};
    \end{polaraxis}
\end{tikzpicture}%
\end{tabular}

\end{document}

Final product is below (for demo)

enter image description here

2

For the sake of completeness with PSTricks.

\documentclass[pstricks,border=24pt,12pt]{standalone}
\usepackage{pst-plot}
\usepackage{graphicx}

\newsavebox\IBox
\savebox\IBox{\includegraphics[scale=1]{example-image-a}}

\def\Rows{5}
\def\Columns{5}

\psset
{
    xunit=\dimexpr\wd\IBox/\Columns,
    yunit=\dimexpr\ht\IBox/\Rows,
}

\begin{document}
\begin{pspicture}(\Columns,\Rows)
    \rput[bl](0,0){\usebox\IBox}
    \psaxes[axesstyle=frame,tickstyle=inner,ticksize=0 5pt](\Columns,\Rows)
    \psellipse[linecolor=red,linestyle=dashed,linewidth=5pt](2.5,2.5)(2,2)
\end{pspicture}
\end{document}

enter image description here

You must log in to answer this question.

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