@@ -496,37 +496,40 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
496496 out_alpha *= _resample (self , alpha , out_shape , t , resample = True )
497497 # mask and run through the norm
498498 resampled_masked = np .ma .masked_array (A_resampled , out_mask )
499- output = self .norm (resampled_masked )
499+ res = self .norm (resampled_masked )
500500 else :
501501 if A .ndim == 2 : # interpolation_stage = 'rgba'
502502 self .norm .autoscale_None (A )
503503 A = self .to_rgba (A )
504+ if A .dtype == np .uint8 :
505+ # uint8 is too imprecise for premultiplied alpha roundtrips.
506+ A = np .divide (A , 0xff , dtype = np .float32 )
504507 alpha = self .get_alpha ()
508+ post_apply_alpha = False
505509 if alpha is None : # alpha parameter not specified
506510 if A .shape [2 ] == 3 : # image has no alpha channel
507- output_alpha = 255 if A .dtype == np .uint8 else 1.0
508- else :
509- output_alpha = _resample ( # resample alpha channel
510- self , A [..., 3 ], out_shape , t )
511- output = _resample ( # resample rgb channels
512- self , _rgb_to_rgba (A [..., :3 ]), out_shape , t )
511+ A = np .dstack ([A , np .ones (A .shape [:2 ])])
513512 elif np .ndim (alpha ) > 0 : # Array alpha
514513 # user-specified array alpha overrides the existing alpha channel
515- output_alpha = _resample (self , alpha , out_shape , t )
516- output = _resample (
517- self , _rgb_to_rgba (A [..., :3 ]), out_shape , t )
514+ A = np .dstack ([A [..., :3 ], alpha ])
518515 else : # Scalar alpha
519516 if A .shape [2 ] == 3 : # broadcast scalar alpha
520- output_alpha = ( 255 * alpha ) if A . dtype == np .uint8 else alpha
517+ A = np . dstack ([ A , np . full ( A . shape [: 2 ], alpha , np .float32 )])
521518 else : # or apply scalar alpha to existing alpha channel
522- output_alpha = _resample (self , A [..., 3 ], out_shape , t ) * alpha
523- output = _resample (
524- self , _rgb_to_rgba (A [..., :3 ]), out_shape , t )
525- output [..., 3 ] = output_alpha # recombine rgb and alpha
526-
527- # output is now either a 2D array of normed (int or float) data
519+ post_apply_alpha = True
520+ # Resample in premultiplied alpha space. (TODO: Consider
521+ # implementing premultiplied-space resampling in
522+ # span_image_resample_rgba_affine::generate?)
523+ A [..., :3 ] *= A [..., 3 :]
524+ res = _resample (self , A , out_shape , t )
525+ np .divide (res [..., :3 ], res [..., 3 :], out = res [..., :3 ],
526+ where = res [..., 3 :] != 0 )
527+ if post_apply_alpha :
528+ res [..., 3 ] *= alpha
529+
530+ # res is now either a 2D array of normed (int or float) data
528531 # or an RGBA array of re-sampled input
529- output = self .to_rgba (output , bytes = True , norm = False )
532+ output = self .to_rgba (res , bytes = True , norm = False )
530533 # output is now a correctly sized RGBA array of uint8
531534
532535 # Apply alpha *after* if the input was greyscale without a mask
0 commit comments