Open ruuda opened 9 years ago
Just to add: on page 128 the PDF uses a shading pattern with PatternType
and TilingType
1.
I think this issue was fixed by #6292 (after bisecting).
I think this issue was fixed by #6292 (after bisecting).
Most of it, yes, but there're still remaining issues. See e.g. page 401, and compare with e.g. Adobe Reader.
I have been working on shadings recently, and I stumbled over this item.
I believe there is just one item left, and it is a common issue for all involved shading types.
Some background: I wrote an (almost) exhaustive test pdf and checked my expectations within the firefox version of pdf.js shipped with ubuntu 14.04 . I also checked out the git version of pdf.js, but I haven't been able to actually use it. However, I browsed the source code and the offending issue is still in the most recent state (checked out today).
The problem appears to be that interpolation is always carried out in terms of the target color space. This violates the standard's requirements, however: if there is a function, interpolation must be carried out in the function's parameter space, and the result is to be mapped through the function.
The bug appears to be in display/pattern_helper.js and in pattern.js : pattern.js already evaluates this.context.colorFn in readComponents and pattern_helper.js merely interpoaltes the final colors (in drawTriangle, for example).
Attached is my test pdf which clearly shows the wrong interpolation.
Note that it also shows that pdf.js comes with very high quality with regards to the triangle interpolation, and it is very fast. That is an excellent job in the shader -- and I have seen a couple of other free viewers.
The file P.pdf was generated from the following source that I would like to archive for future reference (but it is forbidden to upload .tex files for some reason):
\pdfcompresslevel=0 \documentclass[a4paper]{article}
\usepackage[top=1cm,left=1cm]{geometry} \usepackage{pgfplots} \pgfplotsset{compat=1.13} \usepgfplotslibrary{patchplots}
\begin{document}
\parskip=1cm \parindent=0pt
\begin{tikzpicture}
\begin{axis}[title=Rectangle from patch input (Function order 1)]
\addplot3[patch,shader=interp,patch type=rectangle] coordinates {
(0,0,0)
(1,0,0)
(1,1,1)
(0,1,0)
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[title=Rectangle from patch input (Function order 0)]
\addplot3[patch,shader=interp,colormap access=const,patch type=rectangle] coordinates {
(0,0,0)
(1,0,0)
(1,1,1)
(0,1,0)
};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[title=Rectangle from patch input (No function)]
\addplot3[patch,shader=interp,mesh/color input=explicit,patch type=rectangle] coordinates {
(0,0,0) [color=blue]
(1,0,0) [color=red]
(1,1,1) [color=green]
(0,1,0) [color=yellow]
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[title=Rectangle from patch input (Function order 1 CMYK),
colormap default colorspace=cmyk,
colormap={hot}{color(0cm)=(blue); color(1cm)=(yellow); color(2cm)=(orange); color(3cm)=(red)},
]
\addplot3[patch,shader=interp,patch type=rectangle] coordinates {
(0,0,0)
(1,0,0)
(1,1,1)
(0,1,0)
};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[title=Rectangle from patch input (Function order 1 GRAY),
colormap default colorspace=gray,
colormap={hot}{color(0cm)=(blue); color(1cm)=(yellow); color(2cm)=(orange); color(3cm)=(red)},
]
\addplot3[patch,shader=interp,patch type=rectangle] coordinates {
(0,0,0)
(1,0,0)
(1,1,1)
(0,1,0)
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[title=Standard use-case,colorbar,
]
\addplot3[surf,shader=interp] {x*y};
\end{axis}
\end{tikzpicture}
\clearpage
\begin{tikzpicture}
\begin{axis}[
title=Bilinear from $4$--point patch input (Function order 1)]
\addplot3[patch,shader=interp,patch type=bilinear]
coordinates {
(0,0,0)
(1,0,0)
(1,1,1)
(0,1,0)
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[
title=Bilinear from $4$--point patch input (Function order 0)]
\addplot3[patch,shader=interp,colormap access=const,patch type=bilinear]
coordinates {
(0,0,0)
(1,0,0)
(1,1,1)
(0,1,0)
};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
title=Bilinear from $4$--point patch input (No Function)]
\addplot3[patch,shader=interp,mesh/color input=explicit,patch type=bilinear]
coordinates {
(0,0,0) [color=blue]
(1,0,0) [color=red]
(1,1,1) [color=green]
(0,1,0) [color=yellow]
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[
colormap default colorspace=cmyk,
colormap={hot}{color(0cm)=(blue); color(1cm)=(yellow); color(2cm)=(orange); color(3cm)=(red)},
title=Bilinear from $4$--point patch input (Function order 1 CMYK)]
\addplot3[patch,shader=interp,patch type=bilinear]
coordinates {
(0,0,0)
(1,0,0)
(1,1,1)
(0,1,0)
};
\end{axis}
\end{tikzpicture}
\clearpage
\begin{tikzpicture}
\begin{axis}[enlargelimits,
title=Single Triangle patch (Function order 1)]
\addplot3[patch,shader=interp,] coordinates {
(0,0,1)
(1,0,0)
(1,1,0)
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[enlargelimits,
title=Single Triangle patch (Function order 0)]
\addplot3[patch,colormap access=const,shader=interp,] coordinates {
(0,0,1)
(1,0,0)
(1,1,0)
};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[enlargelimits,
title=Single Triangle patch (No Function)]
\addplot3[patch,mesh/color input=explicit,shader=interp,] coordinates {
(0,0,1) [color=blue]
(1,0,0) [color=red]
(1,1,0) [color=green]
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[enlargelimits,
colormap default colorspace=cmyk,
colormap={hot}{color(0cm)=(blue); color(1cm)=(yellow); color(2cm)=(orange); color(3cm)=(red)},
title=Single Triangle patch (Function order 1 CMYK)]
\addplot3[patch,shader=interp,] coordinates {
(0,0,1)
(1,0,0)
(1,1,0)
};
\end{axis}
\end{tikzpicture}
\clearpage
\begin{tikzpicture}
\begin{axis}[
title=Quadratic Triangle (Function Order 1)]
\addplot[patch,shader=interp,patch type=triangle quadr,
]
coordinates {
(0,0) (5,4) (0,7)
(2,3) (3,6) (-1,4)
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[
title=Quadratic Triangle (Function Order 2)]
\addplot[patch,shader=interp,colormap access=const,patch type=triangle quadr,
]
coordinates {
(0,0) (5,4) (0,7)
(2,3) (3,6) (-1,4)
};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
title=Quadratic Triangle (No Function)]
\addplot[patch,shader=interp,mesh/color input=explicit,patch type=triangle quadr,
]
coordinates {
(0,0) [color=red] (5,4) [color=blue] (0,7) [color=green]
(2,3) (3,6) (-1,4)
};
\end{axis}
\end{tikzpicture}
\clearpage
\begin{tikzpicture}
\begin{axis}[
title=Single Biquadratic Quadrilateral (Function Order 1)]
\addplot[patch,shader=interp,patch type=biquadratic,
]
coordinates {
(0,0) (6,1) (5,5) (-1,5)
(3,1) (6,3) (2,6) (0,3)
(3,3.75)
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[
title=Single Biquadratic Quadrilateral (Function Order 0)]
\addplot[patch,shader=interp,colormap access=const,patch type=biquadratic,
]
coordinates {
(0,0) (6,1) (5,5) (-1,5)
(3,1) (6,3) (2,6) (0,3)
(3,3.75)
};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
title=Single Biquadratic Quadrilateral (No Function)]
\addplot[patch,shader=interp,mesh/color input=explicit,patch type=biquadratic,
]
coordinates {
(0,0) [color=red] (6,1) [color=blue] (5,5) [color=green] (-1,5) [color=yellow]
(3,1) (6,3) (2,6) (0,3)
(3,3.75)
};
\end{axis}
\end{tikzpicture}
\clearpage
%
\begin{tikzpicture}
\begin{axis}[
title=Single Bicubic Quadrilateral (Function order 1)]
\addplot3[patch,shader=interp,patch type=bicubic,]
coordinates {
(0,0,1) (1,0,0) (2,0,0) (3,0,0)
(0,1,0) (1,1,0) (2,1,0) (3,1,0)
(0,2,0) (1,2,0) (2,2,0) (3,2,0)
(0,3,0) (1,3,0) (2,3,0) (3,3,0)
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[
title=Single Bicubic Quadrilateral (Function order 0)]
\addplot3[patch,shader=interp,colormap access=const,patch type=bicubic,]
coordinates {
(0,0,1) (1,0,0) (2,0,0) (3,0,0)
(0,1,0) (1,1,0) (2,1,0) (3,1,0)
(0,2,0) (1,2,0) (2,2,0) (3,2,0)
(0,3,0) (1,3,0) (2,3,0) (3,3,0)
};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
title=Single Bicubic Quadrilateral (No Function)]
\addplot3[patch,shader=interp,mesh/color input=explicit,patch type=bicubic,]
coordinates {
(0,0,1) [color=red] (1,0,0) (2,0,0) (3,0,0) [color=blue]
(0,1,0) (1,1,0) (2,1,0) (3,1,0)
(0,2,0) (1,2,0) (2,2,0) (3,2,0)
(0,3,0) [color=green] (1,3,0) (2,3,0) (3,3,0) [color=yellow]
};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}[
colormap default colorspace=cmyk,
colormap={hot}{color(0cm)=(blue); color(1cm)=(yellow); color(2cm)=(orange); color(3cm)=(red)},
title=Single Bicubic Quadrilateral (Function order 1 CMYK)]
\addplot3[patch,shader=interp,patch type=bicubic,]
coordinates {
(0,0,1) (1,0,0) (2,0,0) (3,0,0)
(0,1,0) (1,1,0) (2,1,0) (3,1,0)
(0,2,0) (1,2,0) (2,2,0) (3,2,0)
(0,3,0) (1,3,0) (2,3,0) (3,3,0)
};
\end{axis}
\end{tikzpicture}
\end{document}
@cfeuersaenger Thank you providing this information!
Note that functions of order 0 also suffer from the very same defect: interpolation is carried out in the target colorspace instead of the source color space.
Attaching a simple example to demonstrate the effect.
I reproduced the failure with todays "Demo" pdf.js (both with order0.pdf and with P.pdf uploaded 1.5 years ago).
I copy my early problem assessment from above as it is somewhat buried in my lengthy comments:
The bug appears to be in display/pattern_helper.js and in pattern.js : pattern.js already evaluates this.context.colorFn in readComponents and pattern_helper.js merely interpolates the final colors (in drawTriangle, for example).
Plots produced by pgfplots can contain uncommon shaders which are not rendered correctly by pdf.js.
See for instance page 128 of the pgfplots manual (version 1.12.1). On the left: pdf.js in Firefox 39.0, on the right: Adobe Reader 11.0.12. Both running on Windows 7 x64.
More examples of shaders that do not work are in the chapter about the patchplots library (page 396–412). Not all unsupported shaders render as black; some are missing: