Search code examples
pdfgnuplotfile-conversioneps

How to avoid gray outline artefacts when converting an eps image to pdf?


To generate vector graphics figures with LaTeX labels, I use gnuplot and the cairolatex terminal, creating the image via plot "data.txt" u 1:2:3 matrix with image notitle followed by:

latex figuregen.tex
dvips -E -ofile.eps figuregen

# Correct the bounding box automatically:
epstool --copy --bbox file.eps filename.eps

## Create a pdf:
ps2pdf -dPDFSETTINGS=/prepress -dSubsetFonts=true -dEmbedAllFonts=true -dMaxSubsetPct=100 -dCompatibilityLevel=1.3 -dEPSCrop filename.eps filename.pdf

Here is a zoom on a specific region of the original eps image: eps file White regions actually correspond to NaN values in the data file.

Now using the pdf file converted from eps: after conversion to pdf In the pdf version, there are now unwanted outlines around all the NaN pixels, creating an awful lot of noise in the higher portion of the image.

I want to have these images as pdf, free of artefacts, and preserve high-quality LaTeX labels. I suspect that there might be a ps2pdf option to deactivate this kind of unwanted behaviour but I just cannot find it.

I tried things such as: -dGraphicsAlphaBits=1, -dNOINTERPOLATE, -dALLOWPSTRANSPARENCY, -dNOTRANSPARENCY, -dCompatibilityLevel=1.4 or -dCompatibilityLevel=1.5, but without success.

I also tried fixing this directly in gnuplot, but without success (see e.g. below).

Would any of you know how to solve this issue?

Thank you very much for your time!

EDIT

What's even more surprising and problematic is that these artefacts also appear when printed.

Note however that they do not appear at extreme levels of zoom in evince when only a small part of the data set is plotted.

MWE:

# plot.plt
set size ratio -1

set palette defined ( 0 '#D73027', 1 '#F46D43', 2 '#FDAE61', 3 '#FEE090', 4 '#FFFFD9', 5 '#E0F3F8', 6 '#ABD9E9', 7 '#74ADD1', 8 '#4575B4' )

#set yr [300:0] ### no artefacts if zoom is higher than 1310% in evince
set yr [400:100] ### no artefacts if zoom is higher than 1780% in evince
#set yr [450:0] ### artefacts at all zoom levels if we show more data, or all of it

set term cairolatex dashed color; set output "temp.tex"

plot "data.txt" u 1:2:3 matrix with image notitle

set output #Closes the temporary output file.   
!sed -e 's|/Title|%/Title|' -e 's|/Subject|%/Subject|' -e 's|/Creator|%/Creator|' -e 's|/Author|%/Author|' < temp.tex > graph.tex

and, for completeness:

% figuregen.tex

\documentclass[dvips]{article}
\pagestyle{empty}
\usepackage[dvips]{graphicx} %
\begin{document}
\input graph.tex   
\end{document}

If needed, part of the data can be found in text form here; enough to reproduce the issue: https://paste.nomagic.uk/?e0343cc8f759040a#DkRxNiNrH6d3QMZ985CxhA21pG2HpVEShrfjg84uvAdt

EDIT 2

In fact, same artefact issues appear when using set terminal cairolatex pdf

set terminal cairolatex standalone pdf size 16cm,10.5cm dashed transparent
set output "plot.tex"

directly with pdflatex

gnuplot<plot.plt
pdflatex plot.tex

(Note, this is using Gnuplot Version 5.2 patchlevel 6).


Solution

  • The actual problem is, that NaN values are set to transparent black pixels (#00000000).

    The transparency causes these gray outline artifacts, depending on the zooming level. If you zoom close enough, then you see no artifacts.

    But as soon as the image pixels are smaller than your monitor pixels, the values are interpolated for screen display. Its seems that pdf viewers like evince (I tested also okular and mupdf) interpolate both color and alpha channels, so that the alpha value of the Nan pixels is changed, and the underlying black appears as gray border around the color pixels.

    I tried several ways. The easiest one, which actually worked for me was to use the tikz terminal with option externalimages which saves images created with image as separate png file. These png file also contains transparency, and the final result has the same artifacts. But you can use imagemagick's convert to change the transparent NaN pixels of the png to white with

    convert temp.001.png -alpha off -fill white -opaque black temp.001.png
    

    So, a fully working plot file is

    # plot.plt
    set size ratio -1
    
    set palette defined ( 0 '#D73027', 1 '#F46D43', 2 '#FDAE61', 3 '#FEE090', 4 '#FFFFD9', 5 '#E0F3F8', 6 '#ABD9E9', 7 '#74ADD1', 8 '#4575B4' )
    
    set ytics 100
    set yrange reverse
    
    set term tikz standalone externalimages background "white"; set output "temp.tex"
    
    plot "data.txt" u 1:2:3 matrix with image notitle
    
    # temp.001.png is the external image which contains only the 'with image' part
    # We must remove the #00000000 color, which represents the NaN pixels
    # I couldn't replace the colors directly, but I could first remove the alpha channel
    # and then change black to white, because no other black pixel appear
    !convert temp.001.png -alpha off -fill white -opaque black temp.001.png
    
    set output #Closes the temporary output file.   
    !sed -e 's|/Title|%/Title|' -e 's|/Subject|%/Subject|' -e 's|/Creator|%/Creator|' -e 's|/Author|%/Author|' < temp.tex > graph.tex
    !pdflatex graph.tex
    

    Mupdf screen shot for graph.pdf:

    enter image description here

    Note, that I used standalone to be able to directly compile the resulting file, so that I could check the result.

    A more cumbersome alternative would be to "manually" plot with image to a png file, and include that in a second plot, like I described in Big data surface plots: Call gnuplot from tikz to generate bitmap and include automatically? Then you can have more influence on how the png is generated.