Skip to content

Commit 3378438

Browse files
authored
Fix inconsistent byte ordering on big endian systems (#23)
1 parent 6442a38 commit 3378438

9 files changed

Lines changed: 103 additions & 15312 deletions

File tree

.github/dependabot.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# https://docs.github.com/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot#example-dependabotyml-file-for-github-actions
2+
3+
version: 2
4+
updates:
5+
6+
- package-ecosystem: "github-actions"
7+
directory: "/"
8+
schedule:
9+
# Check for updates to GitHub Actions every month
10+
interval: "monthly"

.github/workflows/pr-tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
strategy:
1313
fail-fast: false
1414
matrix:
15-
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
15+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
1616
arch: ['x64']
1717

1818
steps:
@@ -42,7 +42,7 @@ jobs:
4242
strategy:
4343
fail-fast: false
4444
matrix:
45-
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
45+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
4646

4747
steps:
4848
- uses: actions/checkout@v4
@@ -70,7 +70,7 @@ jobs:
7070
strategy:
7171
fail-fast: false
7272
matrix:
73-
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
73+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
7474

7575
steps:
7676
- uses: actions/checkout@v4

.github/workflows/release-wheels.yml

Lines changed: 61 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ jobs:
4242
matrix:
4343
include:
4444
# Windows 64 bit
45-
- os: windows-latest
46-
python: 38
47-
platform_id: win_amd64
4845
- os: windows-latest
4946
python: 39
5047
platform_id: win_amd64
@@ -57,12 +54,11 @@ jobs:
5754
- os: windows-latest
5855
python: 312
5956
platform_id: win_amd64
57+
- os: windows-latest
58+
python: 313
59+
platform_id: win_amd64
6060

6161
# Linux 64 bit manylinux2014
62-
- os: ubuntu-latest
63-
python: 38
64-
platform_id: manylinux_x86_64
65-
manylinux_image: manylinux2014
6662
- os: ubuntu-latest
6763
python: 39
6864
platform_id: manylinux_x86_64
@@ -79,11 +75,12 @@ jobs:
7975
python: 312
8076
platform_id: manylinux_x86_64
8177
manylinux_image: manylinux2014
78+
- os: ubuntu-latest
79+
python: 313
80+
platform_id: manylinux_x86_64
81+
manylinux_image: manylinux2014
8282

8383
# Linux aarch64
84-
- os: ubuntu-latest
85-
python: 38
86-
platform_id: manylinux_aarch64
8784
- os: ubuntu-latest
8885
python: 39
8986
platform_id: manylinux_aarch64
@@ -96,11 +93,11 @@ jobs:
9693
- os: ubuntu-latest
9794
python: 312
9895
platform_id: manylinux_aarch64
96+
- os: ubuntu-latest
97+
python: 313
98+
platform_id: manylinux_aarch64
9999

100100
# MacOS x86_64
101-
- os: macos-latest
102-
python: 38
103-
platform_id: macosx_x86_64
104101
- os: macos-latest
105102
python: 39
106103
platform_id: macosx_x86_64
@@ -113,11 +110,11 @@ jobs:
113110
- os: macos-latest
114111
python: 312
115112
platform_id: macosx_x86_64
113+
- os: macos-latest
114+
python: 313
115+
platform_id: macosx_x86_64
116116

117117
# MacOS arm64
118-
- os: macos-latest
119-
python: 38
120-
platform_id: macosx_arm64
121118
- os: macos-latest
122119
python: 39
123120
platform_id: macosx_arm64
@@ -130,6 +127,9 @@ jobs:
130127
- os: macos-latest
131128
python: 312
132129
platform_id: macosx_arm64
130+
- os: macos-latest
131+
python: 313
132+
platform_id: macosx_arm64
133133

134134
steps:
135135
- uses: actions/checkout@v4
@@ -145,12 +145,12 @@ jobs:
145145
- uses: actions/setup-python@v4
146146
name: Install Python
147147
with:
148-
python-version: '3.9'
148+
python-version: '3.10'
149149

150150
- name: Install dependencies
151151
run: |
152152
python -m pip install -U pip
153-
python -m pip install cibuildwheel>=2.16
153+
python -m pip install cibuildwheel>=2.21
154154
155155
- name: Build wheels
156156
env:
@@ -170,52 +170,53 @@ jobs:
170170
name: wheel-${{ matrix.python }}-${{ matrix.platform_id }}
171171
path: ./dist
172172

173-
test-package:
174-
name: Test built package
175-
needs: [ build-wheels, build-sdist ]
176-
runs-on: ubuntu-latest
177-
timeout-minutes: 30
178-
strategy:
179-
fail-fast: false
180-
matrix:
181-
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
182-
183-
steps:
184-
- name: Set up Python ${{ matrix.python-version }}
185-
uses: actions/setup-python@v5
186-
with:
187-
python-version: ${{ matrix.python-version }}
188-
189-
- name: Download the wheels
190-
uses: actions/download-artifact@v4
191-
with:
192-
path: dist/
193-
merge-multiple: true
194-
195-
- name: Install from package wheels and test
196-
run: |
197-
python -m venv testwhl
198-
source testwhl/bin/activate
199-
python -m pip install -U pip
200-
python -m pip install pytest numpy
201-
python -m pip install -U --pre --find-links dist/ pyjpegls
202-
python -m pytest --pyargs jpeg_ls.tests
203-
deactivate
204-
205-
- name: Install from package tarball and test
206-
run: |
207-
python -m venv testsrc
208-
source testsrc/bin/activate
209-
python -m pip install -U pip
210-
python -m pip install pytest numpy
211-
python -m pip install -U dist/pyjpegls*.tar.gz
212-
python -m pytest --pyargs jpeg_ls.tests
213-
deactivate
173+
# test-package:
174+
# name: Test built package
175+
# needs: [ build-wheels, build-sdist ]
176+
# runs-on: ubuntu-latest
177+
# timeout-minutes: 30
178+
# strategy:
179+
# fail-fast: false
180+
# matrix:
181+
# python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
182+
#
183+
# steps:
184+
# - name: Set up Python ${{ matrix.python-version }}
185+
# uses: actions/setup-python@v5
186+
# with:
187+
# python-version: ${{ matrix.python-version }}
188+
#
189+
# - name: Download the wheels
190+
# uses: actions/download-artifact@v4
191+
# with:
192+
# path: dist/
193+
# merge-multiple: true
194+
#
195+
# - name: Install from package wheels and test
196+
# run: |
197+
# python -m venv testwhl
198+
# source testwhl/bin/activate
199+
# python -m pip install -U pip
200+
# python -m pip install pytest numpy
201+
# python -m pip install -U --pre --find-links dist/ pyjpegls
202+
# python -m pytest --pyargs jpeg_ls.tests
203+
# deactivate
204+
#
205+
# - name: Install from package tarball and test
206+
# run: |
207+
# python -m venv testsrc
208+
# source testsrc/bin/activate
209+
# python -m pip install -U pip
210+
# python -m pip install pytest numpy
211+
# python -m pip install -U dist/pyjpegls*.tar.gz
212+
# python -m pytest --pyargs jpeg_ls.tests
213+
# deactivate
214214

215215
# See: https://github.com/pypa/gh-action-pypi-publish/discussions/15
216216
deploy:
217217
name: Upload wheels to PyPI
218-
needs: [ test-package ]
218+
# needs: [ test-package ]
219+
needs: [ build-wheels, build-sdist ]
219220
runs-on: ubuntu-latest
220221
timeout-minutes: 10
221222
environment:

jpeg_ls/CharLS.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def encode(
3131
interleave_mode: Union[int, None] = None
3232
) -> np.ndarray:
3333
"""Encode grey-scale image via JPEG-LS using CharLS implementation."""
34-
if data_image.dtype == np.uint16 and np.max(data_image) <= 255:
34+
if data_image.dtype.itemsize == 2 and np.max(data_image) <= 255:
3535
data_image = data_image.astype(np.uint8)
3636

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

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

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

0 commit comments

Comments
 (0)