Documented writing your own encoder in C

This commit is contained in:
Andrew Murray 2022-03-01 16:34:21 +11:00
parent a7e8a386d3
commit 2b9cc3ccc5
2 changed files with 48 additions and 50 deletions

View File

@ -328,42 +328,42 @@ The fields are used as follows:
Whether the first line in the image is the top line on the screen (1), or Whether the first line in the image is the top line on the screen (1), or
the bottom line (-1). If omitted, the orientation defaults to 1. the bottom line (-1). If omitted, the orientation defaults to 1.
.. _file-decoders: .. _file-codecs:
Writing Your Own File Decoder in C Writing Your Own File Codec in C
================================== ================================
There are 3 stages in a file decoder's lifetime: There are 3 stages in a file codec's lifetime:
1. Setup: Pillow looks for a function in the decoder registry, falling 1. Setup: Pillow looks for a function in the decoder or encoder registry,
back to a function named ``[decodername]_decoder`` on the internal falling back to a function named ``[codecname]_decoder`` or
core image object. That function is called with the ``args`` tuple ``[codecname]_encoder`` on the internal core image object. That function is
from the ``tile`` setup in the ``_open`` method. called with the ``args`` tuple from the ``tile``.
2. Decoding: The decoder's decode function is repeatedly called with 2. Transforming: The codec's ``decode`` or ``encode`` function is repeatedly
chunks of image data. called with chunks of image data.
3. Cleanup: If the decoder has registered a cleanup function, it will 3. Cleanup: If the codec has registered a cleanup function, it will
be called at the end of the decoding process, even if there was an be called at the end of the transformation process, even if there was an
exception raised. exception raised.
Setup Setup
----- -----
The current conventions are that the decoder setup function is named The current conventions are that the codec setup function is named
``PyImaging_[Decodername]DecoderNew`` and defined in ``decode.c``. The ``PyImaging_[codecname]DecoderNew`` or ``PyImaging_[codecname]EncoderNew``
python binding for it is named ``[decodername]_decoder`` and is setup and defined in ``decode.c`` or ``encode.c``. The Python binding for it is
from within the ``_imaging.c`` file in the codecs section of the named ``[codecname]_decoder`` or ``[codecname]_encoder`` and is setup from
function array. within the ``_imaging.c`` file in the codecs section of the function array.
The setup function needs to call ``PyImaging_DecoderNew`` and at the The setup function needs to call ``PyImaging_DecoderNew`` or
very least, set the ``decode`` function pointer. The fields of ``PyImaging_EncoderNew`` and at the very least, set the ``decode`` or
interest in this object are: ``encode`` function pointer. The fields of interest in this object are:
**decode** **decode**/**encode**
Function pointer to the decode function, which has access to Function pointer to the decode or encode function, which has access to
``im``, ``state``, and the buffer of data to be added to the image. ``im``, ``state``, and the buffer of data to be transformed.
**cleanup** **cleanup**
Function pointer to the cleanup function, has access to ``state``. Function pointer to the cleanup function, has access to ``state``.
@ -373,35 +373,34 @@ interest in this object are:
**state** **state**
An ImagingCodecStateInstance, will be set by Pillow. The ``context`` An ImagingCodecStateInstance, will be set by Pillow. The ``context``
member is an opaque struct that can be used by the decoder to store member is an opaque struct that can be used by the codec to store
any format specific state or options. any format specific state or options.
**pulls_fd** **pulls_fd**/**pushes_fd**
If set to 1, ``state->fd`` will be a pointer to the Python file like If the decoder has ``pulls_fd`` or the encoder has ``pushes_fd`` set to 1,
object. The decoder may use the functions in ``codec_fd.c`` to read ``state->fd`` will be a pointer to the Python file like object. The codec may
directly from the file like object rather than have the data pushed use the functions in ``codec_fd.c`` to read or write directly with the file
through a buffer. like object rather than have the data pushed through a buffer.
.. versionadded:: 3.3.0 .. versionadded:: 3.3.0
Decoding Transforming
-------- ------------
The decode function is called with the target (core) image, the The decode or encode function is called with the target (core) image, the codec
decoder state structure, and a buffer of data to be decoded. state structure, and a buffer of data to be transformed.
It is the decoder's responsibility to pull as much data as possible It is the codec's responsibility to pull as much data as possible out of the
out of the buffer and return the number of bytes consumed. The next buffer and return the number of bytes consumed. The next call to the codec will
call to the decoder will include the previous unconsumed tail. The include the previous unconsumed tail. The codec function will be called
decoder function will be called multiple times as the data is read multiple times as the data processed.
from the file like object.
Alternatively, if ``pulls_fd`` is set, then the decode function is Alternatively, if ``pulls_fd`` or ``pushes_fd`` is set, then the decode or
called once, with an empty buffer. It is the decoder's responsibility encode function is called once, with an empty buffer. It is the codec's
to decode the entire tile in that one call. Using this will provide a responsibility to transform the entire tile in that one call. Using this will
codec with more freedom, but that freedom may mean increased memory usage provide a codec with more freedom, but that freedom may mean increased memory
if entire tile is held in memory at once by the codec. usage if entire tile is held in memory at once by the codec.
If an error occurs, set ``state->errcode`` and return -1. If an error occurs, set ``state->errcode`` and return -1.
@ -410,10 +409,9 @@ Return -1 on success, without setting the errcode.
Cleanup Cleanup
------- -------
The cleanup function is called after the decoder returns a negative The cleanup function is called after the codec returns a negative
value, or if there is a read error from the file. This function should value, or if there is an error. This function should free any allocated
free any allocated memory and release any resources from external memory and release any resources from external libraries.
libraries.
.. _file-codecs-py: .. _file-codecs-py:
@ -428,7 +426,7 @@ They should be registered using :py:meth:`PIL.Image.register_decoder` and
the file codecs, there are three stages in the lifetime of a the file codecs, there are three stages in the lifetime of a
Python-based file codec: Python-based file codec:
1. Setup: Pillow looks for the decoder in the registry, then 1. Setup: Pillow looks for the codec in the decoder or encoder registry, then
instantiates the class. instantiates the class.
2. Transforming: The instance's ``decode`` method is repeatedly called with 2. Transforming: The instance's ``decode`` method is repeatedly called with

View File

@ -2779,9 +2779,9 @@ def frombytes(mode, size, data, decoder_name="raw", *args):
In its simplest form, this function takes three arguments In its simplest form, this function takes three arguments
(mode, size, and unpacked pixel data). (mode, size, and unpacked pixel data).
You can also use any pixel decoder supported by PIL. For more You can also use any pixel decoder supported by PIL. For more
information on available decoders, see the section information on available decoders, see the section
:ref:`Writing Your Own File Decoder <file-decoders>`. :ref:`Writing Your Own File Codec <file-codecs>`.
Note that this function decodes pixel data only, not entire images. Note that this function decodes pixel data only, not entire images.
If you have an entire image in a string, wrap it in a If you have an entire image in a string, wrap it in a