Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b9957b1

Browse filesBrowse files
committed
Merge pull request #5324 from mdboom/transparent-jpg
Fix #5302: Proper alpha-blending for jpeg
2 parents 544b27b + fb6ff8a commit b9957b1
Copy full SHA for b9957b1

File tree

Expand file treeCollapse file tree

2 files changed

+38
-3
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+38
-3
lines changed

‎lib/matplotlib/backends/backend_agg.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_agg.py
+9-2Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from matplotlib.mathtext import MathTextParser
3939
from matplotlib.path import Path
4040
from matplotlib.transforms import Bbox, BboxBase
41+
from matplotlib import colors as mcolors
4142

4243
from matplotlib.backends._backend_agg import RendererAgg as _RendererAgg
4344
from matplotlib import _png
@@ -551,7 +552,6 @@ def print_to_buffer(self):
551552
return result
552553

553554
if _has_pil:
554-
555555
# add JPEG support
556556
def print_jpg(self, filename_or_obj, *args, **kwargs):
557557
"""
@@ -573,14 +573,21 @@ def print_jpg(self, filename_or_obj, *args, **kwargs):
573573
buf, size = self.print_to_buffer()
574574
if kwargs.pop("dryrun", False):
575575
return
576+
# The image is "pasted" onto a white background image to safely
577+
# handle any transparency
576578
image = Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1)
579+
color = mcolors.colorConverter.to_rgb(
580+
rcParams.get('savefig.facecolor', 'white'))
581+
color = tuple([int(x * 255.0) for x in color])
582+
background = Image.new('RGB', size, color)
583+
background.paste(image, image)
577584
options = restrict_dict(kwargs, ['quality', 'optimize',
578585
'progressive'])
579586

580587
if 'quality' not in options:
581588
options['quality'] = rcParams['savefig.jpeg_quality']
582589

583-
return image.save(filename_or_obj, format='jpeg', **options)
590+
return background.save(filename_or_obj, format='jpeg', **options)
584591
print_jpeg = print_jpg
585592

586593
# add TIFF support

‎lib/matplotlib/tests/test_image.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_image.py
+29-1Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from matplotlib.testing.decorators import image_comparison, knownfailureif, cleanup
99
from matplotlib.image import BboxImage, imread, NonUniformImage
1010
from matplotlib.transforms import Bbox
11-
from matplotlib import rcParams
11+
from matplotlib import rcParams, rc_context
1212
import matplotlib.pyplot as plt
1313
from nose.tools import assert_raises
1414
from numpy.testing import assert_array_equal, assert_array_almost_equal
@@ -453,6 +453,34 @@ def test_nonuniformimage_setnorm():
453453
im = NonUniformImage(ax)
454454
im.set_norm(plt.Normalize())
455455

456+
@knownfailureif(not HAS_PIL)
457+
@cleanup
458+
def test_jpeg_alpha():
459+
plt.figure(figsize=(1, 1), dpi=300)
460+
# Create an image that is all black, with a gradient from 0-1 in
461+
# the alpha channel from left to right.
462+
im = np.zeros((300, 300, 4), dtype=np.float)
463+
im[..., 3] = np.linspace(0.0, 1.0, 300)
464+
465+
plt.figimage(im)
466+
467+
buff = io.BytesIO()
468+
with rc_context({'savefig.facecolor': 'red'}):
469+
plt.savefig(buff, transparent=True, format='jpg', dpi=300)
470+
471+
buff.seek(0)
472+
image = Image.open(buff)
473+
474+
# If this fails, there will be only one color (all black). If this
475+
# is working, we should have all 256 shades of grey represented.
476+
print("num colors: ", len(image.getcolors(256)))
477+
assert len(image.getcolors(256)) >= 175 and len(image.getcolors(256)) <= 185
478+
# The fully transparent part should be red, not white or black
479+
# or anything else
480+
print("corner pixel: ", image.getpixel((0, 0)))
481+
assert image.getpixel((0, 0)) == (254, 0, 0)
482+
483+
456484
if __name__=='__main__':
457485
import nose
458486
nose.runmodule(argv=['-s','--with-doctest'], exit=False)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.