I have some color plots that I need to be saved in grayscale. Is there an easy way to do this without changing the plotting formats?
6 Answers
It's currently awkward to do directly from matplotlib, but in "the future" they plan to support a set_gray(True) call on the figure (see the mailing list thread here).
Your best options will be to save it in color and convert it, either in python with PIL:
import Image
Image.open('color.png').convert('L').save('bw.png')
or from the command line with imagemagick:
convert -type Grayscale color.png bw.png
1 Comment
Actually, this was asked before. Here is a pretty good answer, which comes 2nd on google (as of today):
Display image as grayscale using matplotlib
And the solution is VERY similar to Suki's...
Oh, well, I am bored, so I post here also a full blown code:
import numpy as np
import pylab as p
xv=np.ones(4)*.5
yv=np.arange(0,4,1)
xv1=np.ones(4)*-.5
yv1=np.arange(0,4,1)
#red vertical line on the right
yv2=np.arange(0,1.5,0.1)
xv2=np.ones_like(yv2)*.7
#red vertical line on the left
yv3=np.arange(0,2,0.01)
xv3=np.ones_like(yv3)*-0.7
###
xc=np.arange(-1.4,2,0.05)
yc=np.ones_like(xc)*1
fig = p.figure()
ax1 = fig.add_subplot(111)
#adjustprops = dict(left=0.12, bottom=0.2, right=0.965, top=0.96, wspace=0.13, hspace=0.37)
#fig.subplots_adjust(**adjustprops)
ax1.plot(xv,yv, color='blue', lw=1, linestyle='dashed')
ax1.plot(xv1,yv1, 'green', linestyle='dashed')
ax1.plot(np.r_[-1:1:0.2],np.r_[-1:1:0.2],'red')
ax1.plot(xc,yc, 'k.', markersize=3)
p.savefig('colored_image.png')
import matplotlib.image as mpimg
import matplotlib.cm as cm
import Image
figprops = dict(figsize=(10,10), dpi=100)
fig1 = p.figure(**figprops)
#fig1 = p.figure()
#ax1 = fig.add_subplot(111)
adjustprops = dict()
image=Image.open('colored_image.png').convert("L")
arr=np.asarray(image)
p.figimage(arr,cmap=cm.Greys_r)
p.savefig('grayed.png')
p.savefig('grayed.pdf',papertype='a4',orientation='portrait')
This will produce a graph in color, than read it, convert it to gray scale, and will save a png and pdf.
2 Comments
I am struggling with this issue too. As far as I can tell, matplotlib doesn't support direct conversion to grayscale, but you can save a color pdf and then convert it to grayscale with ghostscript:
gs -sOutputFile=gray.pdf -sDEVICE=pdfwrite -sColorConversionStrategy=Gray -dProcessColorModel=/DeviceGray -dNOPAUSE -dBATCH -dAutoRotatePages=/None color.pdf
5 Comments
And to add to Mu Mind's solution
If for whatever reason you want to avoid writing it to a file you can use StringIO like a file:
import Image
import pylab
from StringIO import StringIO
pylab.plot(range(10),[x**2 for x in range(10)])
IO = StringIO()
pylab.savefig(IO,format='png')
IO.seek(0)
#this, I stole from Mu Mind solution
Image.open(IO).convert('L').show()
1 Comment
Developed from Ian Goodfellow's answer, here is a python script that generates and runs a ghostscript command that converts a PDF into grayscale. It is preferable to the answers that rasterise to PNG as it retains the vector representation of the plot.
import subprocess
import sys
def pdf_to_grayscale(input_pdf, output_pdf):
try:
# Ghostscript command to convert PDF to grayscale
ghostscript_cmd = [
"gs",
"-sDEVICE=pdfwrite",
"-sColorConversionStrategy=Gray",
"-sProcessColorModel=DeviceGray",
"-dCompatibilityLevel=1.4",
"-dNOPAUSE",
"-dQUIET",
"-dBATCH",
f"-sOutputFile={output_pdf}",
input_pdf
]
# Execute Ghostscript command using subprocess
subprocess.run(ghostscript_cmd, check=True)
print("PDF converted to grayscale successfully.")
except subprocess.CalledProcessError:
print("Error occurred during PDF conversion to grayscale.")
if __name__ == "__main__":
assert len(sys.argv) == 3, "Two args: input pdf and output pdf"
pdf_to_grayscale(sys.argv[1], sys.argv[2])
Save it as to_gray.py and run it like this:
python to_gray.py test.pdf gray.pdf
set_grayattribute is available or not in the latest release of matplotlib.convert -type Grayscale old.png new.pngI think there is already something on SO cf link