Skip to content

Commit

Permalink
Fix inconsistent byte ordering on big endian systems (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
scaramallion authored Oct 27, 2024
1 parent 6442a38 commit 3378438
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 15,312 deletions.
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# https://docs.github.com/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot#example-dependabotyml-file-for-github-actions

version: 2
updates:

- package-ecosystem: "github-actions"
directory: "/"
schedule:
# Check for updates to GitHub Actions every month
interval: "monthly"
6 changes: 3 additions & 3 deletions .github/workflows/pr-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
arch: ['x64']

steps:
Expand Down Expand Up @@ -42,7 +42,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -70,7 +70,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']

steps:
- uses: actions/checkout@v4
Expand Down
121 changes: 61 additions & 60 deletions .github/workflows/release-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ jobs:
matrix:
include:
# Windows 64 bit
- os: windows-latest
python: 38
platform_id: win_amd64
- os: windows-latest
python: 39
platform_id: win_amd64
Expand All @@ -57,12 +54,11 @@ jobs:
- os: windows-latest
python: 312
platform_id: win_amd64
- os: windows-latest
python: 313
platform_id: win_amd64

# Linux 64 bit manylinux2014
- os: ubuntu-latest
python: 38
platform_id: manylinux_x86_64
manylinux_image: manylinux2014
- os: ubuntu-latest
python: 39
platform_id: manylinux_x86_64
Expand All @@ -79,11 +75,12 @@ jobs:
python: 312
platform_id: manylinux_x86_64
manylinux_image: manylinux2014
- os: ubuntu-latest
python: 313
platform_id: manylinux_x86_64
manylinux_image: manylinux2014

# Linux aarch64
- os: ubuntu-latest
python: 38
platform_id: manylinux_aarch64
- os: ubuntu-latest
python: 39
platform_id: manylinux_aarch64
Expand All @@ -96,11 +93,11 @@ jobs:
- os: ubuntu-latest
python: 312
platform_id: manylinux_aarch64
- os: ubuntu-latest
python: 313
platform_id: manylinux_aarch64

# MacOS x86_64
- os: macos-latest
python: 38
platform_id: macosx_x86_64
- os: macos-latest
python: 39
platform_id: macosx_x86_64
Expand All @@ -113,11 +110,11 @@ jobs:
- os: macos-latest
python: 312
platform_id: macosx_x86_64
- os: macos-latest
python: 313
platform_id: macosx_x86_64

# MacOS arm64
- os: macos-latest
python: 38
platform_id: macosx_arm64
- os: macos-latest
python: 39
platform_id: macosx_arm64
Expand All @@ -130,6 +127,9 @@ jobs:
- os: macos-latest
python: 312
platform_id: macosx_arm64
- os: macos-latest
python: 313
platform_id: macosx_arm64

steps:
- uses: actions/checkout@v4
Expand All @@ -145,12 +145,12 @@ jobs:
- uses: actions/setup-python@v4
name: Install Python
with:
python-version: '3.9'
python-version: '3.10'

- name: Install dependencies
run: |
python -m pip install -U pip
python -m pip install cibuildwheel>=2.16
python -m pip install cibuildwheel>=2.21
- name: Build wheels
env:
Expand All @@ -170,52 +170,53 @@ jobs:
name: wheel-${{ matrix.python }}-${{ matrix.platform_id }}
path: ./dist

test-package:
name: Test built package
needs: [ build-wheels, build-sdist ]
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Download the wheels
uses: actions/download-artifact@v4
with:
path: dist/
merge-multiple: true

- name: Install from package wheels and test
run: |
python -m venv testwhl
source testwhl/bin/activate
python -m pip install -U pip
python -m pip install pytest numpy
python -m pip install -U --pre --find-links dist/ pyjpegls
python -m pytest --pyargs jpeg_ls.tests
deactivate
- name: Install from package tarball and test
run: |
python -m venv testsrc
source testsrc/bin/activate
python -m pip install -U pip
python -m pip install pytest numpy
python -m pip install -U dist/pyjpegls*.tar.gz
python -m pytest --pyargs jpeg_ls.tests
deactivate
# test-package:
# name: Test built package
# needs: [ build-wheels, build-sdist ]
# runs-on: ubuntu-latest
# timeout-minutes: 30
# strategy:
# fail-fast: false
# matrix:
# python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
#
# steps:
# - name: Set up Python ${{ matrix.python-version }}
# uses: actions/setup-python@v5
# with:
# python-version: ${{ matrix.python-version }}
#
# - name: Download the wheels
# uses: actions/download-artifact@v4
# with:
# path: dist/
# merge-multiple: true
#
# - name: Install from package wheels and test
# run: |
# python -m venv testwhl
# source testwhl/bin/activate
# python -m pip install -U pip
# python -m pip install pytest numpy
# python -m pip install -U --pre --find-links dist/ pyjpegls
# python -m pytest --pyargs jpeg_ls.tests
# deactivate
#
# - name: Install from package tarball and test
# run: |
# python -m venv testsrc
# source testsrc/bin/activate
# python -m pip install -U pip
# python -m pip install pytest numpy
# python -m pip install -U dist/pyjpegls*.tar.gz
# python -m pytest --pyargs jpeg_ls.tests
# deactivate

# See: https://github.com/pypa/gh-action-pypi-publish/discussions/15
deploy:
name: Upload wheels to PyPI
needs: [ test-package ]
# needs: [ test-package ]
needs: [ build-wheels, build-sdist ]
runs-on: ubuntu-latest
timeout-minutes: 10
environment:
Expand Down
19 changes: 9 additions & 10 deletions jpeg_ls/CharLS.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def encode(
interleave_mode: Union[int, None] = None
) -> np.ndarray:
"""Encode grey-scale image via JPEG-LS using CharLS implementation."""
if data_image.dtype == np.uint16 and np.max(data_image) <= 255:
if data_image.dtype.itemsize == 2 and np.max(data_image) <= 255:
data_image = data_image.astype(np.uint8)

buffer = encode_array(data_image, lossy_error, interleave_mode)
Expand Down Expand Up @@ -129,11 +129,8 @@ def encode_array(
bytearray
The encoded JPEG-LS codestream.
"""
if arr.dtype == np.uint8:
bytes_per_pixel = 1
elif arr.dtype == np.uint16:
bytes_per_pixel = 2
else:
bytes_per_pixel = arr.dtype.itemsize
if bytes_per_pixel not in (1, 2) or arr.dtype.kind != "u":
raise ValueError(
f"Invalid ndarray dtype '{arr.dtype}', expecting np.uint8 or np.uint16."
)
Expand Down Expand Up @@ -309,7 +306,7 @@ def encode_pixel_data(src: bytes, lossy_error: int = 0, **kwargs: Any) -> bytear
Parameters
----------
src : bytes
The image data to be JPEG-LS encoded.
The little-endian ordered image data to be JPEG-LS encoded.
lossy_error : int, optional
The absolute value of the allowable error when encoding using
near-lossless, default ``0`` (lossless). For example, if using 8-bit
Expand Down Expand Up @@ -384,7 +381,7 @@ def jlsread(src: JLSSourceType) -> np.ndarray:
im, info = decode_buffer(buffer)

bytes_per_pixel = math.ceil(info["bits_per_sample"] / 8)
arr = np.frombuffer(im, dtype=f"u{bytes_per_pixel}")
arr = np.frombuffer(im, dtype=f"<u{bytes_per_pixel}")
rows = info["height"]
columns = info["width"]
samples_per_pixel = info["components"]
Expand Down Expand Up @@ -413,7 +410,8 @@ def decode_buffer(src: Union[bytes, bytearray]) -> Tuple[bytearray, Dict[str, in
Returns
-------
tuple[bytearray, dict[str, int]]
The decoded (image data, image metadata).
The decoded (image data, image metadata). The image data will use little-endian
byte ordering for multi-byte pixels.
"""
return _CharLS._decode(src), _CharLS.read_header(src)

Expand All @@ -437,6 +435,7 @@ def decode_pixel_data(src: Union[bytes, bytearray], **kwargs: Any) -> Tuple[byte
Returns
-------
tuple[bytearray, dict[str, int]]
The decoded (image data, image metadata).
The decoded (image data, image metadata). The image data will use little-endian
byte ordering for multi-byte pixels.
"""
return decode_buffer(src)
Loading

0 comments on commit 3378438

Please sign in to comment.