Skip to content

Commit 5612f56

Browse files
authored
Refactor encoders and decoders modules, add support for JPEG-LS encoding (pydicom#2015)
1 parent 8c75525 commit 5612f56

36 files changed

+6051
-3216
lines changed

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@
1010

1111
*pydicom* is a pure Python package for working with [DICOM](https://www.dicomstandard.org/) files.
1212
It lets you read, modify and write DICOM data in an easy "pythonic" way. As a pure Python package,
13-
*pydicom* can run anywhere Python runs without any other requirements, although if you're working
13+
*pydicom* can run anywhere Python runs without any other requirements, although if you're working
1414
with *Pixel Data* then we recommend you also install [NumPy](https://numpy.org).
1515

16-
Note that *pydicom* is a general-purpose DICOM framework concerned with
17-
reading and writing DICOM datasets. In order to keep the
16+
Note that *pydicom* is a general-purpose DICOM framework concerned with
17+
reading and writing DICOM datasets. In order to keep the
1818
project manageable, it does not handle the specifics of individual SOP classes
1919
or other aspects of DICOM. Other libraries both inside and outside the
20-
[pydicom organization](https://github.com/pydicom) are based on *pydicom*
21-
and provide support for other aspects of DICOM, and for more
20+
[pydicom organization](https://github.com/pydicom) are based on *pydicom*
21+
and provide support for other aspects of DICOM, and for more
2222
specific applications.
2323

24-
Examples are [pynetdicom](https://github.com/pydicom/pynetdicom), which
24+
Examples are [pynetdicom](https://github.com/pydicom/pynetdicom), which
2525
is a Python library for DICOM networking, and [deid](https://github.com/pydicom/deid),
2626
which supports the anonymization of DICOM files.
2727

@@ -81,7 +81,7 @@ array([[175, 180, 166, ..., 203, 207, 216],
8181
#### JPEG, JPEG-LS and JPEG 2000
8282
Converting JPEG compressed *Pixel Data* to an ``ndarray`` requires installing one or more additional Python libraries. For information on which libraries are required, see the [pixel data handler documentation](https://pydicom.github.io/pydicom/stable/old/image_data_handlers.html#guide-compressed).
8383

84-
Compressing data into one of the JPEG formats is not currently supported.
84+
Currently only JPEG-LS (with [pyjpegls](https://github.com/pydicom/pyjpegls)) is supported for compressing data.
8585

8686
#### RLE
8787
Encoding and decoding RLE *Pixel Data* only requires NumPy, however it can
@@ -121,12 +121,12 @@ plt.show()
121121

122122
## Contributing
123123

124-
We are all volunteers working on *pydicom* in our free time. As our
125-
resources are limited, we very much value your contributions, be it bug fixes, new
124+
We are all volunteers working on *pydicom* in our free time. As our
125+
resources are limited, we very much value your contributions, be it bug fixes, new
126126
core features, or documentation improvements. For more information, please
127127
read our [contribution guide](https://github.com/pydicom/pydicom/blob/main/CONTRIBUTING.md).
128128

129-
If you have examples or extensions of *pydicom* that don't belong with the
130-
core software, but that you deem useful to others, you can add them to our
129+
If you have examples or extensions of *pydicom* that don't belong with the
130+
core software, but that you deem useful to others, you can add them to our
131131
contribution repository:
132132
[contrib-pydicom](https://www.github.com/pydicom/contrib-pydicom).

doc/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474

7575
autodoc_default_options = {
7676
"members": None,
77-
"no-inherited-members": None,
77+
"inherited-members": True,
7878
}
7979

8080
# copybutton conf

doc/guides/encoding/encoder_plugin_options.rst

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,26 @@ gdcm
3939
pylibjpeg
4040
=========
4141

42-
+--------------------------+-----------------+------------------+-----------------------------+
43-
| Encoder | Options |
44-
+ +-----------------+------------------+-----------------------------+
45-
| | Key | Value | Description |
46-
+==========================+=================+==================+=============================+
47-
|:attr:`RLELosslessEncoder`| ``'byteorder'`` | ``'<'``, ``'>'`` | The byte order of `src` may |
48-
| | | | be little- or big-endian |
49-
+--------------------------+-----------------+------------------+-----------------------------+
42+
+--------------------------------+-----------------+------------------+-----------------------------+
43+
| Encoder | Options |
44+
+ +-----------------+------------------+-----------------------------+
45+
| | Key | Value | Description |
46+
+================================+=================+==================+=============================+
47+
|:attr:`RLELosslessEncoder` | ``'byteorder'`` | ``'<'``, ``'>'`` | The byte order of `src` may |
48+
| | | | be little- or big-endian |
49+
+--------------------------------+-----------------+------------------+-----------------------------+
50+
51+
52+
.. _encoder_plugin_pyjpegls:
53+
54+
pyjpegls
55+
========
56+
57+
+---------------------------------+-----------------+----------------------------+-----------------------------+
58+
| Encoder | Options |
59+
+ +-----------------+----------------------------+-----------------------------+
60+
| | Key | Value | Description |
61+
+=================================+=================+============================+=============================+
62+
|:attr:`JPEGLSLosslessEncoder` | (none available) |
63+
|:attr:`JPEGLSNearLosslessEncoder`| |
64+
+---------------------------------+-----------------+----------------------------+-----------------------------+

doc/guides/encoding/encoder_plugins.rst

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
Pixel Data Encoder Plugins
55
==========================
66

7+
.. note::
8+
9+
This guide is intended for advanced users who need support for something
10+
not provided by the :doc:`existing encoder plugins </reference/pixels.encoders>`.
11+
712
*Pixel Data* encoding in *pydicom* uses an :class:`~pydicom.pixels.encoders.base.Encoder`
813
instance for the specific *Transfer Syntax* as a manager for plugins that
914
perform the encoding work. This guide covers the requirements for those plugins
@@ -25,17 +30,26 @@ An encoding plugin must implement three objects within the same module:
2530

2631
.. code-block:: python
2732
28-
def foo(src: bytes, **kwargs: Any) -> bytes:
33+
def foo(src: bytes, runner: EncodeRunner) -> bytes | bytearray:
2934
30-
Where
35+
Where:
3136

3237
* `src` is the raw uncompressed data to be encoded as :class:`bytes`. When
33-
the data in `src` represents multi-byte values
34-
(such as 16-bit pixels), then `src` will use little-endian byte
35-
ordering by default. Support for big-endian byte ordering by the encoding
36-
function is completely optional.
37-
* `kwargs` is a :class:`dict` which at a minimum contains the following
38-
required keys:
38+
the data in `src` represents multi-byte values (such as 16-bit pixels), then
39+
`src` will use little-endian byte ordering by default. Support for big-endian
40+
byte ordering by the encoding function is completely optional.
41+
42+
The data in `src` will be sized as:
43+
44+
* 1 byte per sample for 0 < *Bits Stored* <= 8
45+
* 2 bytes per sample for 8 < *Bits Stored* <= 16
46+
* 4 bytes per sample for 16 < *Bits Stored* <= 32
47+
* 8 bytes per sample for 32 < *Bits Stored* <= 64
48+
49+
* `runner` is an :class:`~pydicom.pixels.encoders.base.EncodeRunner` instance
50+
that manages the encoding process and has access to the encoding options,
51+
either directly through the class properties or indirectly with the
52+
:meth:`~pydicom.pixels.encoders.base.EncodeRunner.get_option` method.
3953

4054
* ``'transfer_syntax_uid'``: :class:`~pydicom.uid.UID` - the intended
4155
*Transfer Syntax UID* of the encoded data.
@@ -59,15 +73,19 @@ An encoding plugin must implement three objects within the same module:
5973
* ``'photometric_interpretation'``: :class:`str` - the intended color space
6074
of the encoded data, such as ``'YBR_FULL'``
6175

62-
`kwargs` may also contain optional parameters intended to be used
63-
with the encoder function to allow customization of the encoding process
64-
or to provide additional functionality. Support for these optional
65-
parameters is not required, however.
76+
If your encoder needs to signal that one of the encoding option values needs
77+
to be modified then this can be done with the
78+
:meth:`~pydicom.pixels.encoders.base.EncodeRunner.set_option` method. This
79+
should only be done after successfully encoding the frame, as if the
80+
encoding fails changing the option value may cause issues with
81+
other encoding plugins that may also attempt to encode the same frame. It's also
82+
important to be aware that any changes you make will also affect following frames
83+
(if any).
6684

6785
At a minimum the encoding function must support the encoding of
6886
little-endian byte ordered data and should return the encoded
6987
data in a format meeting the requirements of the corresponding *Transfer
70-
Syntax UID* as :class:`bytes`.
88+
Syntax UID* as :class:`bytes` or :class:`bytearray`.
7189

7290
* A function named ``is_available`` with the following signature:
7391

doc/guides/encoding/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ Pixel Data Encoding
88
.. toctree::
99
:maxdepth: 1
1010

11+
jpeg_ls
1112
rle_lossless
1213

1314

14-
Encoding plugin information:
15+
Encoding plugin information:
1516

1617
.. toctree::
1718
:maxdepth: 1

0 commit comments

Comments
 (0)