Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/api/artist_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@

Artist.set_alpha
Artist.get_alpha
Artist.set_blend_mode
Artist.get_blend_mode
Artist.set_snap
Artist.get_snap
Artist.set_visible
Expand Down Expand Up @@ -200,4 +202,4 @@
getp
setp
kwdoc
ArtistInspector

Check warning on line 205 in doc/api/artist_api.rst

View workflow job for this annotation

GitHub Actions / sphinx

[sphinx] doc/api/artist_api.rst#L205

py:class reference target not found: matplotlib.axes._base._AxesBase [ref.class]
Raw output
doc/api/artist_api.rst:205: WARNING: py:class reference target not found: matplotlib.axes._base._AxesBase [ref.class]

Check warning on line 205 in doc/api/artist_api.rst

View workflow job for this annotation

GitHub Actions / sphinx

[sphinx] doc/api/artist_api.rst#L205

py:class reference target not found: matplotlib.image._ImageBase [ref.class]
Raw output
doc/api/artist_api.rst:205: WARNING: py:class reference target not found: matplotlib.image._ImageBase [ref.class]

Check warning on line 205 in doc/api/artist_api.rst

View workflow job for this annotation

GitHub Actions / sphinx

[sphinx] doc/api/artist_api.rst#L205

py:class reference target not found: matplotlib.text._AnnotationBase [ref.class]
Raw output
doc/api/artist_api.rst:205: WARNING: py:class reference target not found: matplotlib.text._AnnotationBase [ref.class]
13 changes: 13 additions & 0 deletions doc/release/next_whats_new/blend_modes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Blending and compositing artists
--------------------------------

There are now alternative options for blending and compositing artists on top
of previously drawn artists, instead of the normal alpha blending. The
behavior is controlled by the artist's ``blend_mode`` property. See
:ref:`blend-modes` for a gallery and for a table of supporting backends.

Furthermore, there is support for blend groups, also known as transparency
groups, which can be isolated, knockout, or both. For example, isolated blend
groups allow multiple artists to be rendered together in a separate buffer,
which is subsequently blended into the primary buffer. See
:ref:`blend-groups` for more details and for a table of supporting backends.
2 changes: 1 addition & 1 deletion doc/sphinxext/gallery_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def __call__(self, item):
# text
"text_intro", "text_props",
# colors
"colors",
"colors", "blend_modes", "blend_groups",

# **Examples**
# animation
Expand Down
118 changes: 118 additions & 0 deletions extern/agg24-svn/include/agg_color_rgba.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,124 @@ namespace agg
*this = from_wavelength(wavelen, gamma);
}

#ifdef MPL_ADD_AGG_HSL_BLEND_MODES
// The following functions are used for the non-separable blend modes

double max_rgb() const
{
double max_rg = ((r > g) ? r : g);
return (max_rg > b) ? max_rg : b;
}

double min_rgb() const
{
double min_rg = ((r < g) ? r : g);
return (min_rg < b) ? min_rg : b;
}

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

rgba& clip_color()
{
double L = luminosity();
double N = min_rgb();
double X = max_rgb();
if (N < 0.)
{
r = L + (((r - L) * L) / (L - N));
g = L + (((g - L) * L) / (L - N));
b = L + (((b - L) * L) / (L - N));
}
if (X > 1.)
{
r = L + (((r - L) * (1 - L)) / (X - L));
g = L + (((g - L) * (1 - L)) / (X - L));
b = L + (((b - L) * (1 - L)) / (X - L));
}
return *this;
}

rgba& set_luminosity(double L)
{
double D = L - luminosity();
r += D;
g += D;
b += D;
return clip_color();
}

double saturation() const
{
return max_rgb() - min_rgb();
}

rgba& set_saturation(double S)
{
double *cmin, *cmid, *cmax;
if (r <= g)
{
if (g <= b)
{
cmin = &r;
cmid = &g;
cmax = &b;
}
else
{
cmax = &g;
if (r <= b)
{
cmin = &r;
cmid = &b;
}
else
{
cmin = &b;
cmid = &r;
}
}
}
else
{
if (r <= b)
{
cmin = &g;
cmid = &r;
cmax = &b;
}
else
{
cmax = &r;
if (g <= b)
{
cmin = &g;
cmid = &b;
}
else
{
cmin = &b;
cmid = &g;
}
}
}
if (*cmax > *cmin)
{
*cmid = ((*cmid - *cmin) * S) / (*cmax - *cmin);
*cmax = S;
}
else
{
*cmid = 0;
*cmax = 0;
}
*cmin = 0;
return *this;
}
#endif

};

inline rgba operator+(const rgba& a, const rgba& b)
Expand Down
107 changes: 107 additions & 0 deletions extern/agg24-svn/include/agg_pixfmt_rgba.h
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,98 @@ namespace agg
};
#endif

#ifdef MPL_ADD_AGG_HSL_BLEND_MODES
// These four blend modes are implemented per the PDF specification

//=====================================================comp_op_rgba_hsl_hue
template<class ColorT, class Order>
struct comp_op_rgba_hsl_hue : blender_base<ColorT, Order>
{
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
using blender_base<ColorT, Order>::get;
using blender_base<ColorT, Order>::set;

static AGG_INLINE void blend_pix(value_type* p,
value_type r, value_type g, value_type b, value_type a, cover_type cover)
{
rgba s = get(r, g, b, a, cover).demultiply();
rgba d = get(p).demultiply();
rgba blend = rgba(s);
blend.set_saturation(d.saturation()).set_luminosity(d.luminosity());
rgba comp = s * s.a * (1 - d.a) + blend * s.a * d.a + d * (1 - s.a) * d.a;
comp.a = s.a + d.a - s.a * d.a;
set(p, comp);
}
};

//=====================================================comp_op_rgba_hsl_saturation
template<class ColorT, class Order>
struct comp_op_rgba_hsl_saturation : blender_base<ColorT, Order>
{
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
using blender_base<ColorT, Order>::get;
using blender_base<ColorT, Order>::set;

static AGG_INLINE void blend_pix(value_type* p,
value_type r, value_type g, value_type b, value_type a, cover_type cover)
{
rgba s = get(r, g, b, a, cover).demultiply();
rgba d = get(p).demultiply();
rgba blend = rgba(d);
blend.set_saturation(s.saturation()).set_luminosity(d.luminosity());
rgba comp = s * s.a * (1 - d.a) + blend * s.a * d.a + d * (1 - s.a) * d.a;
comp.a = s.a + d.a - s.a * d.a;
set(p, comp);
}
};

//=====================================================comp_op_rgba_hsl_color
template<class ColorT, class Order>
struct comp_op_rgba_hsl_color : blender_base<ColorT, Order>
{
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
using blender_base<ColorT, Order>::get;
using blender_base<ColorT, Order>::set;

static AGG_INLINE void blend_pix(value_type* p,
value_type r, value_type g, value_type b, value_type a, cover_type cover)
{
rgba s = get(r, g, b, a, cover).demultiply();
rgba d = get(p).demultiply();
rgba blend = rgba(s);
blend.set_luminosity(d.luminosity());
rgba comp = s * s.a * (1 - d.a) + blend * s.a * d.a + d * (1 - s.a) * d.a;
comp.a = s.a + d.a - s.a * d.a;
set(p, comp);
}
};

//=====================================================comp_op_rgba_hsl_luminosity
template<class ColorT, class Order>
struct comp_op_rgba_hsl_luminosity : blender_base<ColorT, Order>
{
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
using blender_base<ColorT, Order>::get;
using blender_base<ColorT, Order>::set;

static AGG_INLINE void blend_pix(value_type* p,
value_type r, value_type g, value_type b, value_type a, cover_type cover)
{
rgba s = get(r, g, b, a, cover).demultiply();
rgba d = get(p).demultiply();
rgba blend = rgba(d);
blend.set_luminosity(s.luminosity());
rgba comp = s * s.a * (1 - d.a) + blend * s.a * d.a + d * (1 - s.a) * d.a;
comp.a = s.a + d.a - s.a * d.a;
set(p, comp);
}
};
#endif


//======================================================comp_op_table_rgba
template<class ColorT, class Order> struct comp_op_table_rgba
Expand Down Expand Up @@ -1207,6 +1299,14 @@ namespace agg
//comp_op_rgba_contrast <ColorT,Order>::blend_pix,
//comp_op_rgba_invert <ColorT,Order>::blend_pix,
//comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix,

#ifdef MPL_ADD_AGG_HSL_BLEND_MODES
comp_op_rgba_hsl_hue <ColorT,Order>::blend_pix,
comp_op_rgba_hsl_saturation <ColorT,Order>::blend_pix,
comp_op_rgba_hsl_color <ColorT,Order>::blend_pix,
comp_op_rgba_hsl_luminosity <ColorT,Order>::blend_pix,
#endif

0
};

Expand Down Expand Up @@ -1243,6 +1343,13 @@ namespace agg
//comp_op_invert, //----comp_op_invert
//comp_op_invert_rgb, //----comp_op_invert_rgb

#ifdef MPL_ADD_AGG_HSL_BLEND_MODES
comp_op_hsl_hue,
comp_op_hsl_saturation,
comp_op_hsl_color,
comp_op_hsl_luminosity,
#endif

end_of_comp_op_e
};

Expand Down
1 change: 1 addition & 0 deletions galleries/users_explain/artists/artist_intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ We can interrogate the full list of settable properties with
animated = False
antialiased or aa = True
bbox = Bbox(x0=0.004013842290585101, y0=0.013914221641967...
blend_mode = normal
children = []
clip_box = TransformedBbox( Bbox(x0=0.0, y0=0.0, x1=1.0, ...
clip_on = True
Expand Down
9 changes: 5 additions & 4 deletions galleries/users_explain/colors/GALLERY_HEADER.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
Colors
------

Matplotlib has support for visualizing information with a wide array
of colors and colormaps. These tutorials cover the basics of how
these colormaps look, how you can create your own, and how you can
customize colormaps for your use case.
Matplotlib has support for visualizing information with a wide array of colors
and colormaps. The color tutorials cover the basics of specifying colors, as
well as the range of options for blending the colors of overlapping artists.
The colormap tutorials cover the basics of how colormaps look, how you can
create your own, and how you can customize colormaps for your use case.

For even more information see the :ref:`examples page <color_examples>`.
Loading
Loading