Skip to content

Add blend modes and blend groups for compositing#31162

Open
ayshih wants to merge 13 commits into
matplotlib:mainfrom
ayshih:agg_compositing
Open

Add blend modes and blend groups for compositing#31162
ayshih wants to merge 13 commits into
matplotlib:mainfrom
ayshih:agg_compositing

Conversation

@ayshih

@ayshih ayshih commented Feb 15, 2026

Copy link
Copy Markdown
Contributor

PR summary

This PR adds support for blend modes beyond alpha blending (e.g., "screen" or "hard light"), so closes #6210. With this PR, all artists can specify blend_mode, and they are supported by Agg-based and Cairo-based backends, and mostly supported by SVG/PDF/PGF backends.

Of course, mplcairo provides access to these blend modes, but this PR provides blend-mode support without needing cairo.

Update: This PR uses this functionality to fix a long-standing bug (e.g., fixes #27016) with Agg rendering of Gouraud shading, where the edges of triangles would become visible when transparency is involved.

Update: This PR adds support for blend groups, which can be isolated, knockout, or both.


✅ = supported, 🟡 = supported through rasterization, ❌ = not supported

Blend modes Agg Cairo SVG PDF PGF PS
normal
multiply, screen, overlay, darken, lighten,
color dodge, color burn, hard light, soft light,
difference, exclusion
🟡
hue, saturation, color, luminosity ✅* 🟡
knockout, erase, clear, atop, xor, plus 🟡 🟡 🟡 🟡
  • "normal" is the normal alpha blending (also known as "over" or "source over")
  • "multiply" through "exclusion" are separable blend modes (color channels are independent)
  • "hue" through "luminosity" are non-separable blend modes
  • "knockout" through "plus" are Porter Duff compositing operators, where "knockout" is also known as "source" and "erase" is also known as "destination out"
  • * Text artists disappear on some combinations of Cairo version and platform, likely a Cairo bug
Blend groups Agg Cairo SVG PDF PGF PS
neither isolated nor knockout (same as no group)
isolated only 🟡
isolated and knockout 🟡 🟡
knockout only

Agg showcase

  • Gouraud shading can look wrong with some blend modes, for the same reason it can look wrong under normal blend mode when alpha < 1, due to overlapping triangles Now fixed
agg

Cairo showcase

  • With some combinations of Cairo version and platform, text is missing in non-separable blend modes, which is presumably a bug in Cairo
  • Gouraud shading is apparently not supported by the Cairo backend, so I commented out the pcolormesh call I added support for Gouraud shading

Windows

cairo

macOS

blend_modes_cairo_macos

SVG showcase

  • These results may not render as intended depending on the SVG renderer (try non-mobile web browsers)
  • The Porter Duff compositing operators normally use a different mechanism to command the renderer, which is inaccessible through SVG XML, so are currently disabled (and fall back to "normal" with a warning)

Figure_1

PDF showcase

  • I haven't figured out how to implement the Porter Duff compositing operators

Figure_1.pdf

PGF showcase

  • The PGF and PGF->PDF output looks fine, but the PGF->PNG output via pdftocairo (on Windows) appears to screw up some colors for the non-separable blend modes
  • Gouraud shading is apparently not supported by the PGF backend, so I commented out the pcolormesh call
  • No Porter Duff compositing operators yet again

Figure_1.pgf.pdf

Generating code

import matplotlib
#matplotlib.use('TkCairo')

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Rectangle

N = 10
data = np.arange(N**2).reshape((N, N)) % (N-1)

fig, axs = plt.subplots(3, 8, figsize=(10, 5.5), layout="tight")
axs = axs.flatten()
fig.set_facecolor("none")

blend_modes = ["normal", "multiply", "screen", "overlay",
               "darken", "lighten", "color dodge", "color burn",
               "hard light", "soft light", "difference", "exclusion",
               "hue", "saturation", "color", "luminosity",
               "knockout", "erase", "clear", "atop", "xor", "plus"]

for ax in axs:
    ax.set_facecolor("none")
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 1.2)
    ax.set_axis_off()

for i, blend_mode in enumerate(blend_modes):
    axs[i].imshow(data, cmap='Reds', alpha=0.75, extent=(0, 0.8, 0, 0.8))
    axs[i].imshow(data[::-1, :], cmap='Blues', alpha=0.75, extent=(0.2, 1, 0.4, 1.2),
                  blend_mode=blend_mode)
    axs[i].pcolormesh(*np.meshgrid(np.linspace(0.6, 0.9, 5), np.linspace(0.7, 1, 5)),
                      data[:5, :5], cmap='Spectral', alpha=0.75, shading='gouraud',
                      blend_mode=blend_mode)
    axs[i].text(0.05, 0.15, "Horizontal", weight="bold", color="c",
                blend_mode=blend_mode)
    axs[i].text(0.35, 0.10, "Tilted", weight="bold", color="m", rotation=45,
                blend_mode=blend_mode)
    axs[i].plot([0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2], [0.7, 0.8, 0.9, 1, 0.7, 0.8, 0.9, 1],
                'p', markersize=15, markeredgecolor="orange", markerfacecolor="purple", alpha=0.75,
                blend_mode=blend_mode)
    axs[i].plot([0, 1], [1.2, 0], color="y",
                blend_mode=blend_mode)
    circ = Circle((.65, 0.5), .3, facecolor='g', alpha=0.5,
                  blend_mode=blend_mode, zorder=2)
    axs[i].add_artist(circ)

    rect = Rectangle((0, 1.2), 1, .3, facecolor='lightgray', clip_on=False)
    axs[i].add_artist(rect)
    axs[i].set_title(blend_mode)

plt.show()

Put off to future work:

  • Change the way pcolormesh.snap behaves when the mesh edges are not horizontal/vertical
  • Change the default antialiasing behavior of contourf()/pcolor()/pcolormesh() to be True
  • Agg: investigate alpha edge around Gouraud shading

PR checklist

@ayshih ayshih changed the title WIP: Add blend modes for compositing, supported by Agg backend WIP: Add blend modes for compositing, supported by Agg-based backends Feb 15, 2026
@github-actions github-actions Bot added topic: mpl_toolkit Documentation: API files in lib/ and doc/api labels Feb 15, 2026
@timhoffm

Copy link
Copy Markdown
Member

This looks interesting. Thanks for working on it.

Since I’m not into the topic I can dare to ask the stupid questions:

  • Is it correct that an Artist and its blend mode define completely how they blend with “the background” I.e. all previously drawn artists? In particular, this does not depend on the blend mode of the other artists.
  • Are all these blend modes parameter-less?

@ayshih

ayshih commented Feb 15, 2026

Copy link
Copy Markdown
Contributor Author
  • Is it correct that an Artist and its blend mode define completely how they blend with “the background” I.e. all previously drawn artists? In particular, this does not depend on the blend mode of the other artists.

Yup, that is correct: the history of how that "background" was constructed has no bearing on how the next Artist is blended in using its specific blend mode.

It's also important to remember that that the "empty" background of an Axes is solid white, and thus not actually empty as far as these blend modes are concerned. For example, using "screen" to blend in an image on a truly empty background will just return the image, but on a white background will return solid white, which can make it look instead like the image call failed. That's why I turn off the face colors in my example above.

What I still need to investigate is how my changes interact with collections of Artists. A user may want "over" blending (the default) within the collection before using a different blend mode for the collection as a whole.

  • Are all these blend modes parameter-less?

Yes. In principle, the transformation functions for the hue/saturation/color/luminosity operators could have more than one possibility, but in practice I think everyone has simply used the same functions for decades (as defined in the PDF specification).

@ayshih ayshih force-pushed the agg_compositing branch 2 times, most recently from 2221d69 to 6d49bcf Compare February 16, 2026 04:43
Comment thread lib/matplotlib/artist.py Outdated
@anntzer

anntzer commented Feb 16, 2026

Copy link
Copy Markdown
Contributor

This is pretty cool :-)

It's also important to remember that that the "empty" background of an Axes is solid white, and thus not actually empty as far as these blend modes are concerned. For example, using "screen" to blend in an image on a truly empty background will just return the image, but on a white background will return solid white, which can make it look instead like the image call failed. That's why I turn off the face colors in my example above.

What I still need to investigate is how my changes interact with collections of Artists. A user may want "over" blending (the default) within the collection before using a different blend mode for the collection as a whole.

Actually I suspect that another possibility is to want some nonstandard blending between multiple artists, then "over" blending of the result over the background.

In general I suspect this would be related to adding support for temporary, intermediate rendering buffers, which is also something that would be useful for other purposes e.g. contour label overplotting (#26971 (comment)).

@ayshih

ayshih commented Feb 16, 2026

Copy link
Copy Markdown
Contributor Author

By the way, I decided to rename "over" to "normal". That mode of blending is referred to as "normal" often enough, and it makes it readily apparent to users that it is the standard choice (and the default).

@ayshih ayshih force-pushed the agg_compositing branch 4 times, most recently from f49e8d0 to f7af1e4 Compare February 17, 2026 14:15
@ayshih ayshih changed the title WIP: Add blend modes for compositing, supported by Agg-based backends WIP: Add blend modes for compositing, fully supported by Agg backend and mostly supported by others Feb 17, 2026
@ayshih ayshih changed the title WIP: Add blend modes for compositing, fully supported by Agg backend and mostly supported by others WIP: Add blend modes for compositing, fully supported by Agg backends and mostly supported by other major backends Feb 17, 2026
@ayshih

ayshih commented Mar 6, 2026

Copy link
Copy Markdown
Contributor Author

Yeah, I think you're right on not putting in a warning. The false positive of emitting a warning when someone legitimately wants to name an SVG group something totally reasonable like "overlay" is not worth mitigating the hypothetical confusion of someone mistakenly calling open_group() instead of open_blend_group(). When the group isn't blending as they desire, hopefully they pull up the docstring on the method they are calling and that will immediately reveal the error to them.

@ayshih

ayshih commented Mar 9, 2026

Copy link
Copy Markdown
Contributor Author

I've implemented two more Porter-Duff compositing operators – "source" and "clear" – for both Agg and Cairo backends, but I think "source" is too confusing of a name. Since "source" provides the similar behavior as a knockout group, I have renamed it "knockout" for blend_mode.

@ayshih

ayshih commented Mar 10, 2026

Copy link
Copy Markdown
Contributor Author

I've now implemented that a blend group can be an isolated group, a knockout group, both, or neither. Isolated groups are supported by all non-PS backends. Knockout groups are fully supported by only the PDF and PGF backends and partially supported by Agg and Cairo backends (cannot do non-isolated and knockout at the same time). If a knockout group is specified and the backend does not support it, the group will be rendered as non-knockout (in the images below, the panel on the right falls back to the panel to the left).

Blend groups Agg Cairo SVG PDF PGF PS
isolated only
isolated and knockout
knockout only

Agg

Top-right panel is not supported
bg_agg

Cairo

Top-right panel is not supported
bg_cairo

SVG

Right column is not supported
bg

PDF

All supported
bg.pdf

PGF

All supported
bg.pgf.pdf

Generating code

import matplotlib
#matplotlib.use('TkCairo')

import numpy as np

import matplotlib.pyplot as plt
from matplotlib.artist import Artist
from matplotlib.patches import Circle

class ArtistGroup(Artist):
    def __init__(self, artist_list, *, group_blend_mode=None, group_alpha=1, knockout=False):
        self._artist_list = artist_list
        self._group_blend_mode = group_blend_mode
        self._group_alpha = group_alpha
        self._knockout = knockout
        super().__init__()

    def draw(self, renderer):
        renderer.open_blend_group(self._group_blend_mode, alpha=self._group_alpha, knockout=self._knockout)
        for a in self._artist_list:
            if not a.is_transform_set():
                a.set_transform(self.get_transform())
            a.draw(renderer)
        renderer.close_blend_group()


fig, axs = plt.subplots(2, 2, figsize=(6, 6), layout='constrained')
fig.set_facecolor("none")

for i, group_blend_mode in enumerate([None, "normal"]):
    for j, knockout in enumerate([False, True]):
        axs[i, j].set_facecolor("none")
        axs[i, j].set_xlim(-1, 1)
        axs[i, j].set_ylim(-1, 1)
        axs[i, j].set_aspect("equal")

        axs[i, j].imshow(np.arange(20*20).reshape((20, 20)) % 19,
                      cmap='Spectral', extent=[-1, 1, -1, 1])

        left = Circle((-0.25, 0), 0.6, fc='c', alpha=0.75, blend_mode='multiply')
        right = Circle((0.25, 0), 0.6, fc='m', alpha=0.75, blend_mode='multiply')

        both = ArtistGroup([left, right], group_blend_mode=group_blend_mode, knockout=knockout)
        axs[i, j].add_artist(both)

axs[0, 0].set_title('non-knockout')
axs[0, 1].set_title('knockout')
axs[0, 0].set_ylabel('non-isolated')
axs[1, 0].set_ylabel('isolated')

plt.show()

@ayshih

ayshih commented Mar 12, 2026

Copy link
Copy Markdown
Contributor Author

Update: Now reverted, but I put the function at the bottom of this post in case someone in the future wants to give this approach another try

I had been hoping to use the blend modes and blend groups to fix the issue of visible grid lines of pcolormesh with the PDF backend, as worked so well for the Agg/Cairo backends (#31162 (comment)). However, nothing in that vein really panned out. Instead, an approach that works is to implement a RendererPdf.draw_quad_mesh() that takes advantage of the fact that the existing draw_gouraud_triangles() code already specifies each Gouraud triangle in a disconnected fashion, even for adjacent triangles. So, draw_quad_mesh() creates a Gouraud mesh where each triangle is flat in color and adjacent triangles can have different colors even at shared vertices.

I will actually likely revert this change because the alignment and edge aliasing is worse with this change, but it does get rid of the visible grid lines.

Before this PR

Figure_1-before.pdf

After this PR

Figure_1-after.pdf


Preserving the attempt for posterity:

    def draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight,
                       coordinates, offsets, offsetTrans, facecolors,
                       antialiased, edgecolors):
        # Use the fallback drawing of each quad as a path if edges are stroked
        if (edgecolors.size != 0 and edgecolors[0][3] != 0):
            super().draw_quad_mesh(gc, master_transform, meshWidth, meshHeight,
                                   coordinates, offsets, offsetTrans, facecolors,
                                   antialiased, edgecolors)
            return

        # Otherwise, leverage the Gouraud code path with each triangle having
        # three vertices of the same color, but common vertices of adjacent
        # triangles can have different colors

        if isinstance(coordinates, np.ma.MaskedArray):
            p = coordinates.data
        else:
            p = coordinates

        # TODO: adjust for offsets and offsetTrans

        p_a = p[:-1, :-1]
        p_b = p[:-1, 1:]
        p_c = p[1:, 1:]
        p_d = p[1:, :-1]
        triangles = np.concatenate([
            p_a, p_b, p_c,
            p_c, p_a, p_d,
        ], axis=2).reshape((-1, 3, 2))

        colors = np.repeat(facecolors, 6, axis=0).reshape((-1, 3, 4))
        empty = (colors[:, 0, 3] == 0)

        self.draw_gouraud_triangles(gc, triangles[~empty], colors[~empty],
                                    master_transform)

@ayshih

ayshih commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

Ugh, trying to have a Cairo figure test is a disaster.

The Cairo bug with missing text is not limited to Windows, but I don't have a handle on the common thread (and there may be multiple issues at play).

From the CI:

Platform libcairo pycairo Works
Ubuntu 22.04 1.16.0 (via apt) 1.29.0
Ubuntu 24.04 1.18.0 (via apt) 1.29.0
macOS arm64 1.18.4 (via apt?) 1.29.0

From my own machines:

Platform libcairo pycairo Works
macOS x86_64 1.18.4 (via conda-forge) 1.29.0
Windows 1.18.4 1.29.0

I have not yet tried to vary the installed versions, but I feel like there are other packages that matter or the precise way that cairo 1.18.4 was built matters.

Even setting aside the bug, the text is rendered slightly differently between the CI builds. And even ignoring all text-related discrepancies, the blending is a bit different on the edges between the macOS ARM builds and the Ubuntu builds. The three categories of builds are running different versions of libcairo, so the blending differences might be due to that, but that still inhibits a common image test.

Image diff between Ubuntu 22.04 and Ubuntu 24.04
blend_modes_cairo-failed-diff
Image diff between Ubuntu 22.04 and macOS arm64
blend_modes_cairo-failed-diff

@anntzer

anntzer commented May 7, 2026

Copy link
Copy Markdown
Contributor

I didn't know, but am not really surprised that cairo's exact rendering depends on the details of the build. Looks like the difference is mostly related to antialiasing, i.e. the colors in the "middle" of the overlaying patches still match, so perhaps 1) disabling antialiasing throughout may help (set_antialias(False) on the patches)?, or 2) instead of an image comparison test, the test could be to draw two partially overlapping squares, then extract the rgba buffer and simply test the rgba values for a pixel in the middle of the first square, for a pixel in the middle of the second square, and for a pixel in the overlaying region.
(Getting texts to match across versions is pretty much hopeless (I don't know if cairo picks up matplotlib's forced freetype version -- likely not?) and I would just get rid of them in the test images.)

@ayshih

ayshih commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

Here is how I have decided to resolve the Cairo image test:

  • Remove all text from the test image generated for Cairo. All other backends continue to test text.
  • Use the macOS arm64 output as the reference image (zero tolerance) because it is the only category of CI builds that actually install the latest version of cairo (1.18.4)
  • For the CI builds that run an older version of cairo (i.e., 1.16.0 or 1.18.0 running on Ubuntu), the non-text rendering discrepancies smell like bugs in Cairo rendering prior to 1.18.4, so I bump the tolerance up to 3 to account for them, and I think 3 is still low enough to be somewhat useful. For comparison the rendering difference when text is on the image is >18.

@ayshih

ayshih commented May 8, 2026

Copy link
Copy Markdown
Contributor Author

This PR is ready for comprehensive review! The remaining open question in my mind is whether the helper ArtistGroup class that I define on the documentation page for blend groups is appropriate and robust enough to live in the library proper. But, that decision could also be put off until the blend-group functionality has been out in the wild for a while.

Here's an example of using the "screen" blend mode to composite two images of the Sun at different wavelengths (171 angstroms in yellow, 211 angstroms in purple):
example

@story645

Copy link
Copy Markdown
Member

call nit about docs: Can you combine the examples into a "blending alpha" user guide entry under color. Alpha is introduced in the colors explanation so I think goes under the "colors" category.

@ayshih

ayshih commented May 15, 2026

Copy link
Copy Markdown
Contributor Author

I have relocated the two documentation pages to under "Colors" in the user guide, and linked to the blend-modes page from the existing description of normal alpha blending.

Also, the conclusion at yesterday's dev meeting was that – for this PR – the helper class (ArtistGroup) can live on just the documentation page rather than being moved to the library proper. The thinking is that there ought to be a future discussion of the requirements and design of a fully realized "compound artist" class, and how that may intersect with or replace the existing Container class, but that is all beyond the scope of this PR.

@ayshih

ayshih commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

As a nudge for reviewer attention on this PR, I'll point out that the added documentation page for blend modes now starts with this simple example to illustrate the benefit of non-normal blending:

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots(figsize=(6, 3), layout='constrained')

ax.text(1.5, 1.3, '"normal" blend mode', ha='center')
ax.add_patch(Circle((1, 0), 1, color='c', ec='none'))
ax.add_patch(Circle((2, 0), 1, color='m', ec='none'))
ax.add_patch(Circle((1.5, -0.87), 1, color='y', ec='none'))

ax.text(5.5, 1.3, '"multiply" blend mode', ha='center')
ax.add_patch(Circle((5, 0), 1, color='c', ec='none', blend_mode='multiply'))
ax.add_patch(Circle((6, 0), 1, color='m', ec='none', blend_mode='multiply'))
ax.add_patch(Circle((5.5, -0.87), 1, color='y', ec='none', blend_mode='multiply'))

ax.set_xlim(-0.2, 7.2)
ax.set_ylim(-1.9, 1.2)
ax.set_aspect('equal')
ax.axis('off')
sphx_glr_blend_modes_001

@tacaswell

Copy link
Copy Markdown
Member

I am 👍🏻 on this conceptually but have not reviewed the code.

@ayshih

ayshih commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

I've confirmed: if a blending use case is not supported by a vector backend but is supported by the Agg backend, then turning on rasterization can be a workaround assuming that the fixed resolution of the output is acceptable. This even works for the PS backend as long as alpha is 1 everywhere.

This means the support tables could be written as:

Blend modes Agg Cairo SVG PDF PGF PS
normal
multiply, screen, overlay, darken, lighten,
color dodge, color burn, hard light, soft light,
difference, exclusion
🟡
hue, saturation, color, luminosity 🟡
knockout, erase, clear, atop, xor, plus 🟡 🟡 🟡 🟡
Blend groups Agg Cairo SVG PDF PGF PS
neither isolated nor knockout (same as no group)
isolated only 🟡
isolated and knockout 🟡 🟡
knockout only

✅ = supported, 🟡 = supported through rasterization, ❌ = not supported

@ayshih

ayshih commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Updates over the past two weeks:

  • In the documentation, I now discuss rasterization as an option to achieve blending results that are not natively supported by the particular vector backend, which greatly reduces the number of ❌ in the support tables. I also added figure tests for rasterization.
  • I chose better colors for the blend-groups documentation so that it is easier to see the differences between the options.
  • For non-isolated knockout blend groups (which not supported in general by Agg, which is a problem for the rendered documentation), I now show a workaround that can be used for Agg – and hence can be shown in the rendered documentation – if all the artists in the group have the same blend mode.
  • Buried in the thread above, I noted that sometimes the edges of two adjacent contour regions are not exactly coincident. I tracked that down to a snapping-related bug that is fixed by Fix a bug of ignoring the closing path segment when automatically determining whether to snap #32018.

@story645 story645 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So big picture is this is fantastic and thank you for all the work and sticking with it.

While reviewing the C++, I was struggling a bit with which formulas each section is implementing. Can you add some comments in the C++ with short forms of the formulas you're implementing? I tried to use copilot and searching for some of them, but was a bit muddled, and I think adding the formulas will make it easier to make sure things stay in sync.

Not sure where to add it, but the note about how "not supported" means "no easy path to implementation. Which in hindsight, this PR would probably be easier to review if it was broken out by backend - feature comes in w/ agg/cairo, then pdf/pgf, then svg. And I mentioned this in the review comments too, but l think this pr is so large and indepth that the motivating examples of antialiasing and gourard(sp?) triangles should be pushed out into their own prs b/c they require additional context on top of this PR.

Also I think all of this should get a giant provisional flag for now? attn @timhoffm

Comment on lines +4 to +5
There are now alternative options for blending and compositing artists on top
of previously drawn artists, instead of the normal alpha blending. The

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
There are now alternative options for blending and compositing artists on top
of previously drawn artists, instead of the normal alpha blending. The
There are now alternative options, to normal alpha blending, for blending and compositing artists on top of previously drawn artists. The

I dunno that I like my suggestion either, but this sentence feels a bit wonky


double luminosity() const
{
return 0.3*r + 0.59*g + 0.11*b;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you cite where these coefficients come from?

Comment on lines +204 to +205
double N = min_rgb();
double X = max_rgb();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
double N = min_rgb();
double X = max_rgb();
double min = min_rgb();
double max = max_rgb();

something that I think makes it easier to follow through that this is a basic rescaling?

rgba& set_saturation(double S)
{
double *cmin, *cmid, *cmax;
if (r <= g)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you don't need to keep track of which color is min,mid,max, can you just use a sort function? Or is it not efficient?

}
if (*cmax > *cmin)
{
*cmid = ((*cmid - *cmin) * S) / (*cmax - *cmin);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you leave a comment here about what this is for - AI says to rescale the median color?

Comment thread lib/matplotlib/image.py
for a in artists:
if (isinstance(a, _ImageBase) and a.can_composite() and
a.get_clip_on() and not a.get_clip_path()):
a.get_clip_on() and not a.get_clip_path() and

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so any non normal blend mode should trigger a draw?

Comment thread src/agg_workaround.h
if(alpha == 0) return;

// The following code does not accurately transform to higher bit depth
// TODO: Improve the accuracy of this code when we are prepared to regenerate all baseline images

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be converted to an issue when this pr gets merged?

cairo_version = None


def plot_blend_mode_gallery(text=True, gouraud=True, rasterize=False):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this cause you can't parameterize image comparison tests?

renderer.close_blend_group()


def plot_blend_group_types(rasterize=False):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question about paramterization

axs[i].set_title(blend_mode)


class ArtistGroup(Artist):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this seems silly, but can you add a test of your testing helper? that artist group properly groups?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: diagonal lines in pcolormesh with Gouraud shading and transparency Alternative compositing methods

5 participants