92
92
93
93
# TODOs:
94
94
#
95
- # * the alpha channel of images
96
95
# * image compression could be improved (PDF supports png-like compression)
97
96
# * encoding of fonts, including mathtext fonts and unicode support
98
97
# * TTF support has lots of small TODOs, e.g., how do you know if a font
@@ -1262,18 +1261,19 @@ def imageObject(self, image):
1262
1261
self .images [image ] = (name , ob )
1263
1262
return name
1264
1263
1265
- # These two from backend_ps.py
1266
- # TODO: alpha (SMask, p. 518 of pdf spec)
1267
-
1268
1264
def _rgb (self , im ):
1269
1265
h , w , s = im .as_rgba_str ()
1270
1266
1271
1267
rgba = np .fromstring (s , np .uint8 )
1272
1268
rgba .shape = (h , w , 4 )
1273
1269
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
1277
1277
1278
1278
def _gray (self , im , rc = 0.3 , gc = 0.59 , bc = 0.11 ):
1279
1279
rgbat = im .as_rgba_str ()
@@ -1284,24 +1284,30 @@ def _gray(self, im, rc=0.3, gc=0.59, bc=0.11):
1284
1284
r = rgba_f [:, :, 0 ]
1285
1285
g = rgba_f [:, :, 1 ]
1286
1286
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
1289
1294
1290
1295
def writeImages (self ):
1291
1296
for img , pair in six .iteritems (self .images ):
1292
1297
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 )
1303
1299
else :
1304
1300
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 :
1305
1311
smaskObject = self .reserveObject ("smask" )
1306
1312
self .beginStream (
1307
1313
smaskObject .id ,
@@ -1312,17 +1318,16 @@ def writeImages(self):
1312
1318
# TODO: predictors (i.e., output png)
1313
1319
self .currentstream .write (adata )
1314
1320
self .endStream ()
1321
+ obj ['SMask' ] = smaskObject
1315
1322
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 ()
1326
1331
1327
1332
def markerObject (self , path , trans , fillp , strokep , lw , joinstyle ,
1328
1333
capstyle ):
0 commit comments