4242from matplotlib .transforms import Affine2D
4343
4444
45+ # Cairo's image buffers are premultiplied ARGB32,
46+ # Matplotlib's are unmultiplied RGBA8888.
47+
48+
4549def _premultiplied_argb32_to_unmultiplied_rgba8888 (buf ):
4650 """
4751 Convert a premultiplied ARGB32 buffer to an unmultiplied RGBA8888 buffer.
48-
49- Cairo uses the former format, Matplotlib the latter.
5052 """
5153 rgba = np .take ( # .take() ensures C-contiguity of the result.
5254 buf ,
@@ -62,6 +64,26 @@ def _premultiplied_argb32_to_unmultiplied_rgba8888(buf):
6264 return rgba
6365
6466
67+ def _unmultipled_rgba8888_to_premultiplied_argb32 (rgba8888 ):
68+ """
69+ Convert an unmultiplied RGBA8888 buffer to a premultiplied ARGB32 buffer.
70+ """
71+ if sys .byteorder == "little" :
72+ argb32 = np .take (rgba8888 , [2 , 1 , 0 , 3 ], axis = 2 )
73+ rgb24 = argb32 [..., :- 1 ]
74+ alpha8 = argb32 [..., - 1 :]
75+ else :
76+ argb32 = np .take (rgba8888 , [3 , 0 , 1 , 2 ], axis = 2 )
77+ alpha8 = argb32 [..., :1 ]
78+ rgb24 = argb32 [..., 1 :]
79+ # Only bother premultiplying when the alpha channel is not fully opaque,
80+ # as the cost is not negligible. The unsafe cast is needed to do the
81+ # multiplication in-place in an integer buffer.
82+ if alpha8 .min () != 0xff :
83+ np .multiply (rgb24 , alpha8 / 0xff , out = rgb24 , casting = "unsafe" )
84+ return argb32
85+
86+
6587if cairo .__name__ == "cairocffi" :
6688 # Convert a pycairo context to a cairocffi one.
6789 def _to_context (ctx ):
@@ -358,11 +380,7 @@ def _draw_paths():
358380 _draw_paths ()
359381
360382 def draw_image (self , gc , x , y , im ):
361- # bbox - not currently used
362- if sys .byteorder == 'little' :
363- im = im [:, :, (2 , 1 , 0 , 3 )]
364- else :
365- im = im [:, :, (3 , 0 , 1 , 2 )]
383+ im = _unmultipled_rgba8888_to_premultiplied_argb32 (im [::- 1 ])
366384 surface = cairo .ImageSurface .create_for_data (
367385 im .ravel ().data , cairo .FORMAT_ARGB32 ,
368386 im .shape [1 ], im .shape [0 ], im .shape [1 ] * 4 )
@@ -371,10 +389,7 @@ def draw_image(self, gc, x, y, im):
371389
372390 ctx .save ()
373391 ctx .set_source_surface (surface , float (x ), float (y ))
374- if gc .get_alpha () != 1 :
375- ctx .paint_with_alpha (gc .get_alpha ())
376- else :
377- ctx .paint ()
392+ ctx .paint ()
378393 ctx .restore ()
379394
380395 def draw_text (self , gc , x , y , s , prop , angle , ismath = False , mtext = None ):
0 commit comments