<commit_before>Images
======

pyglet provides functions for loading and saving images in various formats
using native operating system services.  pyglet can also work with the `Python
Imaging Library`_ (PIL) for access to more file formats.

Loaded images can be efficiently provided to OpenGL as a texture, and OpenGL
textures and framebuffers can be retrieved as pyglet images to be saved or
otherwise manipulated.

Some simple methods are provided for drawing images to windows; these will
usually be sufficient for writing simple sprite-based games.  For more
advanced imaging you will need some knowledge of OpenGL.

.. contents::
    :local:

.. _Python Imaging Library: http://www.pythonware.com/products/pil/

Loading an image
----------------

Images are loaded using the `pyglet.image.load` function::

    from pyglet import image
    kitten = image.load('kitten.png')

Without any additional arguments, `load` will attempt to load the
filename specified using any available image decoder.  This will allow you to
load PNG, GIF, JPEG, BMP and DDS files, and possibly other files as well,
depending on your operating system and additional installed modules (see the
next section for details).  If the image cannot be loaded, an
`ImageDecodeException` will be raised.

You can load an image from any file-like object providing a `read` method by
specifying the `file` keyword parameter::

    kitten_stream = open('kitten.png', 'rb')
    kitten = image.load('kitten.png', file=kitten_stream)

In this case the filename ``kitten.png`` is optional, but gives a hint to the
decoder as to the file type (it is otherwise unused).

pyglet provides the following image decoders:

    .. list-table::
        :header-rows: 1
       
        * - Module
          - Class
          - Description
        * - ``pyglet.image.codecs.dds``
          - ``DDSImageDecoder``
          - Reads Microsoft DirectDraw Surface files containing compressed
            textures
        * - ``pyglet.image.codecs.gdiplus``
          - ``GDIPlusDecoder``
          - Uses Windows GDI+ services to decode images.
        * - ``pyglet.image.codecs.gdkpixbuf2``
          - ``GdkPixbuf2ImageDecoder``
          - Uses the GTK-2.0 GDK functions to decode images.
        * - ``pyglet.image.codecs.pil``
          - ``PILImageDecoder``
          - Wrapper interface around PIL Image class.
        * - ``pyglet.image.codecs.png``
          - ``PNGImageDecoder``
          - PNG decoder written in pure Python.
        * - ``pyglet.image.codecs.quicktime``
          - ``QuickTimeImageDecoder``
          - Uses Mac OS X QuickTime to decode images.

Each of these classes registers itself with `pyglet.image` with the filename
extensions it supports.  The `load` function will try each image decoder with
a matching file extension first, before attempting the other decoders.  Only
if every image decoder fails to load an image will `ImageDecodeException` be
raised (the origin of the exception will be the first decoder that was
attempted).

You can override this behaviour and specify a particular decoding instance to
use.  For example, in the following example the pure Python PNG decoder is
always used rather than the operating system's decoder::

    from pyglet.image.codecs.png import PNGImageDecoder
    kitten = image.load('kitten.png', decoder=PNGImageDecoder())

This use is not recommended unless your application has to work around
specific deficiences in an operating system decoder.

Supported image formats
-----------------------

The following table lists the image formats that can be loaded on each
operating system.  If PIL is installed, any additional formats it supports can
also be read.  See the `Python Imaging Library Handbook`_ for a list of such
formats.

.. _Python Imaging Library Handbook: http://www.pythonware.com/library/pil/handbook/index.htm

    .. list-table::
        :header-rows: 1

        * - Extension
          - Description
          - Windows XP
          - Mac OS X
          - Linux [#linux]_
        * - ``.bmp``
          - Windows Bitmap
          - X
          - X
          - X
        * - ``.dds``
          - Microsoft DirectDraw Surface [#dds]_
          - X
          - X
          - X
        * - ``.exif``
          - Exif
          - X
          -  
          -  
        * - ``.gif``
          - Graphics Interchange Format
          - X
          - X
          - X
        * - ``.jpg .jpeg``
          - JPEG/JIFF Image
          - X
          - X
          - X
        * - ``.jp2 .jpx``
          - JPEG 2000
          -  
          - X
          -  
        * - ``.pcx``
          - PC Paintbrush Bitmap Graphic
          -  
          - X
          -  
        * - ``.png``
          - Portable Network Graphic
          - X
          - X
          - X
        * - ``.pnm``
          - PBM Portable Any Map Graphic Bitmap
          -  
          -  
          - X
        * - ``.ras``
          - Sun raster graphic
          -  
          -  
          - X
        * - ``.tga``
          - Truevision Targa Graphic
          -  
          - X
          -  
        * - ``.tif .tiff``
          - Tagged Image File Format
          - X
          - X
          - X
        * - ``.xbm``
          - X11 bitmap
          -  
          - X
          - X
        * - ``.xpm``
          - X11 icon
          -  
          - X
          - X

The only supported save format is PNG, unless PIL is installed, in which case
any format it supports can be written.

.. [#linux] Requires GTK 2.0 or later.

.. [#dds] Only S3TC compressed surfaces are supported.  Depth, volume and cube
          textures are not supported.

Working with images
-------------------

The `image.load` function returns an `AbstractImage`.  The actual class of the
object depends on the decoder that was used, but all images support the
following attributes:

`width`
    The width of the image, in pixels.
`height`
    The height of the image, in pixels.
`anchor_x`
    Distance of the anchor point from the left edge of the image, in pixels
`anchor_y`
    Distance of the anchor point from the bottom edge of the image, in pixels

The anchor point defaults to (0, 0), though some image formats may contain an
intrinsic anchor point.  The anchor point is used to align the image to a
point in space when drawing it.

You may only want to use a portion of the complete image.  You can use the
`get_region` method to return an image of a rectangular region of a source
image::

    image_part = kitten.get_region(x=10, y=10, width=100, height=100)

This returns an image with dimensions 100x100.  The region extracted from
`kitten` is aligned such that the bottom-left corner of the rectangle is 10
pixels from the left and 10 pixels from the bottom of the image.

Image regions can be used as if they were complete images.  Note that changes
to an image region may or may not be reflected on the source image, and
changes to the source image may or may not be reflected on any region images.
You should not assume either behaviour.

Displaying images
-----------------

Use the `blit` method to draw an image to the current window::

    kitten.blit(x, y)

You can use the `blit` method to draw any image, including an image region.
The `x` and `y` coordinates locate where to draw the anchor point of the
image.  For example, to center the image at ``(x, y)``::

    kitten.anchor_x = kitten.width // 2
    kitten.anchor_y = kitten.height // 2
    kitten.blit(x, y)

You can also specify an optional `z` component to the `blit` method.  This has
no effect unless you have changed the default projection or enabled depth
testing.  In the following example, the second image is drawn *behind* the
first, even though it is drawn after it::

    from pyglet.gl import *
    glEnable(GL_DEPTH_TEST)

    kitten.blit(x, y, 0)
    kitten.blit(x, y, -0.5)

The default pyglet projection has a depth range of (-1, 1) -- images drawn
with a z value outside this range will not be visible, regardless of whether
depth testing is enabled or not.

Images with an alpha channel can be blended with the existing framebuffer.  To
do this you need to supply OpenGL with a blend equation.  The following code
fragment implements the most common form of alpha blending, however other
techniques are also possible::

    from pyglet.gl import *
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

You would only need to call the code above once during your program, before
you draw any images. 

The AbstractImage hierarchy
---------------------------

The following sections deal with the various concrete image classes.  All
images subclass `AbstractImage`, which provides the basic interface described
in previous sections.

.. figure:: abstract_image.svg

    The `AbstractImage` class hierarchy.

An image of any class can be converted into a `Texture` or `ImageData` using
the `get_texture` and `get_image_data` methods defined on `AbstractImage`.  For
example, to load an image and work with it as an OpenGL texture::

    kitten = image.load('kitten.png').get_texture()

There is no penalty for accessing one of these methods if object is already<commit_msg>Add in a note about performance. Not sure I got the cross-reference stuff right though.<commit_after>Images
======

pyglet provides functions for loading and saving images in various formats
using native operating system services.  pyglet can also work with the `Python
Imaging Library`_ (PIL) for access to more file formats.

Loaded images can be efficiently provided to OpenGL as a texture, and OpenGL
textures and framebuffers can be retrieved as pyglet images to be saved or
otherwise manipulated.

Some simple methods are provided for drawing images to windows; these will
usually be sufficient for writing simple sprite-based games.  For more
advanced imaging you will need some knowledge of OpenGL.

.. contents::
    :local:

.. _Python Imaging Library: http://www.pythonware.com/products/pil/

Loading an image
----------------

Images are loaded using the `pyglet.image.load` function::

    from pyglet import image
    kitten = image.load('kitten.png')

Without any additional arguments, `load` will attempt to load the
filename specified using any available image decoder.  This will allow you to
load PNG, GIF, JPEG, BMP and DDS files, and possibly other files as well,
depending on your operating system and additional installed modules (see the
next section for details).  If the image cannot be loaded, an
`ImageDecodeException` will be raised.

You can load an image from any file-like object providing a `read` method by
specifying the `file` keyword parameter::

    kitten_stream = open('kitten.png', 'rb')
    kitten = image.load('kitten.png', file=kitten_stream)

In this case the filename ``kitten.png`` is optional, but gives a hint to the
decoder as to the file type (it is otherwise unused).

pyglet provides the following image decoders:

    .. list-table::
        :header-rows: 1
       
        * - Module
          - Class
          - Description
        * - ``pyglet.image.codecs.dds``
          - ``DDSImageDecoder``
          - Reads Microsoft DirectDraw Surface files containing compressed
            textures
        * - ``pyglet.image.codecs.gdiplus``
          - ``GDIPlusDecoder``
          - Uses Windows GDI+ services to decode images.
        * - ``pyglet.image.codecs.gdkpixbuf2``
          - ``GdkPixbuf2ImageDecoder``
          - Uses the GTK-2.0 GDK functions to decode images.
        * - ``pyglet.image.codecs.pil``
          - ``PILImageDecoder``
          - Wrapper interface around PIL Image class.
        * - ``pyglet.image.codecs.png``
          - ``PNGImageDecoder``
          - PNG decoder written in pure Python.
        * - ``pyglet.image.codecs.quicktime``
          - ``QuickTimeImageDecoder``
          - Uses Mac OS X QuickTime to decode images.

Each of these classes registers itself with `pyglet.image` with the filename
extensions it supports.  The `load` function will try each image decoder with
a matching file extension first, before attempting the other decoders.  Only
if every image decoder fails to load an image will `ImageDecodeException` be
raised (the origin of the exception will be the first decoder that was
attempted).

You can override this behaviour and specify a particular decoding instance to
use.  For example, in the following example the pure Python PNG decoder is
always used rather than the operating system's decoder::

    from pyglet.image.codecs.png import PNGImageDecoder
    kitten = image.load('kitten.png', decoder=PNGImageDecoder())

This use is not recommended unless your application has to work around
specific deficiences in an operating system decoder.

Supported image formats
-----------------------

The following table lists the image formats that can be loaded on each
operating system.  If PIL is installed, any additional formats it supports can
also be read.  See the `Python Imaging Library Handbook`_ for a list of such
formats.

.. _Python Imaging Library Handbook: http://www.pythonware.com/library/pil/handbook/index.htm

    .. list-table::
        :header-rows: 1

        * - Extension
          - Description
          - Windows XP
          - Mac OS X
          - Linux [#linux]_
        * - ``.bmp``
          - Windows Bitmap
          - X
          - X
          - X
        * - ``.dds``
          - Microsoft DirectDraw Surface [#dds]_
          - X
          - X
          - X
        * - ``.exif``
          - Exif
          - X
          -  
          -  
        * - ``.gif``
          - Graphics Interchange Format
          - X
          - X
          - X
        * - ``.jpg .jpeg``
          - JPEG/JIFF Image
          - X
          - X
          - X
        * - ``.jp2 .jpx``
          - JPEG 2000
          -  
          - X
          -  
        * - ``.pcx``
          - PC Paintbrush Bitmap Graphic
          -  
          - X
          -  
        * - ``.png``
          - Portable Network Graphic
          - X
          - X
          - X
        * - ``.pnm``
          - PBM Portable Any Map Graphic Bitmap
          -  
          -  
          - X
        * - ``.ras``
          - Sun raster graphic
          -  
          -  
          - X
        * - ``.tga``
          - Truevision Targa Graphic
          -  
          - X
          -  
        * - ``.tif .tiff``
          - Tagged Image File Format
          - X
          - X
          - X
        * - ``.xbm``
          - X11 bitmap
          -  
          - X
          - X
        * - ``.xpm``
          - X11 icon
          -  
          - X
          - X

The only supported save format is PNG, unless PIL is installed, in which case
any format it supports can be written.

.. [#linux] Requires GTK 2.0 or later.

.. [#dds] Only S3TC compressed surfaces are supported.  Depth, volume and cube
          textures are not supported.

Working with images
-------------------

The `image.load` function returns an `AbstractImage`.  The actual class of the
object depends on the decoder that was used, but all images support the
following attributes:

`width`
    The width of the image, in pixels.
`height`
    The height of the image, in pixels.
`anchor_x`
    Distance of the anchor point from the left edge of the image, in pixels
`anchor_y`
    Distance of the anchor point from the bottom edge of the image, in pixels

The anchor point defaults to (0, 0), though some image formats may contain an
intrinsic anchor point.  The anchor point is used to align the image to a
point in space when drawing it.

You may only want to use a portion of the complete image.  You can use the
`get_region` method to return an image of a rectangular region of a source
image::

    image_part = kitten.get_region(x=10, y=10, width=100, height=100)

This returns an image with dimensions 100x100.  The region extracted from
`kitten` is aligned such that the bottom-left corner of the rectangle is 10
pixels from the left and 10 pixels from the bottom of the image.

Image regions can be used as if they were complete images.  Note that changes
to an image region may or may not be reflected on the source image, and
changes to the source image may or may not be reflected on any region images.
You should not assume either behaviour.

Displaying images
-----------------

Use the `blit` method to draw an image to the current window::

    kitten.blit(x, y)

You can use the `blit` method to draw any image, including an image region.
The `x` and `y` coordinates locate where to draw the anchor point of the
image.  For example, to center the image at ``(x, y)``::

    kitten.anchor_x = kitten.width // 2
    kitten.anchor_y = kitten.height // 2
    kitten.blit(x, y)

You can also specify an optional `z` component to the `blit` method.  This has
no effect unless you have changed the default projection or enabled depth
testing.  In the following example, the second image is drawn *behind* the
first, even though it is drawn after it::

    from pyglet.gl import *
    glEnable(GL_DEPTH_TEST)

    kitten.blit(x, y, 0)
    kitten.blit(x, y, -0.5)

The default pyglet projection has a depth range of (-1, 1) -- images drawn
with a z value outside this range will not be visible, regardless of whether
depth testing is enabled or not.

Images with an alpha channel can be blended with the existing framebuffer.  To
do this you need to supply OpenGL with a blend equation.  The following code
fragment implements the most common form of alpha blending, however other
techniques are also possible::

    from pyglet.gl import *
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

You would only need to call the code above once during your program, before
you draw any images.

The `blit` method is not designed for high-performance display of many
images. See the `pyglet.graphics` and related `pyglet.sprite` modules for
high-performance image display.


The AbstractImage hierarchy
---------------------------

The following sections deal with the various concrete image classes.  All
images subclass `AbstractImage`, which provides the basic interface described
in previous sections.

.. figure:: abstract_image.svg

    The `AbstractImage` class hierarchy.

An image of any class can be converted into a `Texture` or `ImageData` using
the `get_texture` and `get_image_data` methods defined on `AbstractImage`.  For
example, to load an image and work with it as an OpenGL texture::

    kitten = image.load('kitten.png').get_texture()

There is no penalty for accessing one of these methods if object is already
{'fraction_non_alphanumeric': 0.08060358715497798, 'fraction_numerical': 0.005047792933089893, 'mean_word_length': 2.282164258019034, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6251224', 'n_tokens_mistral': 5211, 'n_tokens_neox': 4970, 'n_words': 2300}