Skip to content

Commit 328b7a7

Browse files
authored
Changes for updated plugin interface (#15)
1 parent c25e462 commit 328b7a7

8 files changed

Lines changed: 500 additions & 406 deletions

File tree

LICENSE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
pylibjpeg
2-
---------
1+
pylibjpeg-libjpeg
2+
-----------------
33

44
https://github.com/scaramallion/pylibjpeg
55

libjpeg/_libjpeg.cpp

Lines changed: 442 additions & 364 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libjpeg/_libjpeg.pyx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ def decode(np.ndarray[np.uint8_t, ndim=1] input_buffer, colourspace):
6464
cdef char *pInput = <char *>np.PyArray_DATA(input_buffer)
6565

6666
# Create array for output and get pointer to first element
67-
bpp = ceil(param['bits_per_sample'] / 8)
67+
bpp = ceil(param['precision'] / 8)
6868
nr_bytes = (
69-
param['rows'] * param['columns'] * param['samples_per_pixel'] * bpp
69+
param['rows'] * param['columns'] * param['nr_components'] * bpp
7070
)
7171
output_buffer = np.zeros(nr_bytes, dtype=np.uint8)
7272
cdef char *pOutput = <char *>np.PyArray_DATA(output_buffer)
@@ -118,8 +118,8 @@ def get_parameters(np.ndarray[np.uint8_t, ndim=1] input_buffer):
118118
parameters = {
119119
'rows' : param.rows,
120120
'columns' : param.columns,
121-
'samples_per_pixel' : param.samples_per_pixel,
122-
'bits_per_sample' : param.bits_per_sample,
121+
'nr_components' : param.samples_per_pixel,
122+
'precision' : param.bits_per_sample,
123123
}
124124

125125
return status, parameters

libjpeg/tests/pydicom_handler.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ def get_pixeldata(ds):
138138
for frame, offset in zip(generate_frames, generate_offsets):
139139
# Encoded JPG data to be sent to the decoder
140140
frame = np.frombuffer(frame, np.uint8)
141-
arr[offset:offset + frame_len] = decode_pixel_data(frame, p_interp)
141+
arr[offset:offset + frame_len] = decode_pixel_data(
142+
frame, ds.group_dataset(0x0028)
143+
)
142144

143145
return arr.view(pixel_dtype(ds))

libjpeg/tests/test_decode.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,9 @@ def test_invalid_colourspace_warns():
102102
nr_frames = ds.get('NumberOfFrames', 1)
103103
frame = next(generate_pixel_data_frame(ds.PixelData, nr_frames))
104104
msg = r"no colour transformation will be applied"
105+
ds.PhotometricInterpretation = 'ANY'
105106
with pytest.warns(UserWarning, match=msg):
106-
arr = decode_pixel_data(np.frombuffer(frame, 'uint8'), 'ANY')
107+
arr = decode_pixel_data(np.frombuffer(frame, 'uint8'), ds)
107108

108109
arr = reshape_pixel_array(ds, arr)
109110

libjpeg/tests/test_parameters.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ def test_get_parameters_bytes():
7777
info = (257, 255, 4, 8)
7878

7979
assert (info[0], info[1]) == (params['rows'], params['columns'])
80-
assert info[2] == params['samples_per_pixel']
81-
assert info[3] == params['bits_per_sample']
80+
assert info[2] == params["nr_components"]
81+
assert info[3] == params["precision"]
8282

8383

8484
@pytest.mark.skipif(not HAS_PYDICOM, reason="No pydicom")
@@ -128,8 +128,8 @@ def test_baseline(self, fname, info):
128128
params = get_parameters(np.frombuffer(frame, 'uint8'))
129129

130130
assert (info[0], info[1]) == (params['rows'], params['columns'])
131-
assert info[2] == params['samples_per_pixel']
132-
assert info[3] == params['bits_per_sample']
131+
assert info[2] == params["nr_components"]
132+
assert info[3] == params["precision"]
133133

134134
@pytest.mark.parametrize("fname, info", REF_DCM['1.2.840.10008.1.2.4.51'])
135135
def test_extended(self, fname, info):
@@ -142,8 +142,8 @@ def test_extended(self, fname, info):
142142
params = get_parameters(np.frombuffer(frame, 'uint8'))
143143

144144
assert (info[0], info[1]) == (params['rows'], params['columns'])
145-
assert info[2] == params['samples_per_pixel']
146-
assert info[3] == params['bits_per_sample']
145+
assert info[2] == params["nr_components"]
146+
assert info[3] == params["precision"]
147147

148148
@pytest.mark.parametrize("fname, info", REF_DCM['1.2.840.10008.1.2.4.57'])
149149
def test_lossless(self, fname, info):
@@ -156,8 +156,8 @@ def test_lossless(self, fname, info):
156156
params = get_parameters(np.frombuffer(frame, 'uint8'))
157157

158158
assert (info[0], info[1]) == (params['rows'], params['columns'])
159-
assert info[2] == params['samples_per_pixel']
160-
assert info[3] == params['bits_per_sample']
159+
assert info[2] == params["nr_components"]
160+
assert info[3] == params["precision"]
161161

162162
@pytest.mark.parametrize("fname, info", REF_DCM['1.2.840.10008.1.2.4.70'])
163163
def test_lossless_sv1(self, fname, info):
@@ -170,8 +170,8 @@ def test_lossless_sv1(self, fname, info):
170170
params = get_parameters(np.frombuffer(frame, 'uint8'))
171171

172172
assert (info[0], info[1]) == (params['rows'], params['columns'])
173-
assert info[2] == params['samples_per_pixel']
174-
assert info[3] == params['bits_per_sample']
173+
assert info[2] == params["nr_components"]
174+
assert info[3] == params["precision"]
175175

176176
@pytest.mark.parametrize("fname, info", REF_DCM['1.2.840.10008.1.2.4.80'])
177177
def test_extended(self, fname, info):
@@ -184,8 +184,8 @@ def test_extended(self, fname, info):
184184
params = get_parameters(np.frombuffer(frame, 'uint8'))
185185

186186
assert (info[0], info[1]) == (params['rows'], params['columns'])
187-
assert info[2] == params['samples_per_pixel']
188-
assert info[3] == params['bits_per_sample']
187+
assert info[2] == params["nr_components"]
188+
assert info[3] == params["precision"]
189189

190190
@pytest.mark.parametrize("fname, info", REF_DCM['1.2.840.10008.1.2.4.81'])
191191
def test_extended(self, fname, info):
@@ -198,8 +198,8 @@ def test_extended(self, fname, info):
198198
params = get_parameters(np.frombuffer(frame, 'uint8'))
199199

200200
assert (info[0], info[1]) == (params['rows'], params['columns'])
201-
assert info[2] == params['samples_per_pixel']
202-
assert info[3] == params['bits_per_sample']
201+
assert info[2] == params["nr_components"]
202+
assert info[3] == params["precision"]
203203

204204

205205
REF_JPG = {
@@ -264,8 +264,8 @@ def test_baseline(self, fname, info):
264264
params = get_parameters(np.frombuffer(data, 'uint8'))
265265

266266
assert (info[0], info[1]) == (params['rows'], params['columns'])
267-
assert info[2] == params['samples_per_pixel']
268-
assert info[3] == params['bits_per_sample']
267+
assert info[2] == params["nr_components"]
268+
assert info[3] == params["precision"]
269269

270270
@pytest.mark.parametrize("fname, info", REF_JPG['10918']['p2'])
271271
def test_extended_p2(self, fname, info):
@@ -277,8 +277,8 @@ def test_extended_p2(self, fname, info):
277277
params = get_parameters(np.frombuffer(data, 'uint8'))
278278

279279
assert (info[0], info[1]) == (params['rows'], params['columns'])
280-
assert info[2] == params['samples_per_pixel']
281-
assert info[3] == params['bits_per_sample']
280+
assert info[2] == params["nr_components"]
281+
assert info[3] == params["precision"]
282282

283283
@pytest.mark.parametrize("fname, info", REF_JPG['10918']['p4'])
284284
def test_extended_p4(self, fname, info):
@@ -290,8 +290,8 @@ def test_extended_p4(self, fname, info):
290290
params = get_parameters(np.frombuffer(data, 'uint8'))
291291

292292
assert (info[0], info[1]) == (params['rows'], params['columns'])
293-
assert info[2] == params['samples_per_pixel']
294-
assert info[3] == params['bits_per_sample']
293+
assert info[2] == params["nr_components"]
294+
assert info[3] == params["precision"]
295295

296296
@pytest.mark.parametrize("fname, info", REF_JPG['10918']['p14'])
297297
def test_lossless_p14(self, fname, info):
@@ -303,8 +303,8 @@ def test_lossless_p14(self, fname, info):
303303
params = get_parameters(np.frombuffer(data, 'uint8'))
304304

305305
assert (info[0], info[1]) == (params['rows'], params['columns'])
306-
assert info[2] == params['samples_per_pixel']
307-
assert info[3] == params['bits_per_sample']
306+
assert info[2] == params["nr_components"]
307+
assert info[3] == params["precision"]
308308

309309
@pytest.mark.parametrize("fname, info", REF_JPG['14495']['JLS'])
310310
def test_jls(self, fname, info):
@@ -316,5 +316,5 @@ def test_jls(self, fname, info):
316316
params = get_parameters(np.frombuffer(data, 'uint8'))
317317

318318
assert (info[0], info[1]) == (params['rows'], params['columns'])
319-
assert info[2] == params['samples_per_pixel']
320-
assert info[3] == params['bits_per_sample']
319+
assert info[2] == params["nr_components"]
320+
assert info[3] == params["precision"]

libjpeg/utils.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,16 @@ def decode(arr, colour_transform=0, reshape=True):
8787
status = status.decode("utf-8")
8888
code, msg = status.split("::::")
8989
code = int(code)
90+
print(params)
9091

9192
if code == 0 and reshape is True:
92-
bpp = ceil(params['bits_per_sample'] / 8)
93+
bpp = ceil(params["precision"] / 8)
9394
if bpp == 2:
9495
out = out.view('uint16')
9596

9697
shape = [params['rows'], params['columns']]
97-
if params['samples_per_pixel'] > 1:
98-
shape.append(params['samples_per_pixel'])
98+
if params["nr_components"] > 1:
99+
shape.append(params["nr_components"])
99100

100101
return out.reshape(*shape)
101102
elif code == 0 and reshape is False:
@@ -113,7 +114,7 @@ def decode(arr, colour_transform=0, reshape=True):
113114
)
114115

115116

116-
def decode_pixel_data(arr, photometric_interp):
117+
def decode_pixel_data(arr, ds):
117118
"""Return the decoded JPEG data from `arr` as a :class:`numpy.ndarray`.
118119
119120
Intended for use with *pydicom* ``Dataset`` objects.
@@ -123,10 +124,12 @@ def decode_pixel_data(arr, photometric_interp):
123124
arr : numpy.ndarray or bytes
124125
A 1D array of ``np.uint8``, or a Python :class:`bytes` object
125126
containing the encoded JPEG image.
126-
photometric_interp : str
127-
The (0028,0004) *Photometric Interpretation* of the pixel data, one of
128-
``'MONOCHROME1'``, ``'MONOCHROME2'``, ``'RGB'``, ``'YBR_FULL'``,
129-
``'YBR_FULL_422'``.
127+
ds : pydicom.dataset.Dataset
128+
A :class:`~pydicom.dataset.Dataset` containing the group ``0x0028``
129+
elements corresponding to the *Pixel Data*. Must contain a
130+
(0028,0004) *Photometric Interpretation* element with the colour
131+
space of the pixel data, one of ``'MONOCHROME1'``, ``'MONOCHROME2'``,
132+
``'RGB'``, ``'YBR_FULL'``, ``'YBR_FULL_422'``.
130133
131134
Returns
132135
-------
@@ -146,6 +149,14 @@ def decode_pixel_data(arr, photometric_interp):
146149
'YBR_FULL_422' : 0,
147150
}
148151

152+
if 'PhotometricInterpretation' not in ds:
153+
raise ValueError(
154+
"The (0028,0004) Photometric Interpretation element is missing "
155+
"from the dataset"
156+
)
157+
158+
photometric_interp = ds.PhotometricInterpretation
159+
149160
try:
150161
transform = colours[photometric_interp]
151162
except KeyError:
@@ -171,8 +182,8 @@ def get_parameters(arr):
171182
-------
172183
dict
173184
A :class:`dict` containing JPEG image parameters with keys including
174-
``'rows'``, ``'columns'``, ``'samples_per_pixel'`` and
175-
``'bits_per_sample'``.
185+
``'rows'``, ``'columns'``, ``"nr_components"`` and
186+
``"precision"``.
176187
177188
Raises
178189
------

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,5 +206,7 @@ def get_source_files():
206206
"1.2.840.10008.1.2.4.81 = libjpeg:decode_pixel_data",
207207
],
208208
'pylibjpeg.jpeg_decoders': 'libjpeg = libjpeg:decode',
209+
'pylibjpeg.jpeg_ls_decoders': 'libjpeg = libjpeg:decode',
210+
'pylibjpeg.jpeg_xt_decoders': 'libjpeg = libjpeg:decode',
209211
},
210212
)

0 commit comments

Comments
 (0)