{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n# Blending and compositing artists\n\nWhen an artist is drawn on top of existing elements, the default behavior is for\nthe artist's colors to be blended with the colors underneath the artist using\n`alpha-based transparency `. An *alpha* value of 1\nnormally means that the underlying colors are completely hidden.\n\nAn example of an alternative to normal alpha blending is the\n[\"multiply\" blend mode](https://en.wikipedia.org/wiki/Blend_modes#Multiply)_,\nwhere the RGB channel values (in the range [0, 1]) of the artist colors and the\nunderlying colors are multiplied together. For this blend mode, the underlying\ncolors can still affect the final color even when the *alpha* value is 1.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nfrom matplotlib.patches import Circle\n\nfig, ax = plt.subplots(figsize=(6, 3), layout='constrained')\n\nax.text(1.5, 1.2, 'default behavior\\n(a.k.a. \"normal\" blend mode)', ha='center')\nax.add_patch(Circle((1, 0), 1, color='c', ec='none'))\nax.add_patch(Circle((2, 0), 1, color='m', ec='none'))\nax.add_patch(Circle((1.5, -0.87), 1, color='y', ec='none'))\n\nax.text(5.5, 1.2, '\"multiply\" blend mode', ha='center')\nax.add_patch(Circle((5, 0), 1, color='c', ec='none'))\nax.add_patch(Circle((6, 0), 1, color='m', ec='none', blend_mode='multiply'))\nax.add_patch(Circle((5.5, -0.87), 1, color='y', ec='none', blend_mode='multiply'))\n\nax.set_xlim(-0.2, 7.2)\nax.set_ylim(-1.9, 1.5)\nax.set_aspect('equal')\nax.axis('off')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matplotlib provides a wide range of alternative behaviors to the default\n(\"normal\") behavior:\n\n* 15 [blend modes](https://en.wikipedia.org/wiki/Blend_modes)\n* 6 [Porter-Duff compositing operators](https://www.w3.org/TR/compositing-1/#advancedcompositing)\n\n(See also `blend-groups` for the additional capability of blending groups\nof artists.)\n\nThese behaviors are specified via the artist's ``blend_mode`` property. You\ncan set the property when creating a new artist, or you can call\n`.Artist.set_blend_mode` on an existing artist. You can specify the behavior\neither by string or by member of the `.BlendMode` enumeration.\n\nBelow is a gallery illustrating the effect of each ``blend_mode`` option for a\nvariety of artists. Although each panel in the gallery has all of its artists\nusing the same blend mode, artists in the same axes can have different blend\nmodes from each other. Be aware that the background of the axes and the\nbackground of the figure are artists as well, so their respective colors may\naffect the blending result.\n\nBackends using the Agg renderer (the default) or the Cairo renderer natively\nsupport all of these ``blend_mode`` options. The vector backends do not\nnatively support some of the options, but one can use rasterization (see\n:doc:`/gallery/misc/rasterization_demo`) to achieve the blending effect if the\nfixed resolution of the result is acceptable.\n\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\nfrom matplotlib.patches import Circle, Rectangle\n\nN = 10\ndata = np.arange(N**2).reshape((N, N)) % (N-1)\n\nfig, axs = plt.subplots(3, 8, figsize=(10, 6), layout='tight')\naxs = axs.flatten()\nfig.set_facecolor('none')\n\nblend_modes = ['normal',\n\n # Blend modes\n 'multiply', 'screen', 'overlay', 'darken', 'lighten',\n 'color dodge', 'color burn', 'hard light', 'soft light',\n 'difference', 'exclusion',\n 'hue', 'saturation', 'color', 'luminosity',\n\n # Porter-Duff compositing operators\n 'knockout', 'erase', 'clear', 'atop', 'xor', 'plus']\n\nfor ax in axs:\n ax.set_facecolor('none')\n ax.set_xlim(0, 1)\n ax.set_ylim(0, 1.2)\n ax.set_axis_off()\n\nfor i, blend_mode in enumerate(blend_modes):\n axs[i].imshow(data, cmap='Reds', alpha=0.75, extent=(0, 0.8, 0, 0.8))\n\n # Four different artist types drawn using this blend_mode setting\n axs[i].imshow(data[::-1, :], cmap='Blues', alpha=0.75, extent=(0.2, 1, 0.4, 1.2),\n blend_mode=blend_mode)\n axs[i].text(0.05, 0.15, 'Test', weight='bold', color='c',\n blend_mode=blend_mode)\n axs[i].plot([0, 1], [1.2, 0], color='y',\n blend_mode=blend_mode)\n circ = Circle((.65, 0.5), .3, facecolor='g', alpha=0.5, zorder=2,\n blend_mode=blend_mode)\n axs[i].add_artist(circ)\n\n rect = Rectangle((0, 1.2), 1, .3, facecolor='lightgray', clip_on=False)\n axs[i].add_artist(rect)\n axs[i].set_title(blend_mode)\n\nplt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This table shows by backend which options for ``blend_mode`` are supported\nnatively (\u2705) versus supported only through rasterization (\ud83d\udfe1).\n\n+----------------+-----+-------+-----+-----+-----+----+\n| Option | Agg | Cairo | SVG | PDF | PGF | PS |\n+================+=====+=======+=====+=====+=====+====+\n| normal [#]_ | \u2705 | \u2705 | \u2705 | \u2705 | \u2705 | \u2705 |\n+----------------+-----+-------+-----+-----+-----+----+\n| multiply, | \u2705 | \u2705 | \u2705 | \u2705 | \u2705 | \ud83d\udfe1 |\n| screen, | | | | | | |\n| overlay, | | | | | | |\n| darken, | | | | | | |\n| lighten, | | | | | | |\n| color dodge, | | | | | | |\n| color burn, | | | | | | |\n| hard light, | | | | | | |\n| soft light, | | | | | | |\n| difference, | | | | | | |\n| exclusion, | | | | | | |\n| hue, | | | | | | |\n| saturation, | | | | | | |\n| color, | | | | | | |\n| luminosity | | | | | | |\n+----------------+-----+-------+-----+-----+-----+----+\n| knockout [#]_, | \u2705 | \u2705 | \ud83d\udfe1 | \ud83d\udfe1 | \ud83d\udfe1 | \ud83d\udfe1 |\n| erase [#]_, | | | | | | |\n| clear, | | | | | | |\n| atop, | | | | | | |\n| xor, | | | | | | |\n| plus | | | | | | |\n+----------------+-----+-------+-----+-----+-----+----+\n\n.. [#] also known as \"over\"\n.. [#] also known as \"source\"\n.. [#] also known as \"destination out\"\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.15" } }, "nbformat": 4, "nbformat_minor": 0 }