Wie zeichne ich pixelgenau auf mit \includeimage eingebetteten Bildern in TikZ?

Wie zeichne ich pixelgenau auf mit \includeimage eingebetteten Bildern in TikZ?

Ich möchte auf ein Bild zeichnen, welches ich mit \includeimage eingebettet habe:

\documentclass[tikz]{standalone}
\begin{document}
  \begin{tikzpicture}
    \node[anchor=south west,inner sep=0] (image) at (0,0) {\includegraphics{example-image}};
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
      \draw[color=red] (0,0) rectangle (1,1);
    \end{scope}
  \end{tikzpicture}
\end{document}

Nehmen wir an, das Bild hat eine Größe von 800 x 600 Pixeln. Das Problem dabei ist, dass x und y in Breite und Höhe zwischen 0 und 1 skalieren. Ich möchte auf dem Bild zeichnen und dabei seine Pixel als Koordinatenreferenz verwenden, und zwar so, dass

\draw[color=red] (0,0) rectangle (1,1);

kann ersetzt werden durch

\draw[color=red] (0,0) rectangle (800,600);

Mein Problem besteht nun darin, die x- und y-Werte im Bereich zu skalieren. Ich dachte, die folgende Anweisung würde funktionieren:

\begin{scope}[x={($(image.south east)/800$)},y={($(image.north west)/600$)}]

aber es wird der folgende Fehler ausgegeben:

Package tikz Error: + or - expected.

Ich habe Kapitel 13.5 im TikZ/PGF-Handbuch nachgeschlagen, aber es scheint, als ob es auf diese Weise mit der image.direction-Anweisung nicht funktioniert.

Wie kann ich meinen Umfang richtig skalieren?

Antwort1

Bearbeiten:In der ersten Version meiner Antwort habe ich – wie @Jake in seinem Kommentar anmerkte – den Kern der Frage nicht verstanden. Hier ist also die korrigierte Lösung, inspiriert von @Jakes Antwort:

    \documentclass{article}
    \usepackage{tikz}
    \usepackage{calc}
    \usepackage{graphicx}

\begin{document}
    \begin{figure}
\centering
\sbox0{\includegraphics[width=0.5\textwidth]{example-image}}%
\begin{tikzpicture}[x=\wd0/800, y=\ht0/600]
\node[anchor=south west,inner sep=0pt] at (0,0){\usebox0};
\draw[blue] (200,100) rectangle + (500,300);
\draw[red,thick] (0,0) rectangle + (800,600);
\end{tikzpicture}
    \end{figure}
\end{document}

Der Hauptunterschied besteht darin, dass stattdessen neue Längen box0und Möglichkeiten verwendet werden, die diese bieten. Dadurch ist der obige Code etwas kürzer, führt aber zum gleichen Ergebnis:

Bildbeschreibung hier eingeben

Nachtrag:Beachten Sie, was @jfbu in seinem Kommentar sagt: „… \box0ist manchmal etwas gefährlich, insbesondere wenn Sie die Verwendung von \wd0oder verzögern \ht0. Es ist sicherer , … zu \newsavebox\myboxverwenden . Obwohl ich bisher keine schlechten Erfahrungen mit gemacht habe , ist es also besser, auf der sicheren Seite zu bleiben und LateX zu verwenden und das obige MWE wie folgt umzuschreiben:\sbox\mybox\wd\myboxbox0

\documentclass{article}
    \usepackage{tikz}
    \usepackage{calc}
    \usepackage{graphicx}

\newsavebox\mybo

% for show only a figure
\usepackage[active,floats,tightpage]{preview}
\PreviewBorder{1em}

\begin{document}   
    \begin{figure}[h]
\centering
\sbox\mybox{\includegraphics[width=0.5\textwidth]{example-image}}%
\begin{tikzpicture}[x=\wd\mybox/800, y=\ht\mybox/600]
    \node[anchor=south west,inner sep=0pt] at (0,0) {\usebox\mybox};
    \draw[blue,very thin] (200,100) rectangle + (500,300);
    \draw[red,thick] (0,0) rectangle + (800,600);
\end{tikzpicture}
    \end{figure}
\end{document}

Die Bot-Lösung hat einen wichtigen Vorteil: Das Bild wird nur einmal verarbeitet (beim Speichern in der Savebox und dann als \usebox\myboxoder gemäß dem ersten Beispiel als verwendet \usebox0. Dies reduziert möglicherweise die Kompilierungszeit (wie auch @jfbu in seinem Kommentar angibt).

Antwort2

Sie versuchen das Richtige, aber die Syntax für die Koordinatenberechnung ist etwas eingeschränkt: Sie erwartet, dass der Faktor für die Streckung des Vektors am Anfang des Ausdrucks erscheint. Sie könnten also verwenden

\begin{scope}[x={($1/800*(image.south east)$)},y={($1/600*(image.north west)$)}]

Es stellt sich jedoch heraus, dass dieser Ansatz offenbar einige Präzisionsprobleme aufweist, da das resultierende Koordinatensystem nicht genau mit dem Bild übereinstimmt.

Stattdessen möchten Sie vielleicht den Ansatz von cfr verwenden.https://tex.stackexchange.com/a/269850/2552, was bei mir problemlos funktioniert (aber mehr Tipparbeit erfordert):

\documentclass[tikz, demo]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}

\newlength\iwidth
\newlength\iheight
\settoheight\iheight{\includegraphics{example-image}}
\settowidth\iwidth{\includegraphics{example-image}}

  \begin{tikzpicture}[x=\iwidth/800, y=\iheight/600]
    \node[anchor=south west,inner sep=0] (image) at (0,0) {\includegraphics{example-image}};
      \draw[color=red] (0, 0) rectangle (800, 600);
  \end{tikzpicture}
\end{document}

verwandte Informationen