Skip to content
Merged
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
3 changes: 3 additions & 0 deletions doc/api/artist_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ Drawing

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 @@ -211,3 +213,4 @@ Helper classes

ArtistInspector
ArtistList
BlendMode
1 change: 1 addition & 0 deletions doc/api/typing_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Color
Artist styles
=============

.. autodata:: matplotlib.typing.BlendModeType
.. autodata:: matplotlib.typing.LineStyleType
.. autodata:: matplotlib.typing.DrawStyleType
.. autodata:: matplotlib.typing.MarkEveryType
Expand Down
6 changes: 3 additions & 3 deletions doc/missing-references.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"doc/docstring of matplotlib.ft2font.pybind11_detail_function_record_v1_system_libstdcpp_gxx_abi_1xxx_use_cxx11_abi_1.set_text:1"
],
"matplotlib.axes._base._AxesBase": [
"doc/api/artist_api.rst:213"
"doc/api/artist_api.rst:216"
],
"matplotlib.backend_bases._Backend": [
"lib/matplotlib/backend_bases.py:docstring of matplotlib.backend_bases.ShowBase:1"
Expand All @@ -21,7 +21,7 @@
"lib/matplotlib/backends/backend_tkcairo.py:docstring of matplotlib.backends.backend_tkcairo.FigureCanvasTkCairo:1"
],
"matplotlib.image._ImageBase": [
"doc/api/artist_api.rst:213",
"doc/api/artist_api.rst:216",
"lib/matplotlib/image.py:docstring of matplotlib.image.AxesImage:1",
"lib/matplotlib/image.py:docstring of matplotlib.image.BboxImage:1",
"lib/matplotlib/image.py:docstring of matplotlib.image.FigureImage:1"
Expand Down Expand Up @@ -70,7 +70,7 @@
"lib/matplotlib/projections/geo.py:docstring of matplotlib.projections.geo.MollweideAxes.MollweideTransform:1"
],
"matplotlib.text._AnnotationBase": [
"doc/api/artist_api.rst:213",
"doc/api/artist_api.rst:216",
"lib/matplotlib/offsetbox.py:docstring of matplotlib.offsetbox.AnnotationBbox:1",
"lib/matplotlib/text.py:docstring of matplotlib.text.Annotation:1"
],
Expand Down
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
--------------------------------

In addition to normal alpha blending, there are now alternative options for
blending and compositing artists on top of previously drawn artists. 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.
98 changes: 98 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,104 @@ 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
// They are near-literal implementations of pseudocode provided in the
// PDF specification (e.g., pages 326-327 of the PDF 1.7 specification,
// https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf)

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;
Comment thread
story645 marked this conversation as resolved.
}

rgba& clip_color()
{
double L = luminosity();
double N = min_rgb();
double X = max_rgb();
Comment thread
story645 marked this conversation as resolved.
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();
}

// Helper method to get pointers to the min/mid/max color channels in that order
std::array<double*, 3> get_min_mid_max_pointers()
{
std::array<double*, 3> out = {&r, &g, &b};

// Do a bubble sort on the three pointers based on the values
if (*out[0] > *out[1])
{
std::swap(out[0], out[1]);
}
if (*out[1] > *out[2])
{
std::swap(out[1], out[2]);

// We need to perform the third check only if the second swap happened
if (*out[0] > *out[1])
{
std::swap(out[0], out[1]);
}
}
return out;
}

rgba& set_saturation(double S)
{
auto [cmin, cmid, cmax] = get_min_mid_max_pointers();
if (*cmax > *cmin)
{
*cmid = ((*cmid - *cmin) * S) / (*cmax - *cmin);
Comment thread
story645 marked this conversation as resolved.
*cmax = S;
}
else
{
*cmid = 0;
*cmax = 0;
}
*cmin = 0;
return *this;
}
#endif

};

inline rgba operator+(const rgba& a, const rgba& b)
Expand Down
111 changes: 111 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,102 @@ namespace agg
};
#endif

#ifdef MPL_ADD_AGG_HSL_BLEND_MODES
// These four blend modes are implemented per the PDF specification
Comment thread
ayshih marked this conversation as resolved.
// (e.g., pages 327-328 of Section 11.3.5 of the PDF 1.7 specification,
Comment thread
story645 marked this conversation as resolved.
// which is formally ISO 32000-1:2008, with a free version available at
// https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf)
Comment thread
ayshih marked this conversation as resolved.
// For the code below, the two colors have been renamed: C_s -> s and C_b -> d

//=====================================================comp_op_rgba_hsl_hue
template<class ColorT, class Order>
Comment thread
QuLogic marked this conversation as resolved.
struct comp_op_rgba_hsl_hue : blender_base<ColorT, Order>
Comment thread
story645 marked this conversation as resolved.
{
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 +1303,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 +1347,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