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

Skip to content

Commit b9957b1

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

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

lib/matplotlib/backends/backend_agg.py

Lines 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

Lines 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)