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

Skip to content

Commit feec983

Browse files
committed
Merge pull request matplotlib#4595 from jkseppan/grayscale-smask
Fix alpha channels in PDF images
2 parents 906c61e + 141d796 commit feec983

File tree

3 files changed

+47
-29
lines changed

3 files changed

+47
-29
lines changed

lib/matplotlib/backends/backend_pdf.py

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@
9292

9393
# TODOs:
9494
#
95-
# * the alpha channel of images
9695
# * image compression could be improved (PDF supports png-like compression)
9796
# * encoding of fonts, including mathtext fonts and unicode support
9897
# * TTF support has lots of small TODOs, e.g., how do you know if a font
@@ -1262,18 +1261,19 @@ def imageObject(self, image):
12621261
self.images[image] = (name, ob)
12631262
return name
12641263

1265-
# These two from backend_ps.py
1266-
# TODO: alpha (SMask, p. 518 of pdf spec)
1267-
12681264
def _rgb(self, im):
12691265
h, w, s = im.as_rgba_str()
12701266

12711267
rgba = np.fromstring(s, np.uint8)
12721268
rgba.shape = (h, w, 4)
12731269
rgba = rgba[::-1]
1274-
rgb = rgba[:, :, :3]
1275-
a = rgba[:, :, 3:]
1276-
return h, w, rgb.tostring(), a.tostring()
1270+
rgb = rgba[:, :, :3].tostring()
1271+
a = rgba[:, :, 3]
1272+
if np.all(a == 255):
1273+
alpha = None
1274+
else:
1275+
alpha = a.tostring()
1276+
return h, w, rgb, alpha
12771277

12781278
def _gray(self, im, rc=0.3, gc=0.59, bc=0.11):
12791279
rgbat = im.as_rgba_str()
@@ -1284,24 +1284,30 @@ def _gray(self, im, rc=0.3, gc=0.59, bc=0.11):
12841284
r = rgba_f[:, :, 0]
12851285
g = rgba_f[:, :, 1]
12861286
b = rgba_f[:, :, 2]
1287-
gray = (r*rc + g*gc + b*bc).astype(np.uint8)
1288-
return rgbat[0], rgbat[1], gray.tostring()
1287+
a = rgba[:, :, 3]
1288+
if np.all(a == 255):
1289+
alpha = None
1290+
else:
1291+
alpha = a.tostring()
1292+
gray = (r*rc + g*gc + b*bc).astype(np.uint8).tostring()
1293+
return rgbat[0], rgbat[1], gray, alpha
12891294

12901295
def writeImages(self):
12911296
for img, pair in six.iteritems(self.images):
12921297
if img.is_grayscale:
1293-
height, width, data = self._gray(img)
1294-
self.beginStream(
1295-
pair[1].id,
1296-
self.reserveObject('length of image stream'),
1297-
{'Type': Name('XObject'), 'Subtype': Name('Image'),
1298-
'Width': width, 'Height': height,
1299-
'ColorSpace': Name('DeviceGray'), 'BitsPerComponent': 8})
1300-
# TODO: predictors (i.e., output png)
1301-
self.currentstream.write(data)
1302-
self.endStream()
1298+
height, width, data, adata = self._gray(img)
13031299
else:
13041300
height, width, data, adata = self._rgb(img)
1301+
1302+
colorspace = 'DeviceGray' if img.is_grayscale else 'DeviceRGB'
1303+
obj = {'Type': Name('XObject'),
1304+
'Subtype': Name('Image'),
1305+
'Width': width,
1306+
'Height': height,
1307+
'ColorSpace': Name(colorspace),
1308+
'BitsPerComponent': 8}
1309+
1310+
if adata is not None:
13051311
smaskObject = self.reserveObject("smask")
13061312
self.beginStream(
13071313
smaskObject.id,
@@ -1312,17 +1318,16 @@ def writeImages(self):
13121318
# TODO: predictors (i.e., output png)
13131319
self.currentstream.write(adata)
13141320
self.endStream()
1321+
obj['SMask'] = smaskObject
13151322

1316-
self.beginStream(
1317-
pair[1].id,
1318-
self.reserveObject('length of image stream'),
1319-
{'Type': Name('XObject'), 'Subtype': Name('Image'),
1320-
'Width': width, 'Height': height,
1321-
'ColorSpace': Name('DeviceRGB'), 'BitsPerComponent': 8,
1322-
'SMask': smaskObject})
1323-
# TODO: predictors (i.e., output png)
1324-
self.currentstream.write(data)
1325-
self.endStream()
1323+
self.beginStream(
1324+
pair[1].id,
1325+
self.reserveObject('length of image stream'),
1326+
obj
1327+
)
1328+
# TODO: predictors (i.e., output png)
1329+
self.currentstream.write(data)
1330+
self.endStream()
13261331

13271332
def markerObject(self, path, trans, fillp, strokep, lw, joinstyle,
13281333
capstyle):
Binary file not shown.

lib/matplotlib/tests/test_backend_pdf.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,16 @@ def test_hatching_legend():
119119
b = plt.Rectangle([0, 0], 0, 0, facecolor="blue", hatch="XXXX")
120120

121121
fig.legend([a, b, a, b], ["", "", "", ""])
122+
123+
124+
@image_comparison(baseline_images=['grayscale_alpha'],
125+
extensions=['pdf'], tol=1e-3)
126+
def test_grayscale_alpha():
127+
"""Masking images with NaN did not work for grayscale images"""
128+
x, y = np.ogrid[-2:2:.1, -2:2:.1]
129+
dd = np.exp(-(x**2 + y**2))
130+
dd[dd < .1] = np.nan
131+
fig, ax = plt.subplots()
132+
ax.imshow(dd, interpolation='none', cmap='gray_r')
133+
ax.set_xticks([])
134+
ax.set_yticks([])

0 commit comments

Comments
 (0)