Skip to content

Commit

Permalink
Improved blit() docs (#2262)
Browse files Browse the repository at this point in the history
* updated blit docs

* oopsies

* Return

added separators and slight correction

shortened blit docs

removed redundant note, slightly better default blend_flag description

removed special flags section in blit

added some highlights to the last note

better notes, separated param descriptions into separate sections

various rephrases to improve passive voice use and readability

added more info about the default blend flag. cleanup

moved the special flags section to Surface(),
addressed reviews.

changed the way sections are made

removed "-"s to align all cases

substantially changed special flags descriptions

added comment on how the alpha channel is treated

some other minor changes

some corrections

* format, removed section lines

* corrected a phrase

* made short parameters list clearer

* re-added a very compact version of special flags section

* removed bullet points

* readded versionadded tags

* removed special flags section again

* moved to bullet point list of notes

* Revert "moved to bullet point list of notes"

This reverts commit eeff064.

* - simplified blit docs
- moved noted to bullet list
- moved special flags list to a separate page

* tried to address reviews and concerns

* partially addressed reviews, condensed some sentences.

* Added "Example Use" section

* method links now work

* fix

* Update docs/reST/ref/special_flags_list.rst

Co-authored-by: Dan Lawrence <[email protected]>

* fblits*

---------

Co-authored-by: Dan Lawrence <[email protected]>
  • Loading branch information
itzpr3d4t0r and MyreMylar authored Nov 26, 2023
1 parent 9d76a10 commit da69f21
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 34 deletions.
115 changes: 115 additions & 0 deletions docs/reST/ref/special_flags_list.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
.. include:: common.txt

====================
:mod:`special flags`
====================

What Are Special Flags?
=======================

**Special flags are a means of controlling how a** :class:`Surface` **is drawn onto another**.
They can be used to create visual effects, such as glowing particles, or to perform surface
masking or manipulation.
They are used with the following methods:

- :meth:`pygame.Surface.blit`
- :meth:`pygame.Surface.blits`
- :meth:`pygame.Surface.fblits`
- :meth:`pygame.Surface.fill`

Specifically they are passed as the ``special_flags`` argument of these methods by using
``pygame.BLEND_*`` constants and allow you to choose how the colors of the surfaces are
combined or blended together. Different flags can produce widely different results, so
it is important to experiment to understand how they work.

By default, surfaces are drawn without any special flags, meaning they will be drawn based
on their bit ``depth`` and ``colorkey``:

- If the ``Surface`` has a ``colorkey``, the pixels matching the ``colorkey`` will be transparent.

- If the ``Surface`` has a per-pixel or global alpha value, the alpha value will be used to blend the
pixels with the ``Surface`` below.

- If the ``Surface`` doesn't have a ``colorkey`` or alpha value, the pixels will be opaque, meaning
that the ``Surface`` will effectively overwrite the pixels of the ``Surface`` below.

The default drawing mode has its own flag: ``BLENDMODE_NONE`` (``0``).

Special Flags List
==================

**Blending without Alpha Channel (RGB)**

----

.. versionaddedold:: 1.8 / 1.8.1

- ``BLEND_ADD`` / ``BLEND_RGB_ADD``
Adds the source color channels to the destination color channels, clamped to a maximum of 255.
The result color is always a lighter color.

- ``BLEND_SUB`` / ``BLEND_RGB_SUB``
Subtracts the source color channels from the destination color channels, clamped to a minimum of 0.
The result color is always a darker color.

- ``BLEND_MULT`` / ``BLEND_RGB_MULT``
Multiplies the destination color channels by the source color channels, divided by 256 (or >> 8).
The result color is always a darker color.

- ``BLEND_MIN`` / ``BLEND_RGB_MIN``
Takes the minimum value between the source and destination color channels.

- ``BLEND_MAX`` / ``BLEND_RGB_MAX``
Takes the maximum value of each color channel

**Blending with Alpha Channel (RGBA)**

----

.. versionaddedold:: 1.8.1

- ``BLEND_RGBA_ADD``
Works like ``BLEND_RGB_ADD``, but also adds the alpha channel.

- ``BLEND_RGBA_SUB``
Works like ``BLEND_RGB_SUB``, but also subtracts the alpha channel.

- ``BLEND_RGBA_MULT``
Works like ``BLEND_RGB_MULT``, but also multiplies the alpha channel.

- ``BLEND_RGBA_MIN``
Works like ``BLEND_RGB_MIN``, but also minimizes the alpha channel.

- ``BLEND_RGBA_MAX``
Works like ``BLEND_RGB_MAX``, but also maximizes the alpha channel.

**Special Alpha Blending (RGBA)**

----

.. versionaddedold:: 1.9.2

- ``BLEND_PREMULTIPLIED``
Uses premultiplied alpha blending for slightly faster blits and more
accurate blending results when the color channels are already multiplied
by the surface alpha channel.
You should only use this blend mode if you previously premultiplied the Surface with
:meth:`pygame.Surface.premul_alpha()`, or if you know that the Surface was already
created or loaded in with premultiplied alpha colors. You can read more about the
advantages of `premultiplied alpha blending
here <https://en.wikipedia.org/wiki/Alpha_compositing>`_.

.. versionaddedold:: 2.0.0

- ``BLEND_ALPHA_SDL2``
Uses the SDL2 blitter for alpha blending, which may give slightly different
results compared to the default blitter used in Pygame 1. This algorithm uses
different approximations for alpha blending and supports Run-Length Encoding
(RLE) on alpha-blended surfaces.

**Other (RGB / RGBA)**

----

- ``BLENDMODE_NONE``
It's the default drawing mode. It's equivalent to not passing any special flags.
75 changes: 42 additions & 33 deletions docs/reST/ref/surface.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,44 +89,53 @@

.. method:: blit

| :sl:`draw one image onto another`
| :sl:`draw another surface onto this one`
| :sg:`blit(source, dest, area=None, special_flags=0) -> Rect`
Draws a source Surface onto this Surface. The draw can be positioned with
the dest argument. The dest argument can either be a pair of coordinates representing the position of
the upper left corner of the blit or a Rect, where the upper left corner of the rectangle will be used as the
position for the blit. The size of the destination rectangle does not
effect the blit.
Draws another Surface onto this Surface.

An optional area rectangle can be passed as well. This represents a
smaller portion of the source Surface to draw.

.. versionaddedold:: 1.8
Optional ``special_flags``: ``BLEND_ADD``, ``BLEND_SUB``,
``BLEND_MULT``, ``BLEND_MIN``, ``BLEND_MAX``.

.. versionaddedold:: 1.8.1
Optional ``special_flags``: ``BLEND_RGBA_ADD``, ``BLEND_RGBA_SUB``,
``BLEND_RGBA_MULT``, ``BLEND_RGBA_MIN``, ``BLEND_RGBA_MAX``
``BLEND_RGB_ADD``, ``BLEND_RGB_SUB``, ``BLEND_RGB_MULT``,
``BLEND_RGB_MIN``, ``BLEND_RGB_MAX``.

.. versionaddedold:: 1.9.2
Optional ``special_flags``: ``BLEND_PREMULTIPLIED``

.. versionaddedold:: 2.0.0
Optional ``special_flags``: ``BLEND_ALPHA_SDL2`` - Uses the SDL2 blitter for alpha blending,
this gives different results than the default blitter, which is modelled after SDL1, due to
different approximations used for the alpha blending formula. The SDL2 blitter also supports
RLE on alpha blended surfaces which the pygame one does not.

The return rectangle is the area of the affected pixels, excluding any
pixels outside the destination Surface, or outside the clipping area.
**Parameters**
- ``source``
The ``Surface`` object to draw onto this ``Surface``.
If it has transparency, transparent pixels will be ignored when blittting to an 8-bit ``Surface``.
- ``dest``
The ``source`` draw position onto this ``Surface``.
It can be a coordinate ``(x, y)`` or a ``Rect`` (using its top-left corner).
If a ``Rect`` is passed, its size will not affect the blit.
- ``area`` *(optional)*
The rectangular portion of the ``source`` to draw.
It can be a ``Rect`` object representing that section. If ``None`` or not provided,
the entire source surface will be drawn.
If the ``Rect`` has negative position, the final blit position will be
``dest`` - ``Rect.topleft``.
- ``special_flags`` *(optional)*
Controls how the colors of the ``source`` are combined with this Surface.
If not provided it defaults to ``BLENDMODE_NONE`` (``0``).
See :doc:`special_flags_list` for a list of possible values.
**Return**
A :doc:`rect` object representing the affected area of this ``Surface`` that was modified
by the blit operation. This area includes only the pixels within this ``Surface`` or
its clipping area (see :meth:`set_clip`).
Generally you don't need to use this return value, as it was initially designed to
pass it to :meth:`pygame.display.update` to optimize the updating of the display.
Since modern computers are fast enough to update the entire display at high speeds,
this return value is rarely used nowadays.
**Example Use**
.. code-block:: python
# create a surface of size 50x50 and fill it with red color
red_surf = pygame.Surface((50, 50))
red_surf.fill("red")
# draw the surface on another surface at position (0, 0)
another_surface.blit(red_surf, (0, 0))
Pixel alphas will be ignored when blitting to an 8 bit Surface.
**Notes**
- When self-blitting and there is a colorkey or alpha transparency set, resulting colors
may appear slightly different compared to a non-self blit.

For a surface with colorkey or blanket alpha, a blit to self may give
slightly different colors than a non self-blit.
- The blit is ignored if the ``source`` is positioned completely outside this ``Surface``'s
clipping area. Otherwise only the overlapping area will be drawn.

.. ## Surface.blit ##
Expand Down
2 changes: 1 addition & 1 deletion src_c/doc/surface_doc.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Auto generated file: with makeref.py . Docs go in docs/reST/ref/ . */
#define DOC_SURFACE "Surface((width, height), flags=0, depth=0, masks=None) -> Surface\nSurface((width, height), flags=0, Surface) -> Surface\npygame object for representing images"
#define DOC_SURFACE_BLIT "blit(source, dest, area=None, special_flags=0) -> Rect\ndraw one image onto another"
#define DOC_SURFACE_BLIT "blit(source, dest, area=None, special_flags=0) -> Rect\ndraw another surface onto this one"
#define DOC_SURFACE_BLITS "blits(blit_sequence=((source, dest), ...), doreturn=True) -> [Rect, ...] or None\nblits(((source, dest, area), ...)) -> [Rect, ...]\nblits(((source, dest, area, special_flags), ...)) -> [Rect, ...]\ndraw many images onto another"
#define DOC_SURFACE_FBLITS "fblits(blit_sequence=((source, dest), ...), special_flags=0, /) -> None\ndraw many surfaces onto the calling surface at their corresponding location and the same special_flags"
#define DOC_SURFACE_CONVERT "convert(surface, /) -> Surface\nconvert(depth, flags=0, /) -> Surface\nconvert(masks, flags=0, /) -> Surface\nconvert() -> Surface\nchange the pixel format of an image"
Expand Down

0 comments on commit da69f21

Please sign in to comment.