Tikz: Can I interpolate an image using texture coordinates?

In computer graphics it is common to map parts of an image to a triangle. For example see this image from Wikipedia Now, I have an image and want to assign parts of it to several triangles like in the center image above, such that it is continuous but distorted according to the triangles. I would prefer a solution where i can assign arbitrary [0,1]² coordinates of the image to a tikz path (triangle) so that the image gets interpolated and stretched according to this coordinates.

What I can imagine so far:

• I can clip the image at the triangle with \clip

• The xslant/yslant options seem to allow shearing the image like in this answer

However, bringing both together makes a very hard time of getting the correct stretch factors and getting continuity. Note, that I want to have the effect from the 'Affine' image for multiple triangles.

• You need to use nonlinear transformations not slants. scales and slants are affine transformations. Jan 29 '18 at 9:19
• @percusse Or affine transformations per triangle (using scope or similar). But then having a possibility for setting texture coordinates is still necessary. Jan 29 '18 at 12:58
• What have you got so far, code-wise? What are texture coordinates?
– cfr
Jan 29 '18 at 23:21
• @cfr A texture coordinate is a relative image coordinate. I.e. (0,0), (0,1), (1,0) and (1,1) are the corners of the image. I want to say "map texcoord X of the image to a point of my path". Interpolation and distortion should happen automatically. Here, a path is a triangle, but higher order polygons would also be interesting. Jan 30 '18 at 9:40
• shameless self-promotion Jan 30 '18 at 23:49

Inspired by the linked answer to "Draw Text in different shapes" I found a solution. It computes the affine mapping for a texture to a single triangle and does clipping and drawing in the unit texture space. Unfortunately, the solution is not robust due to limited computation precision and range. Depending on the triangles one gets errors or just vanishing triangles.

\documentclass{article}
\usepackage{tikz}

% Get X and Y of a coordinate as separated variables.
% Modified solution from: https://tex.stackexchange.com/a/58590/103072
\makeatletter
\newcommand{\gettikzxy}{%
\path #1;%
\edef#2{ \strip@pt\pgf@x }%
\edef#3{ \strip@pt\pgf@y }%
}
\makeatother

% Command to draw one textured triangle
% #1-#3 are coordinates of the triangle
% #4-#6 are texture coordinates in [0,1]^2 of the image
%       where (0,0) is bottom left
% #7 is the name of the image
\newcommand\texturedtriangle{%
% Decode all the coordinates into nice single numbers
\gettikzxy{#1}{\ax}{\ay}
\gettikzxy{#2}{\bx}{\by}
\gettikzxy{#3}{\cx}{\cy}
\gettikzxy{#4}{\tax}{\tay}
\gettikzxy{#5}{\tbx}{\tby}
\gettikzxy{#6}{\tcx}{\tcy}
\gettikzxy{(1,1)}{\ux}{\uy}
% Compute the required affine transformation
\pgfmathsetmacro\det{\tax*(\tcy-\tby) + \tay*(\tbx-\tcx) - \tbx*\tcy + \tby*\tcx}
\pgfmathsetmacro\aa{(\ax*(\tcy-\tby) + \tay*(\bx-\cx) - \bx*\tcy + \tby*\cx)/\det}
\pgfmathsetmacro\ba{(\ax*(\tbx-\tcx) + \tax*(\cx-\bx) - \tbx*\cx + \bx*\tcx)/\det}
\pgfmathsetmacro\ab{(\ay*(\tcy-\tby) + \tay*(\by-\cy) - \by*\tcy + \tby*\cy)/\det}
\pgfmathsetmacro\bb{(\ay*(\tbx-\tcx) + \tax*(\cy-\by) - \tbx*\cy + \by*\tcx)/\det}
\pgfmathsetmacro\tx{\ax - (\tax*\aa + \tay*\ba)}
\pgfmathsetmacro\ty{\ay - (\tax*\ab + \tay*\bb)}
\pgflowlevelobj{
\pgfsettransformentries{\aa}{\ab}{\ba}{\bb}{\tx pt}{\ty pt}
}{
% We are inside the texture space here...
\clip #4 -- #5 -- #6 -- cycle;
% Draw a unit sized image (from (0,0) to (1,1) if no scale)
\node at (0.5,0.5) {\includegraphics[width=\ux pt, height=\uy pt]{#7}};
}
}

\begin{document}

\begin{tikzpicture}[scale=2]
\texturedtriangle{(0,0)}{(2,0)}{(0.5,2)} {(0,0)}{(1,0)}{(0,1)} {dragon}
\texturedtriangle{(2.5,1.5)}{(2,0)}{(0.5,2)} {(1,1)}{(1,0)}{(0,1)} {dragon}
\texturedtriangle{(2.5,1.5)}{(1,3)}{(0.5,2)} {(1,1)}{(1,0)}{(0,1)} {dragon}
\texturedtriangle{(-0.5,2)}{(1,3)}{(0.5,2)} {(1,1)}{(1,0)}{(0,1)} {dragon}
\draw (0,0) -- (2,0) -- (0.5,2) -- cycle;
\draw (2.5,1.5) -- (2,0) -- (0.5,2) -- cycle;
\draw (2.5,1.5) -- (1,3) -- (0.5,2) -- cycle;
\draw (-0.5,2) -- (1,3) -- (0.5,2) -- cycle;
\end{tikzpicture}

\end{document}

The output of the code looks like 