svg_path_editor.path_shade ========================== .. py:module:: svg_path_editor.path_shade Attributes ---------- .. autoapisummary:: svg_path_editor.path_shade.WEBP svg_path_editor.path_shade.PNG Classes ------- .. autoapisummary:: svg_path_editor.path_shade.ImageFormat svg_path_editor.path_shade.WebpFormat svg_path_editor.path_shade.PngFormat svg_path_editor.path_shade.PathShading Functions --------- .. autoapisummary:: svg_path_editor.path_shade.lambert_from_angle svg_path_editor.path_shade.lambert_shading_base64 svg_path_editor.path_shade.shade_path Module Contents --------------- .. py:function:: lambert_from_angle(normal) Lambertian diffuse intensity from a surface normal. The light direction is fixed to :math:`(0, -1, 1)` in world space. The result is .. math:: I = \max(0, \hat{\mathbf{n}}\cdot\hat{\mathbf{L}}), evaluated via the signed angle of ``normal`` in the :math:`xy`-plane. :param normal: Surface normal. :return: Lambertian intensity in :math:`[0, 1]`. .. py:class:: ImageFormat Bases: :py:obj:`Protocol` Abstract image encoder. :ivar media_type: MIME type of the encoded image. :ivar extension: File extension (without dot). .. py:attribute:: media_type :type: ClassVar[str] .. py:attribute:: extension :type: ClassVar[str] .. py:method:: encode(data) Encode an RGBA image. :param data: ``(H, W, 4)`` uint8 array in RGBA order. :return: Encoded image bytes. .. py:class:: WebpFormat Lossless WebP encoder. Uses :func:`imagecodecs.webp_encode` with ``lossless=True``. .. py:attribute:: media_type :type: ClassVar[str] :value: 'image/webp' .. py:attribute:: extension :type: ClassVar[str] :value: 'webp' .. py:method:: encode(data) .. py:class:: PngFormat PNG encoder. Uses :func:`imagecodecs.png_encode` with ``level=9``. .. py:attribute:: media_type :type: ClassVar[str] :value: 'image/png' .. py:attribute:: extension :type: ClassVar[str] :value: 'png' .. py:method:: encode(data) .. py:data:: WEBP .. py:data:: PNG .. py:function:: lambert_shading_base64(*, r, phi, locally_convex, resolution, t = 0.25, format = WEBP, seed = None) Render a Lambert–shaded elliptical cone, return encoded bytes and base64 URI. The cone radii are :math:`r = (r_x, r_y)` in image space. For a point :math:`(x, y)` on the grid .. math:: (x, y) \in \left[-\frac{1}{r_x}, \frac{1}{r_x}\right] \times \left[-\frac{1}{r_y}, \frac{1}{r_y}\right], the unnormalized normal is .. math:: \mathbf{n}(x, y) = \left(\frac{x}{r_x^2}, \frac{y}{r_y^2}, 1\right). The Lambert term is .. math:: I(x, y) = \max\left(0, \hat{\mathbf{n}}(x, y)\cdot\hat{\mathbf{L}}\right), where :math:`\hat{\mathbf{L}}` is the unit vector from :math:`(0, s, 1)`, with :math:`s = -1` if ``locally_convex`` else :math:`+1`, rotated in the :math:`xy`-plane by :math:`-\varphi` degrees. Grayscale is binary (0 or 255) according to :math:`I > t`. Alpha is a symmetric remap of :math:`I` around :math:`t`: .. math:: \alpha(I) = \begin{cases} \dfrac{I - t}{1 - t}, & I \geq t,\\ \dfrac{t - I}{t}, & I < t. \end{cases} Before 8-bit quantization, uniform noise in :math:`[0, 1]` is added to alpha for dithering. The final RGBA image is encoded with ``format`` and returned both as raw bytes and as a ``data:...;base64,...`` URI. :param r: Ellipse radii in :math:`x` and :math:`y`. :param phi: Rotation in degrees of the light direction in image space (clockwise in screen coordinates). :param locally_convex: If true, the base light direction is :math:`(0, -1, 1)`, otherwise :math:`(0, 1, 1)`. :param resolution: Pixels per SVG unit. Image size is :math:`\lceil 2 r_x \, \mathrm{resolution} \rceil \times \lceil 2 r_y \, \mathrm{resolution} \rceil`. :param t: Neutral Lambert intensity in :math:`[0, 1]` (threshold). :param format: Image format to use. :param seed: RNG seed for alpha dithering; ``None`` is non-deterministic. :return: ``(img_bytes, img_data_uri)`` with ``img_data_uri`` suitable for SVG ``href``. .. py:class:: PathShading SVG fragments for shaded bevels. :ivar defs_body: Elements for a document-wide ```` (e.g. shared ```` or ```` definitions). :ivar body: Per-path drawing elements (e.g. ````, ````, ````) that reference :attr:`defs_body`. .. py:attribute:: defs_body :type: list[str] .. py:attribute:: body :type: list[str] .. py:function:: shade_path(svg, *, d, threshold, resolution, max_opacity = 1, format = WEBP, shade_offset = 0, clip_offset = 0, seed = None, prec = None) Per-bevel Lambert shading for an SVG path. The path is decomposed into bevel regions via :func:`svg_path_editor.path_offset.bevel_path`. Flat bevel polygons are shaded analytically with :func:`lambert_from_angle`. Curved bevel arcs use a small Lambert RGBA texture from :func:`lambert_shading_base64`, referenced by ```` / ```` and clipped to the arc geometry. For each bevel polygon: * One ```` is emitted with ``fill="white"`` or ``fill="black"`` depending on whether the intensity is above or below ``threshold``. * Opacity is a symmetric remap of the intensity around ``threshold`` in :math:`[0, 1]`, scaled by ``max_opacity``. For each bevel arc: * A Lambert cone texture is generated (or reused from a cache) for ``(r.x, r.y, phi, locally_convex)``. * A base ```` at the origin with size :math:`2 r_x \times 2 r_y` is placed in :attr:`PathShading.defs_body` once per unique key. * For each occurrence, a ```` with the bevel geometry and a ```` of the base image are emitted into :attr:`PathShading.body`, translated so the image origin matches the lower-left corner of the ellipse bounding box, and rotated by ``phi`` around the ellipse center if non-zero. * ```` carries opacity ``max_opacity`` when it is less than 1. To integrate into an SVG, place all ``defs_body`` entries inside a single document-level ```` and insert ``body`` where the path should render. :param svg: Input path to bevel and shade. :param d: Offset distance for :func:`bevel_path`. :param threshold: Neutral Lambert intensity in :math:`[0, 1]`, shared between flat bevels and textures. :param resolution: Pixels per SVG unit for generated textures; image dimensions follow :func:`lambert_shading_base64`. :param max_opacity: Global opacity scale in :math:`[0, 1]`. :param format: Texture format, e.g. :data:`WEBP` or :data:`PNG`. :param seed: RNG seed for alpha dithering in :func:`lambert_shading_base64`; ``None`` for non-deterministic. :param prec: Precision/geometry mode passed to :func:`bevel_path`. ``"auto"`` and ``"auto-intersections"`` select automatic strategies; ``None`` uses the default.