Convert color pdf to grayscale pdf using Python & Matplotlib via Ghostscript




This page shows how to convert color pdf figures generated by python and matplotlib into grayscale pdf via Ghostscript.

See also:

Python Matplotlib Tips: Plot 12-bit tiff image with log scale colorbar using python & matplotlib.pyplot

Some of the output data from measuring equipment have 12-bit unsigned int data. In some case, tiff format is used to ensure the convenience of the users. Reading the 12-bit tiff file and plotting the 12-bit tiff file is very easy. In addition, you can increase the visibility of the output figure by using log scale colormap when you plotting the tiff file. This page shows how to plot 12-bit tiff file in log scale using python and matplotlib.pyplot. 2D gaussian distribution is used as an example data.


Python Matplotlib Tips: Draw three colormap with two colorbar using python and matplotlib.pyplot

This page shows an example of how to arrange three colormap with two colorbar. One colorbar corresponds two colormaps, while the other corresponds to one colormap. Gridspec enables us to properly adjust these positions in the figure.


In [1]:
import platform
print('python: '+platform.python_version())
import matplotlib.pyplot as plt
from matplotlib import __version__ as matplotlibversion
print('matplotlib: '+matplotlibversion)
import numpy as np
print('numpy: '+np.__version__)
%matplotlib inline
import subprocess
python: 3.7.6
matplotlib: 3.1.3
numpy: 1.18.1

Define pdf2gray function to convert color pdf to grayscale pdf via Ghostscript.
Note that the Ghostscript command is gs for Mac/Linux, while it is gswin64c for 64bit windows.

In [2]:
def pdf2gray(fnamein, verbose=False):

    import os
    from os.path import isfile
    '''
    convert pdf from color to grayscale
    '''
    if verbose:
        def vprint(*args):
            for arg in args:
                print(arg)
    else:   
        vprint = lambda *a: None

    vprint('filename: %s' % fnamein)
    
    if fnamein.split('.')[-1] != 'pdf':
        vprint('extension is not pdf, ".pdf" is added.')
        fnamein += '.pdf'
        vprint('modified filename: %s' % fnamein)
    
    if not isfile(fnamein):
        raise FileNotFoundError('No file named %s' % fnamein)

    fnameout = '_g.'.join(fnamein.split('.'))

    if os.name == 'nt':
        gscmd = 'gswin64c'
    elif os.name == 'posix':
        gscmd = 'gs'

    opts = ['%s' % gscmd,
            '-sDEVICE=pdfwrite',
            '-sColorConversionStrategy=Gray',
            '-dProcessColorModel=/DeviceGray',
            '-dCompatibilityLevel=1.4',
            '-dBATCH',
            '-dNOPAUSE',
            '-sOutputFile=%s' % fnameout,
            '%s' % fnamein,
            ]
    cmd = ' '.join(opts)
    vprint('following command is given to Ghostscript:\n%s\n----' % cmd)
    proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    for line in proc.stdout:
        vprint(line.decode('ascii').replace('\n', ''))

Plot dummy color 2d map

In [3]:
xlist = np.linspace(-3.0, 3.0, 100)
ylist = np.linspace(-3.0, 3.0, 100)

X, Y = np.meshgrid(xlist, ylist)
Z = np.sqrt(X**2 + Y**2)
fig,ax=plt.subplots(1,1)
cp = ax.contourf(X, Y, Z)
fig.colorbar(cp)

fn = 'color2gray.pdf'
plt.savefig(fn)

Then you will find color2gray.pdf

In [4]:
proc = subprocess.Popen('ls color2gray*', shell=True, stdout=subprocess.PIPE)
for line in proc.stdout:
    print(line.decode('ascii').replace('\n', ''))
color2gray.pdf

Convert color2gray.pdf to grayscale

In [5]:
pdf2gray(fn, verbose=True)
filename: color2gray.pdf
following command is given to Ghostscript:
gs -sDEVICE=pdfwrite -sColorConversionStrategy=Gray -dProcessColorModel=/DeviceGray -dCompatibilityLevel=1.4 -dBATCH -dNOPAUSE -sOutputFile=color2gray_g.pdf color2gray.pdf
----
GPL Ghostscript 9.52 (2020-03-19)
Copyright (C) 2020 Artifex Software, Inc.  All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
Processing pages 1 through 1.
Page 1

Finally you will see color2gray_g.pdf with grayscale.

In [6]:
proc = subprocess.Popen('ls color2*', shell=True, stdout=subprocess.PIPE)
for line in proc.stdout:
    print(line.decode('ascii').replace('\n', ''))
color2gray.pdf
color2gray_g.pdf