Description
Bug summary
Exporting a figure filled with imshow as pdf is using the wrong colors if the image size/resolution becomes large: E.g. gray cells become red.
Code for reproduction
import numpy as np
import matplotlib.pyplot as plt
# data: four background tiles with one of them highlighted
background = [0.9]*3 # gray
highlight = [1,0,0] # red
X = np.array([[background,highlight],[background,background]]) # varying colors and combinations gives a rich spectrum of bug-phenotypes
# big figure
dpi, figsize = 500, 20 # less dpi or figsize avoids the bug
fig,ax = plt.subplots(figsize=(figsize,figsize),dpi=dpi)
ax.imshow(X)
# export it
fig.savefig(f'minimal.png') # shows correctly three tiles in gray and one tile in red
fig.savefig(f'minimal.pdf') # shows incorrectly all four tiles in red
Actual outcome
The png export shows the correct colors: 3 quarters gray, 1 quarter red. The pdf export shows incorrect colors: 4 quarters red.
minimal.pdf
Expected outcome
The png and pdf export shows the correct colors: 3 quarters gray, 1 quarter red. I.e. the pdf should also look like the png pasted above.
Additional information
This bug only appears for large figure sizes and dpi (maybe if figuresize * dpi is larger than some threshold).
It is also dependent on the colors chosen and the content of the image. In my real-world use case I have a large heatmap with many fields and one color is consistently replaced by some other color from the plot. I also observed variations which replace a color with a darker version of it, e.g. if one switches the roles of red and gray in the minimal example above: Then instead of red the background is dark red in the pdf.
This minimal example was executed in a fresh conda env with matplotlib as only dependency. I tried it before with matplotlib 3.6.3 on a less clean environment with the same results. I dont have an example of it working in previous versions.
I guess it is an issue with a buffer of fixed size in the pdf backend, as it works with the png backend.
A workaround can be the reduction of the dpi - for vector graphics this still contains all the information. But it changes the "physical" size of the pdf.
Operating system
RHEL 7.9
Matplotlib Version
3.7.1
Matplotlib Backend
No response
Python version
3.11.3
Jupyter version
No response
Installation
conda