FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Fix cairo's image inversion and alpha misapplication. by anntzer · Pull Request #11724 · matplotlib/matplotlib · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (2) All 1 file type selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
37 changes: 26 additions & 11 deletions lib/matplotlib/backends/backend_cairo.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@
from matplotlib.transforms import Affine2D


# Cairo's image buffers are premultiplied ARGB32,
# Matplotlib's are unmultiplied RGBA8888.


def _premultiplied_argb32_to_unmultiplied_rgba8888(buf):
"""
Convert a premultiplied ARGB32 buffer to an unmultiplied RGBA8888 buffer.

Cairo uses the former format, Matplotlib the latter.
"""
rgba = np.take( # .take() ensures C-contiguity of the result.
buf,
Expand All @@ -62,6 +64,26 @@ def _premultiplied_argb32_to_unmultiplied_rgba8888(buf):
return rgba


def _unmultipled_rgba8888_to_premultiplied_argb32(rgba8888):
"""
Convert an unmultiplied RGBA8888 buffer to a premultiplied ARGB32 buffer.
"""
if sys.byteorder == "little":
argb32 = np.take(rgba8888, [2, 1, 0, 3], axis=2)
rgb24 = argb32[..., :-1]
alpha8 = argb32[..., -1:]
else:
argb32 = np.take(rgba8888, [3, 0, 1, 2], axis=2)
alpha8 = argb32[..., :1]
rgb24 = argb32[..., 1:]
# Only bother premultiplying when the alpha channel is not fully opaque,
# as the cost is not negligible. The unsafe cast is needed to do the
# multiplication in-place in an integer buffer.
if alpha8.min() != 0xff:
np.multiply(rgb24, alpha8 / 0xff, out=rgb24, casting="unsafe")
return argb32


if cairo.__name__ == "cairocffi":
# Convert a pycairo context to a cairocffi one.
def _to_context(ctx):
Expand Down Expand Up @@ -358,11 +380,7 @@ def _draw_paths():
_draw_paths()

def draw_image(self, gc, x, y, im):
# bbox - not currently used
if sys.byteorder == 'little':
im = im[:, :, (2, 1, 0, 3)]
else:
im = im[:, :, (3, 0, 1, 2)]
im = _unmultipled_rgba8888_to_premultiplied_argb32(im[::-1])
surface = cairo.ImageSurface.create_for_data(
im.ravel().data, cairo.FORMAT_ARGB32,
im.shape[1], im.shape[0], im.shape[1] * 4)
Expand All @@ -371,10 +389,7 @@ def draw_image(self, gc, x, y, im):

ctx.save()
ctx.set_source_surface(surface, float(x), float(y))
if gc.get_alpha() != 1:
ctx.paint_with_alpha(gc.get_alpha())
else:
ctx.paint()
ctx.paint()
ctx.restore()

def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
Expand Down
18 changes: 2 additions & 16 deletions lib/matplotlib/backends/backend_gtk3agg.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,8 @@ def on_draw_event(self, widget, ctx):
width = int(bbox.x1) - int(bbox.x0)
height = int(bbox.y1) - int(bbox.y0)

buf = (np.fromstring(self.copy_from_bbox(bbox).to_string_argb(),
dtype='uint8')
.reshape((width, height, 4)))
# cairo wants premultiplied alpha. Only bother doing the
# conversion when the alpha channel is not fully opaque, as the
# cost is not negligible. (The unsafe cast is needed to do the
# multiplication in-place in an integer buffer.)
if sys.byteorder == "little":
rgb24 = buf[..., :-1]
alpha8 = buf[..., -1:]
else:
alpha8 = buf[..., :1]
rgb24 = buf[..., 1:]
if alpha8.min() != 0xff:
np.multiply(rgb24, alpha8 / 0xff, out=rgb24, casting="unsafe")

buf = backend_cairo._unmultipled_rgba8888_to_premultiplied_argb32(
np.asarray(self.copy_from_bbox(bbox)))
image = cairo.ImageSurface.create_for_data(
buf.ravel().data, cairo.FORMAT_ARGB32, width, height)
ctx.set_source_surface(image, x, y)
Expand Down

Back | FazBrowse Home | New Git URL