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

Skip to content

Fixed background colour of PNGs saved with a non-zero opacity. #1868

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 1, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/users/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ default quality is 95; previously, the default quality was 75. This change
minimizes the artifacting inherent in JPEG images, particularly with images
that have sharp changes in color as plots often do.

Full control of the background color
------------------------------------
Wes Campaigne and Phil Elson fixed the Agg backend such that PNGs are now
saved with the correct background color when :meth:`fig.patch.get_alpha` is
not 1.


.. _whats-new-1-2-2:

new in matplotlib 1.2.2
Expand Down
9 changes: 5 additions & 4 deletions lib/matplotlib/backends/backend_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@

TODO:

* allow save to file handle

* integrate screen dpi w/ ppi and text

"""
from __future__ import division
import threading
Expand Down Expand Up @@ -438,7 +437,7 @@ def draw(self):
"""
if __debug__: verbose.report('FigureCanvasAgg.draw', 'debug-annoying')

self.renderer = self.get_renderer()
self.renderer = self.get_renderer(cleared=True)
# acquire a lock on the shared font cache
RendererAgg.lock.acquire()

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



def get_renderer(self):
def get_renderer(self, cleared=False):
l, b, w, h = self.figure.bbox.bounds
key = w, h, self.figure.dpi
try: self._lastKey, self.renderer
Expand All @@ -459,6 +458,8 @@ def get_renderer(self):
if need_new_renderer:
self.renderer = RendererAgg(w, h, self.figure.dpi)
self._lastKey = key
elif cleared:
self.renderer.clear()
return self.renderer

def tostring_rgb(self):
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ def __init__(self, filename):

revision = ''
self.infoDict = {
'Creator': 'matplotlib %s, http://matplotlib.sf.net' % __version__,
'Creator': 'matplotlib %s, http://matplotlib.org' % __version__,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

'Producer': 'matplotlib pdf backend%s' % revision,
'CreationDate': datetime.today()
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 49 additions & 0 deletions lib/matplotlib/tests/test_agg.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,50 @@
from __future__ import print_function

import os
import tempfile


from numpy.testing import assert_array_almost_equal


from matplotlib.image import imread
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.testing.decorators import cleanup


@cleanup
def test_repeated_save_with_alpha():
# We want an image which has a background color of bluish green, with an
# alpha of 0.25.

fig = Figure([1, 0.4])
canvas = FigureCanvas(fig)
fig.set_facecolor((0, 1, 0.4))
fig.patch.set_alpha(0.25)

# The target color is fig.patch.get_facecolor()

_, img_fname = tempfile.mkstemp(suffix='.png')
try:
fig.savefig(img_fname,
facecolor=fig.get_facecolor(),
edgecolor='none')

# Save the figure again to check that the
# colors don't bleed from the previous renderer.
fig.savefig(img_fname,
facecolor=fig.get_facecolor(),
edgecolor='none')

# Check the first pixel has the desired color & alpha
# (approx: 0, 1.0, 0.4, 0.25)
assert_array_almost_equal(tuple(imread(img_fname)[0, 0]),
(0.0, 1.0, 0.4, 0.250),
decimal=3)
finally:
os.remove(img_fname)


def report_memory(i):
pid = os.getpid()
Expand Down Expand Up @@ -64,3 +108,8 @@ def report_memory(i):
## # w/o text and w/o write_png: Average memory consumed per loop: 0.02
## # w/o text and w/ write_png : Average memory consumed per loop: 0.3400
## # w/ text and w/ write_png : Average memory consumed per loop: 0.32


if __name__ == "__main__":
import nose
nose.runmodule(argv=['-s', '--with-doctest'], exit=False)
19 changes: 19 additions & 0 deletions lib/matplotlib/tests/test_figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,25 @@ def test_suptitle():
fig.suptitle('title', color='g', rotation='30')


@image_comparison(baseline_images=['alpha_background'],
# only test png and svg. The PDF output appears correct,
# but Ghostscript does not preserve the background color.
extensions=['png', 'svg'],
savefig_kwarg={'facecolor': (0, 1, 0.4), 'edgecolor': 'none'})
def test_alpha():
# We want an image which has a background color and an
# alpha of 0.4.
fig = plt.figure(figsize=[2, 1])
fig.set_facecolor((0, 1, 0.4))
fig.patch.set_alpha(0.4)

import matplotlib.patches as mpatches
fig.patches.append(mpatches.CirclePolygon([20, 20],
radius=15,
alpha=0.6,
facecolor='red'))


if __name__ == "__main__":
import nose
nose.runmodule(argv=['-s', '--with-doctest'], exit=False)
6 changes: 3 additions & 3 deletions src/_backend_agg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ RendererAgg::RendererAgg(unsigned int width, unsigned int height, double dpi,
renderingBuffer.attach(pixBuffer, width, height, stride);
pixFmt.attach(renderingBuffer);
rendererBase.attach(pixFmt);
rendererBase.clear(agg::rgba(1, 1, 1, 0));
rendererBase.clear(agg::rgba(0, 0, 0, 0));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious -- why does this matter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH I'm not sure. I'll experiment with reverting this (and my other colour change) now that I've merged @Westacular 's changes into this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it shouldn't make a difference anymore, now that the zero alpha value is being handled correctly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW: I don't care that it's been changed -- all zeros is in some way nicer -- I just wanted to make sure I was understanding what was going on.

rendererAA.attach(rendererBase);
rendererBin.attach(rendererBase);
hatchRenderingBuffer.attach(hatchBuffer, HATCH_SIZE, HATCH_SIZE,
Expand Down Expand Up @@ -1108,7 +1108,7 @@ RendererAgg::draw_image(const Py::Tuple& args)
inv_mtx.invert();

typedef agg::span_allocator<agg::rgba8> color_span_alloc_type;
typedef agg::image_accessor_clip<agg::pixfmt_rgba32>
typedef agg::image_accessor_clip<agg::pixfmt_rgba32_plain>
image_accessor_type;
typedef agg::span_interpolator_linear<> interpolator_type;
typedef agg::span_image_filter_rgba_nn<image_accessor_type,
Expand Down Expand Up @@ -2388,7 +2388,7 @@ RendererAgg::clear(const Py::Tuple& args)
_VERBOSE("RendererAgg::clear");

args.verify_length(0);
rendererBase.clear(agg::rgba(1, 1, 1, 0));
rendererBase.clear(agg::rgba(0, 0, 0, 0));

return Py::Object();
}
Expand Down
2 changes: 1 addition & 1 deletion src/_backend_agg.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

const size_t NUM_VERTICES[] = { 1, 1, 1, 2, 3, 1 };

typedef agg::pixfmt_rgba32 pixfmt;
typedef agg::pixfmt_rgba32_plain pixfmt;
typedef agg::renderer_base<pixfmt> renderer_base;
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_aa;
typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_bin;
Expand Down
2 changes: 1 addition & 1 deletion src/_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include "mplutils.h"


typedef agg::pixfmt_rgba32 pixfmt;
typedef agg::pixfmt_rgba32_plain pixfmt;
typedef agg::pixfmt_rgba32_pre pixfmt_pre;
typedef agg::renderer_base<pixfmt> renderer_base;
typedef agg::span_interpolator_linear<> interpolator_type;
Expand Down