Code Monkey home page Code Monkey logo

pylibjpeg-openjpeg's Introduction

unit-tests type-hints doc-build test-coverage Python version PyPI version DOI

pydicom

pydicom is a pure Python package for working with DICOM files. It lets you read, modify and write DICOM data in an easy "pythonic" way. As a pure Python package, pydicom can run anywhere Python runs without any other requirements, although if you're working with Pixel Data then we recommend you also install NumPy.

Note that pydicom is a general-purpose DICOM framework concerned with reading and writing DICOM datasets. In order to keep the project manageable, it does not handle the specifics of individual SOP classes or other aspects of DICOM. Other libraries both inside and outside the pydicom organization are based on pydicom and provide support for other aspects of DICOM, and for more specific applications.

Examples are pynetdicom, which is a Python library for DICOM networking, and deid, which supports the anonymization of DICOM files.

Installation

Using pip:

pip install pydicom

Using conda:

conda install -c conda-forge pydicom

For more information, including installation instructions for the development version, see the installation guide.

Documentation

The pydicom user guide, tutorials, examples and API reference documentation is available for both the current release and the development version on GitHub Pages.

Pixel Data

Compressed and uncompressed Pixel Data is always available to be read, changed and written as bytes:

>>> from pydicom import dcmread
>>> from pydicom.data import get_testdata_file
>>> path = get_testdata_file("CT_small.dcm")
>>> ds = dcmread(path)
>>> type(ds.PixelData)
<class 'bytes'>
>>> len(ds.PixelData)
32768
>>> ds.PixelData[:2]
b'\xaf\x00'

If NumPy is installed, Pixel Data can be converted to an ndarray using the Dataset.pixel_array property:

>>> arr = ds.pixel_array
>>> arr.shape
(128, 128)
>>> arr
array([[175, 180, 166, ..., 203, 207, 216],
       [186, 183, 157, ..., 181, 190, 239],
       [184, 180, 171, ..., 152, 164, 235],
       ...,
       [906, 910, 923, ..., 922, 929, 927],
       [914, 954, 938, ..., 942, 925, 905],
       [959, 955, 916, ..., 911, 904, 909]], dtype=int16)

Decompressing Pixel Data

JPEG, JPEG-LS and JPEG 2000

Converting JPEG, JPEG-LS or JPEG 2000 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.

RLE

Decompressing RLE Pixel Data only requires NumPy, however it can be quite slow. You may want to consider installing one or more additional Python libraries to speed up the process.

Compressing Pixel Data

Information on compressing Pixel Data using one of the below formats can be found in the corresponding encoding guides. These guides cover the specific requirements for each encoding method and we recommend you be familiar with them when performing image compression.

JPEG-LS, JPEG 2000

Compressing image data from an ndarray or bytes object to JPEG-LS or JPEG 2000 requires installing the following:

RLE

Compressing using RLE requires no additional packages but can be quite slow. It can be sped up by installing pylibjpeg with the pylibjpeg-rle plugin, or gdcm.

Examples

More examples are available in the documentation.

Change a patient's ID

from pydicom import dcmread

ds = dcmread("/path/to/file.dcm")
# Edit the (0010,0020) 'Patient ID' element
ds.PatientID = "12345678"
ds.save_as("/path/to/file_updated.dcm")

Display the Pixel Data

With NumPy and matplotlib

import matplotlib.pyplot as plt
from pydicom import dcmread
from pydicom.data import get_testdata_file

# The path to a pydicom test dataset
path = get_testdata_file("CT_small.dcm")
ds = dcmread(path)
# `arr` is a numpy.ndarray
arr = ds.pixel_array

plt.imshow(arr, cmap="gray")
plt.show()

Contributing

We are all volunteers working on pydicom in our free time. As our resources are limited, we very much value your contributions, be it bug fixes, new core features, or documentation improvements. For more information, please read our contribution guide.

If you have examples or extensions of pydicom that don't belong with the core software, but that you deem useful to others, you can add them to our contribution repository: contrib-pydicom.

pylibjpeg-openjpeg's People

Contributors

dependabot[bot] avatar jmsmkn avatar mrbean-bremen avatar scaramallion avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

pylibjpeg-openjpeg's Issues

Implement proper configuration of openjpeg during build

We need to run cmake so that it produces valid opj_config_private.h and opj_config.h headers, but without actually building the library.

Then during setup.py we should be able to just call cmake, then run the usual install. Hopefully...

Perhaps we can override the standard cmake file with a custom one that does only the bits we need?

`encode` lossless documentation correction

From encode documentation it seems that these calls should give the same result:

import numpy as np
from pydicom import dcmread
from openjpeg import encode, decode

dcm = dcmread("chest.dcm") 

with open('test_jpeg_1.j2k', 'wb') as f:
    f.write(encode(dcm.pixel_array))

with open('test_jpeg_2.j2k', 'wb') as f:
    f.write(encode(dcm.pixel_array, compression_ratios=[1]))

with open('test_jpeg_1.j2k', 'rb') as f:
    im_1 = decode(f.read())

with open('test_jpeg_2.j2k', 'rb') as f:
    im_2 = decode(f.read())

np.allclose(im_1, im_2)
# False

But they are not (the diff is small, but still). From function documentation:

"""
compression_ratios : list[float], optional. Required if using lossy encoding, this is the compression ratio to use for each layer. Should be in decreasing order (such as [80, 30, 10]) and the final value may be 1 to indicate lossless encoding should be used for that layer. Cannot be used with signal_noise_ratios.
"""

True lossless is achieved with encode(dcm.pixel_array) and encode(dcm.pixel_array, compression_ratios=[1]) results in a small residual.

*attached example CT dicom (single channel, grayscale, int16) from public data (just changed the extension to .txt, since github does not allow for .dcm), but you probably can reproduce with any other dicom.

chest.txt

Fix encoding with JP2 encapsulation

Because codec_format=2 doesn't work and JP2 is the only thing reason for supplying the photometric interpretation/colour space as it doesn't get tracked by a J2K codestream.

v1.0.0 Release

  • Confirm updated wheels work
  • Fix up that missing test coverage
  • Switch wheel building to only be on package release publishing

fail to install/run openjpeg

I am running Kaggle kernel with pydicom and failing on decompress some images, so I got to the point I know I need to manually decompress images, but then it seems to fail with come compatibility with numpy...

pip install -q pylibjpeg-libjpeg
pip install -qU "pylibjpeg==1.2" pylibjpeg-openjpeg --no-binary :all:

so I see installed:

pylibjpeg                      1.2.0
pylibjpeg-libjpeg              1.2.0
pylibjpeg-openjpeg             1.1.1

then calling import openjpeg fails with

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-66-80c0acc2a717> in <module>
      1 import pylibjpeg
      2 from pylibjpeg.pydicom.utils import get_pixel_data_decoders
----> 3 import openjpeg

/opt/conda/lib/python3.7/site-packages/openjpeg/__init__.py in <module>
      2 
      3 from ._version import __version__
----> 4 from .utils import decode, decode_pixel_data, get_parameters

/opt/conda/lib/python3.7/site-packages/openjpeg/utils.py in <module>
      5 import warnings
      6 
----> 7 import _openjpeg
      8 
      9 

/opt/conda/lib/python3.7/site-packages/openjpeg/_openjpeg.pyx in init _openjpeg()

ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 88 from C header, got 80 from PyObject

Pip install failing - unable to find build_tools

Background

I'm using a M1 mac mini dev machine, and have previously been using Anaconda based conda for managing environments. This only presently supports using mac x86 versions of everything, which while they work, use mac's rosetta to run the x86 code non-natively.

So I'm cleaning all that cruft out, and using native miniconda mac-arm versions of everything.

Everything has worked fine with installing native python and all the modules I use, right up until pylibjpeg. (Including pydicom, which uses noarch version and runs perfectly it seems so far).

Problem

Using pip (specifically miniconda's pip) to install pylibjpeg fails when trying to install pylibjpeg-openjpeg:

The problem is pip is pullling down pylibjpeg-openjpeg-1.1.1.tar.gz, and then setup.py is failing as its unable to find CMakeLists.txt.

A quick check by manually downloading pylibjpeg-openjpeg-1.1.1.tar.gz shows that the entire build_tools directory is missing:

(aqs-tests-2)  pylibjpeg-openjpeg-1.1.1 >> ls
MANIFEST.in                 README.md                   pylibjpeg_openjpeg.egg-info setup.py
PKG-INFO                    openjpeg                    setup.cfg
(aqs-tests-2)  pylibjpeg-openjpeg-1.1.1 >> find . -name build_tools
(aqs-tests-2)  pylibjpeg-openjpeg-1.1.1 >> ls openjpeg/
__init__.py   _openjpeg.pyx _version.py   src           tests         utils.py

Question
Should I be using a specific (different) tarball instead of what pip's defaulting to (pylibjpeg-openjpeg-1.1.1.tar.gz)?

Pip Install output:

Conda-arm-install-stuff >> pip download pylibjpeg
Collecting pylibjpeg
  Downloading pylibjpeg-1.3.0-py3-none-any.whl (28 kB)
Collecting pylibjpeg-openjpeg
  Downloading pylibjpeg-openjpeg-1.1.1.tar.gz (2.3 MB)
     |████████████████████████████████| 2.3 MB 2.1 MB/s 
    ERROR: Command errored out with exit status 1:
     command: /Users/rjm/miniforge3/envs/aqs-tests-2/bin/python3.8 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_93f9a1031bbc467692cd36833771bcd2/setup.py'"'"'; __file__='"'"'/private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_93f9a1031bbc467692cd36833771bcd2/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-pip-egg-info-lfbbjo5z
         cwd: /private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_93f9a1031bbc467692cd36833771bcd2/
    Complete output (11 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_93f9a1031bbc467692cd36833771bcd2/setup.py", line 87, in <module>
        setup_oj()
      File "/private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_93f9a1031bbc467692cd36833771bcd2/setup.py", line 60, in setup_oj
        shutil.copy(
      File "/Users/rjm/miniforge3/envs/aqs-tests-2/lib/python3.8/shutil.py", line 418, in copy
        copyfile(src, dst, follow_symlinks=follow_symlinks)
      File "/Users/rjm/miniforge3/envs/aqs-tests-2/lib/python3.8/shutil.py", line 264, in copyfile
        with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
    FileNotFoundError: [Errno 2] No such file or directory: 'build_tools/cmake/CMakeLists.txt'
    ----------------------------------------
WARNING: Discarding https://files.pythonhosted.org/packages/71/e9/94f3d009e9f9f31bb76075641214bdabdbe557b26ce74ff71ef1c28b2c05/pylibjpeg-openjpeg-1.1.1.tar.gz#sha256=e7adfd8e2c63661b75219d5ae381ac50381054df41ca94d0d01ddfbe362a66cc (from https://pypi.org/simple/pylibjpeg-openjpeg/) (requires-python:>=3.6). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
  Downloading pylibjpeg-openjpeg-1.1.0.tar.gz (2.3 MB)
     |████████████████████████████████| 2.3 MB 5.7 MB/s 
    ERROR: Command errored out with exit status 1:
     command: /Users/rjm/miniforge3/envs/aqs-tests-2/bin/python3.8 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_cafc2c9526f54399948b001f3b4ac833/setup.py'"'"'; __file__='"'"'/private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_cafc2c9526f54399948b001f3b4ac833/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-pip-egg-info-6b4peu5w
         cwd: /private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_cafc2c9526f54399948b001f3b4ac833/
    Complete output (11 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_cafc2c9526f54399948b001f3b4ac833/setup.py", line 87, in <module>
        setup_oj()
      File "/private/var/folders/t3/6rfnr3rd6jl7_jg08ppg5h3c0000gq/T/pip-download-3opfmxjo/pylibjpeg-openjpeg_cafc2c9526f54399948b001f3b4ac833/setup.py", line 60, in setup_oj
        shutil.copy(
      File "/Users/rjm/miniforge3/envs/aqs-tests-2/lib/python3.8/shutil.py", line 418, in copy
        copyfile(src, dst, follow_symlinks=follow_symlinks)
      File "/Users/rjm/miniforge3/envs/aqs-tests-2/lib/python3.8/shutil.py", line 264, in copyfile
        with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
    FileNotFoundError: [Errno 2] No such file or directory: 'build_tools/cmake/CMakeLists.txt'
    ----------------------------------------
WARNING: Discarding https://files.pythonhosted.org/packages/49/1c/43de9deec30e2a641a3a2f11efa6c13185fa2c77a962676e370a282a3814/pylibjpeg-openjpeg-1.1.0.tar.gz#sha256=66514f5d5df6fdfc704296a8420e4b1feb335fad4e6901435e00c37f353fb44e (from https://pypi.org/simple/pylibjpeg-openjpeg/) (requires-python:>=3.7). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
Collecting pylibjpeg
  Downloading pylibjpeg-1.2.0-py3-none-any.whl (27 kB)
  Downloading pylibjpeg-1.1.1-py3-none-any.whl (29 kB)
  Downloading pylibjpeg-1.1.0-py3-none-any.whl (29 kB)
  Downloading pylibjpeg-1.0.0-py2.py3-none-any.whl (31 kB)

Segmentation fault upon decoding of JPEG200 image

I encountered JPEG2000 images that the library fails to decode:

[ins] In [1]: from openjpeg import decode
         ...:
         ...: with open('example.j2k', 'rb') as f:
         ...:     arr = decode(f)
         ...:
Segmentation fault: 11

However, openjpeg is generally able to decode the same image correctly:

$ opj_decompress -i example.j2k -o example_openjpeg.png

[INFO] Start to read j2k main header (0).
[INFO] Main header has been correctly decoded.
[INFO] No decoded area parameters, set the decoded area to the whole image
[INFO] Header of tile 1 / 1 has been read.
[INFO] Generated Outfile example_openjpeg.png
decode time: 2 ms

I've attached the image as ZIP archive example.zip.

Wheel testing

It's time again to test our wheels work. And also (again), 😍cibuildwheel😍.

Wheels are here, you should run with pytest, pydicom and pylibjpeg-data installed.

python -c "import pytest; import openjpeg; pytest.main(['--pyargs', 'openjpeg.tests'])"

Getting to this stage was so much easier than with libjpeg, I enjoyed it more than I was expecting.

Install problems

Dear, when try to install with pip, a problem occur:

Building wheel for pylibjpeg-openjpeg (pyproject.toml) ... error
error: subprocess-exited-with-error

× Building wheel for pylibjpeg-openjpeg (pyproject.toml) did not run successfully.
│ exit code: 1
╰─> [40 lines of output]
fatal: not a git repository (or any of the parent directories): .git
A setup.py file already exists. Using it.

ERROR: Failed building wheel for pylibjpeg-openjpeg
Failed to build pylibjpeg-openjpeg
ERROR: Could not build wheels for pylibjpeg-openjpeg, which is required to install pyproject.toml-based projects

Enviroment:

Python 3.11.3
pip 23.3.2
MacOS 14.2.1

Cython/numpy build error when using 1.2.0

I was building my application, which uses pydicom==2.2.2 over a CI pipeline and this error appeared where it hadn't appeared before (no changes to pydicom-related code).
If I added pylibjpeg-openjpeg==1.1.1 to my requirements, thus forcing the use of an earlier version to 1.2.0, the error goes away.

Numpy version is numpy==1.21.2

Can anyone replicate?


File "/usr/local/lib/python3.9/site-packages/pydicom/__init__.py", line 32, in <module>
    from pydicom.dataelem import DataElement
  File "/usr/local/lib/python3.9/site-packages/pydicom/dataelem.py", line 18, in <module>
    from pydicom import config  # don't import datetime_conversion directly
  File "/usr/local/lib/python3.9/site-packages/pydicom/config.py", line 262, in <module>
    import pydicom.pixel_data_handlers.pylibjpeg_handler as pylibjpeg_handler  # noqa
  File "/usr/local/lib/python3.9/site-packages/pydicom/pixel_data_handlers/pylibjpeg_handler.py", line 76, in <module>
    import openjpeg
  File "/usr/local/lib/python3.9/site-packages/openjpeg/__init__.py", line 4, in <module>
    from .utils import decode, decode_pixel_data, get_parameters
  File "/usr/local/lib/python3.9/site-packages/openjpeg/utils.py", line 7, in <module>
    import _openjpeg
  File "openjpeg/_openjpeg.pyx", line 1, in init _openjpeg
ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject


Encoding random 1-bit images fails

There's an upstream issue with openjpeg not encoding 1-bit images correctly if they're over a certain size. Which I missed in testing because I set the upper limit on the random arrays incorrectly (range is [0, high), not [0, high]...)

Workaround is to use a precision of 2 instead.

Heap corruptions

Getting heap corruptions under Windows and OSX.

This is why I'm not a C programmer...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.