Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d8fce7b

Browse files
committed
Fixed background colour of PNGs saved with a non-zero opacity.
1 parent d94036c commit d8fce7b

File tree

8 files changed

+125
-7
lines changed

8 files changed

+125
-7
lines changed

doc/users/whats_new.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ Multiple images on same axes are correctly transparent
166166
When putting multiple images onto the same axes, the background color
167167
of the axes will now show through correctly.
168168

169+
Full control of the background color
170+
------------------------------------
171+
Phil Elson fixed the Agg backend such that PNGs are now saved with the correct
172+
background color when :meth:`fig.patch.get_alpha` is not 1.
173+
169174
.. _whats-new-1-2:
170175

171176
new in matplotlib-1.2

lib/matplotlib/backends/backend_agg.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@
1616
1717
TODO:
1818
19-
* allow save to file handle
20-
2119
* integrate screen dpi w/ ppi and text
20+
2221
"""
2322
from __future__ import division
2423
import threading
@@ -438,7 +437,7 @@ def draw(self):
438437
"""
439438
if __debug__: verbose.report('FigureCanvasAgg.draw', 'debug-annoying')
440439

441-
self.renderer = self.get_renderer()
440+
self.renderer = self.get_renderer(cleared=True)
442441
# acquire a lock on the shared font cache
443442
RendererAgg.lock.acquire()
444443

@@ -449,7 +448,7 @@ def draw(self):
449448

450449

451450

452-
def get_renderer(self):
451+
def get_renderer(self, cleared=False):
453452
l, b, w, h = self.figure.bbox.bounds
454453
key = w, h, self.figure.dpi
455454
try: self._lastKey, self.renderer
@@ -459,6 +458,8 @@ def get_renderer(self):
459458
if need_new_renderer:
460459
self.renderer = RendererAgg(w, h, self.figure.dpi)
461460
self._lastKey = key
461+
elif cleared:
462+
self.renderer.clear()
462463
return self.renderer
463464

464465
def tostring_rgb(self):

lib/matplotlib/backends/backend_pdf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ def __init__(self, filename):
436436

437437
revision = ''
438438
self.infoDict = {
439-
'Creator': 'matplotlib %s, http://matplotlib.sf.net' % __version__,
439+
'Creator': 'matplotlib %s, http://matplotlib.org' % __version__,
440440
'Producer': 'matplotlib pdf backend%s' % revision,
441441
'CreationDate': datetime.today()
442442
}
Lines changed: 47 additions & 0 deletions
Loading

lib/matplotlib/tests/test_agg.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,50 @@
11
from __future__ import print_function
22

33
import os
4+
import tempfile
5+
6+
7+
from numpy.testing import assert_array_almost_equal
8+
9+
10+
from matplotlib.image import imread
11+
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
12+
from matplotlib.figure import Figure
13+
from matplotlib.testing.decorators import cleanup
14+
15+
16+
@cleanup
17+
def test_repeated_save_with_alpha():
18+
# We want an image which has a background color of blue, with an
19+
# alpha of 0.25.
20+
21+
fig = Figure([1, 0.4])
22+
canvas = FigureCanvas(fig)
23+
fig.set_facecolor((0, 0, 0.4))
24+
fig.patch.set_alpha(0.25)
25+
26+
# The target color is fig.patch.get_facecolor()
27+
28+
_, img_fname = tempfile.mkstemp(suffix='.png')
29+
try:
30+
fig.savefig(img_fname,
31+
facecolor=fig.get_facecolor(),
32+
edgecolor='none')
33+
34+
# Save the figure again to check that the
35+
# colors don't bleed from the previous renderer.
36+
fig.savefig(img_fname,
37+
facecolor=fig.get_facecolor(),
38+
edgecolor='none')
39+
40+
# Check the first pixel has the desired color & alpha
41+
# (approx: 0, 0, 0.1, 0.25)
42+
assert_array_almost_equal(tuple(imread(img_fname)[0, 0]),
43+
(0.0, 0.0, 0.098, 0.250),
44+
decimal=3)
45+
finally:
46+
os.remove(img_fname)
47+
448

549
def report_memory(i):
650
pid = os.getpid()
@@ -64,3 +108,8 @@ def report_memory(i):
64108
## # w/o text and w/o write_png: Average memory consumed per loop: 0.02
65109
## # w/o text and w/ write_png : Average memory consumed per loop: 0.3400
66110
## # w/ text and w/ write_png : Average memory consumed per loop: 0.32
111+
112+
113+
if __name__ == "__main__":
114+
import nose
115+
nose.runmodule(argv=['-s', '--with-doctest'], exit=False)

lib/matplotlib/tests/test_figure.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,22 @@ def test_suptitle():
7474
fig.suptitle('title', color='g', rotation='30')
7575

7676

77+
@image_comparison(baseline_images=['alpha_background'],
78+
extensions=['png', 'svg'], # PDF is wrong
79+
savefig_kwarg={'facecolor': 'black', 'edgecolor': 'none'})
80+
def test_alpha():
81+
# We want an image which has a background color of black, with an
82+
# alpha of 0.3.
83+
fig = plt.figure(figsize=[2, 1])
84+
fig.set_facecolor('black')
85+
fig.patch.set_alpha(0.3)
86+
87+
import matplotlib.patches as mpatches
88+
fig.patches.append(mpatches.CirclePolygon([20, 20],
89+
radius=15,
90+
facecolor='red'))
91+
92+
7793
if __name__ == "__main__":
7894
import nose
7995
nose.runmodule(argv=['-s', '--with-doctest'], exit=False)

src/_backend_agg.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ RendererAgg::RendererAgg(unsigned int width, unsigned int height, double dpi,
411411
renderingBuffer.attach(pixBuffer, width, height, stride);
412412
pixFmt.attach(renderingBuffer);
413413
rendererBase.attach(pixFmt);
414-
rendererBase.clear(agg::rgba(1, 1, 1, 0));
414+
rendererBase.clear(agg::rgba(0, 0, 0, 0));
415415
rendererAA.attach(rendererBase);
416416
rendererBin.attach(rendererBase);
417417
hatchRenderingBuffer.attach(hatchBuffer, HATCH_SIZE, HATCH_SIZE,
@@ -2388,7 +2388,7 @@ RendererAgg::clear(const Py::Tuple& args)
23882388
_VERBOSE("RendererAgg::clear");
23892389

23902390
args.verify_length(0);
2391-
rendererBase.clear(agg::rgba(1, 1, 1, 0));
2391+
rendererBase.clear(agg::rgba(0, 0, 0, 0));
23922392

23932393
return Py::Object();
23942394
}

0 commit comments

Comments
 (0)