Glymur 0.13.2.post1__py3-none-any.whl → 0.13.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {Glymur-0.13.2.post1.dist-info → Glymur-0.13.4.dist-info}/METADATA +1 -1
- {Glymur-0.13.2.post1.dist-info → Glymur-0.13.4.dist-info}/RECORD +11 -11
- {Glymur-0.13.2.post1.dist-info → Glymur-0.13.4.dist-info}/WHEEL +1 -1
- glymur/codestream.py +12 -6
- glymur/jp2box.py +8 -5
- glymur/jp2k.py +24 -26
- glymur/jp2kr.py +67 -38
- glymur/version.py +1 -1
- {Glymur-0.13.2.post1.dist-info → Glymur-0.13.4.dist-info}/LICENSE.txt +0 -0
- {Glymur-0.13.2.post1.dist-info → Glymur-0.13.4.dist-info}/entry_points.txt +0 -0
- {Glymur-0.13.2.post1.dist-info → Glymur-0.13.4.dist-info}/top_level.txt +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
glymur/__init__.py,sha256=k14IfdaYuTWXSpAIDR3LVDtXt9XKjr-ZSNXCyu8pQko,586
|
|
2
2
|
glymur/_iccprofile.py,sha256=_WfQsT-BqEWQzQVTtuY7tSXqPjOtwvWGW36rKxlLv1s,4148
|
|
3
|
-
glymur/codestream.py,sha256=
|
|
3
|
+
glymur/codestream.py,sha256=In4WjEhm9pjIOgrXOTzX-G2imF13K_o7aV8Dz4uOMhs,60295
|
|
4
4
|
glymur/command_line.py,sha256=jm-6dD2jcU_G7mJAJ0U5sanfG9kRy-j0-G3eSN_Ieek,7476
|
|
5
5
|
glymur/config.py,sha256=ceGulS8TN2OYiTPtq3mAdhXrCCRlxjuLmvN_UG0009Y,4139
|
|
6
6
|
glymur/core.py,sha256=IDkk8FESyukQTB10LHBZ4VQM36NwKE4CXCcuJ407Kzg,3638
|
|
7
|
-
glymur/jp2box.py,sha256=
|
|
8
|
-
glymur/jp2k.py,sha256=
|
|
9
|
-
glymur/jp2kr.py,sha256=
|
|
7
|
+
glymur/jp2box.py,sha256=qh1xUGKoGgVrUHq48yRcJAk7miJ__Udua8QHPTxpfQY,112434
|
|
8
|
+
glymur/jp2k.py,sha256=o2Pg0GgbLd4nto8woYFCmvVemrqMDKXWGgt64fZbjuQ,54520
|
|
9
|
+
glymur/jp2kr.py,sha256=hUxFRXaJI9qmnZ7wNPr_4N-c-JEP7YiM_ea4FpmWD_w,32358
|
|
10
10
|
glymur/options.py,sha256=Y777g4wpxPqRAF8s963goeAIogfLqIe_Dyd9f77MfmU,4428
|
|
11
11
|
glymur/tiff.py,sha256=2uoKfyoyPQWAsdPWB0IxW_npqpP4O10qVADQZf10jXs,41115
|
|
12
|
-
glymur/version.py,sha256=
|
|
12
|
+
glymur/version.py,sha256=aSurVIzgqNAnAJrBLPJKDh99onXgPAcWVn99bnX4wus,981
|
|
13
13
|
glymur/data/__init__.py,sha256=n2KZrHV15it7Wu4YCaBLXui1ZleQ30dnZ92dyP6q05k,955
|
|
14
14
|
glymur/data/goodstuff.j2k,sha256=xKQG68KMu33gYjRUDTQvam1Cue2tdio85rNp5J-rYZE,115220
|
|
15
15
|
glymur/data/heliov.jpx,sha256=KXnYdBZgl25jcGLu-m-QfhuP9pqUXV0Hp9HHEdJqr34,1399071
|
|
@@ -17,9 +17,9 @@ glymur/data/nemo.jp2,sha256=yJ1NkTEwU0B_gBtAiA1c5hxtGYSJtJgq6cHC2IHpj70,1132373
|
|
|
17
17
|
glymur/lib/__init__.py,sha256=JnM9oPfcZhBDLKo7_yLS-lIRQ1wXb1N9hKKQ-G7vYVk,127
|
|
18
18
|
glymur/lib/openjp2.py,sha256=VHCy_TnBSDqQ8YlIQHkyFqUXOQ2E5C3jxJoziG73s0I,45052
|
|
19
19
|
glymur/lib/tiff.py,sha256=2o29IzYTsprVR_C6VDNHOzqk_U7aUdCoLQ2fjiyyoaI,50777
|
|
20
|
-
Glymur-0.13.
|
|
21
|
-
Glymur-0.13.
|
|
22
|
-
Glymur-0.13.
|
|
23
|
-
Glymur-0.13.
|
|
24
|
-
Glymur-0.13.
|
|
25
|
-
Glymur-0.13.
|
|
20
|
+
Glymur-0.13.4.dist-info/LICENSE.txt,sha256=G9pvBgkJdPTtZqQmoRyIgAydtic1ZwWtOWBea9VMW7I,1077
|
|
21
|
+
Glymur-0.13.4.dist-info/METADATA,sha256=R0fok_sUg2bhWbDOWZowQ6jjzRJFBI5SNKhRCw_JkkI,1020
|
|
22
|
+
Glymur-0.13.4.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
23
|
+
Glymur-0.13.4.dist-info/entry_points.txt,sha256=inzxpDbDDfIxtdXpCncAHdAdwJfjtXt3xKvIOsuZsG8,93
|
|
24
|
+
Glymur-0.13.4.dist-info/top_level.txt,sha256=D0SvtBUoPxOs40OTRW3l-kjGFHM6VrXS8yZPK5Fx2wY,7
|
|
25
|
+
Glymur-0.13.4.dist-info/RECORD,,
|
glymur/codestream.py
CHANGED
|
@@ -736,7 +736,9 @@ class Codestream(object):
|
|
|
736
736
|
data = struct.unpack_from('>HIIIIIIIIH', read_buffer)
|
|
737
737
|
|
|
738
738
|
rsiz = data[0]
|
|
739
|
-
|
|
739
|
+
|
|
740
|
+
# Bit 14 (16384) signifies HTJ2K (JPH)
|
|
741
|
+
if rsiz not in _KNOWN_PROFILES and not np.bitwise_and(rsiz, 16384):
|
|
740
742
|
msg = f"Invalid profile: (Rsiz={rsiz})."
|
|
741
743
|
warnings.warn(msg, UserWarning)
|
|
742
744
|
|
|
@@ -767,11 +769,10 @@ class Codestream(object):
|
|
|
767
769
|
num_tiles_y = (xysiz[1] - xyosiz[1]) / (xytsiz[1] - xytosiz[1])
|
|
768
770
|
except ZeroDivisionError:
|
|
769
771
|
msg = (
|
|
770
|
-
f"Invalid tile specification
|
|
771
|
-
f"size of {xytsiz[1]} x {xytsiz[0]}
|
|
772
|
-
f"offset of {xytosiz[1]} x {xytsiz[0]}."
|
|
772
|
+
f"Invalid tile specification in SIZ segment at byte offset "
|
|
773
|
+
f"{offset}: tile size of {xytsiz[1]} x {xytsiz[0]}."
|
|
773
774
|
)
|
|
774
|
-
|
|
775
|
+
raise ZeroDivisionError(msg)
|
|
775
776
|
else:
|
|
776
777
|
numtiles = np.ceil(num_tiles_x) * np.ceil(num_tiles_y)
|
|
777
778
|
if numtiles > 65535:
|
|
@@ -1667,7 +1668,12 @@ class SIZsegment(Segment):
|
|
|
1667
1668
|
try:
|
|
1668
1669
|
profile = _CAPABILITIES_DISPLAY[self.rsiz]
|
|
1669
1670
|
except KeyError:
|
|
1670
|
-
|
|
1671
|
+
if np.bitwise_and(self.rsiz, 16384):
|
|
1672
|
+
# HTJ2K profile that is uninterpreted
|
|
1673
|
+
profile = f'{self.rsiz}'
|
|
1674
|
+
else:
|
|
1675
|
+
# profile unknown
|
|
1676
|
+
profile = f'{self.rsiz} (invalid)'
|
|
1671
1677
|
msg = msg.format(
|
|
1672
1678
|
profile=profile,
|
|
1673
1679
|
height=self.ysiz, width=self.xsiz,
|
glymur/jp2box.py
CHANGED
|
@@ -71,7 +71,7 @@ _EXIF_UUID = UUID(bytes=b'JpgTiffExif->JP2')
|
|
|
71
71
|
_XMP_UUID = UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
class InvalidJp2kWarning(
|
|
74
|
+
class InvalidJp2kWarning(UserWarning):
|
|
75
75
|
"""Issue this warning in case the file is technically invalid but we can
|
|
76
76
|
still read the image.
|
|
77
77
|
"""
|
|
@@ -1259,7 +1259,7 @@ class FileTypeBox(Jp2kBox):
|
|
|
1259
1259
|
"""
|
|
1260
1260
|
box_id = 'ftyp'
|
|
1261
1261
|
longname = 'File Type'
|
|
1262
|
-
_valid_cls = ['jp2 ', 'jpx ', 'jpxb']
|
|
1262
|
+
_valid_cls = ['jp2 ', 'jph ', 'jpx ', 'jpxb']
|
|
1263
1263
|
|
|
1264
1264
|
def __init__(
|
|
1265
1265
|
self, brand='jp2 ', minor_version=0, compatibility_list=None,
|
|
@@ -1304,16 +1304,19 @@ class FileTypeBox(Jp2kBox):
|
|
|
1304
1304
|
return text
|
|
1305
1305
|
|
|
1306
1306
|
def _validate(self, writing=False):
|
|
1307
|
-
"""
|
|
1308
|
-
|
|
1307
|
+
"""
|
|
1308
|
+
Validate the box before writing to file.
|
|
1309
|
+
"""
|
|
1310
|
+
if self.brand not in ['jp2 ', 'jpx ', 'jph ']:
|
|
1309
1311
|
msg = (
|
|
1310
1312
|
f"The file type brand was '{self.brand}'. "
|
|
1311
|
-
f"It should be either 'jp2 ' or '
|
|
1313
|
+
f"It should be either 'jp2 ', 'jpx ', or 'jph '."
|
|
1312
1314
|
)
|
|
1313
1315
|
if writing:
|
|
1314
1316
|
raise InvalidJp2kError(msg)
|
|
1315
1317
|
else:
|
|
1316
1318
|
warnings.warn(msg, UserWarning)
|
|
1319
|
+
|
|
1317
1320
|
for item in self.compatibility_list:
|
|
1318
1321
|
if item not in self._valid_cls:
|
|
1319
1322
|
msg = (
|
glymur/jp2k.py
CHANGED
|
@@ -206,13 +206,13 @@ class Jp2k(Jp2kr):
|
|
|
206
206
|
# Must be determined when writing.
|
|
207
207
|
self._shape = None
|
|
208
208
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
209
|
+
if not hasattr(self, '_codec_format'):
|
|
210
|
+
# Only set codec format if the superclass has not done so, i.e.
|
|
211
|
+
# we are writing instead of reading.
|
|
212
|
+
if self.filename[-4:].endswith(('.jp2', '.JP2', '.jpx', 'JPX')):
|
|
213
|
+
self._codec_format = opj2.CODEC_JP2
|
|
214
|
+
else:
|
|
215
|
+
self._codec_format = opj2.CODEC_J2K
|
|
216
216
|
|
|
217
217
|
self._validate_kwargs()
|
|
218
218
|
|
|
@@ -258,7 +258,7 @@ class Jp2k(Jp2kr):
|
|
|
258
258
|
header box if we were so instructed. This requires a wrapping
|
|
259
259
|
operation.
|
|
260
260
|
"""
|
|
261
|
-
jp2h =
|
|
261
|
+
jp2h = next(filter(lambda x: x.box_id == 'jp2h', self.box), None)
|
|
262
262
|
|
|
263
263
|
extra_boxes = []
|
|
264
264
|
if self._capture_resolution is not None:
|
|
@@ -1125,8 +1125,7 @@ class Jp2k(Jp2kr):
|
|
|
1125
1125
|
|
|
1126
1126
|
def _validate_jp2_colr(self, boxes):
|
|
1127
1127
|
"""Validate JP2 requirements on colour specification boxes."""
|
|
1128
|
-
|
|
1129
|
-
jp2h = lst[0]
|
|
1128
|
+
jp2h = next(filter(lambda x: x.box_id == 'jp2h', boxes), None)
|
|
1130
1129
|
for colr in [box for box in jp2h.box if box.box_id == 'colr']:
|
|
1131
1130
|
if colr.approximation != 0:
|
|
1132
1131
|
msg = (
|
|
@@ -1161,19 +1160,21 @@ class Jp2k(Jp2kr):
|
|
|
1161
1160
|
def _validate_jp2c(self, boxes):
|
|
1162
1161
|
"""Validate the codestream box in relation to other boxes."""
|
|
1163
1162
|
# jp2c must be preceeded by jp2h
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1163
|
+
jp2h_idx, _ = next(
|
|
1164
|
+
filter(lambda x: x[1].box_id == 'jp2h', enumerate(boxes)),
|
|
1165
|
+
(None, None)
|
|
1166
|
+
)
|
|
1167
|
+
jp2c_idx, _ = next(
|
|
1168
|
+
filter(lambda x: x[1].box_id == 'jp2c', enumerate(boxes)),
|
|
1169
|
+
(None, None)
|
|
1170
|
+
)
|
|
1171
|
+
if jp2c_idx is None:
|
|
1170
1172
|
msg = (
|
|
1171
1173
|
"A codestream box must be defined in the outermost list of "
|
|
1172
1174
|
"boxes."
|
|
1173
1175
|
)
|
|
1174
1176
|
raise InvalidJp2kError(msg)
|
|
1175
1177
|
|
|
1176
|
-
jp2c_idx = jp2c_lst[0]
|
|
1177
1178
|
if jp2h_idx >= jp2c_idx:
|
|
1178
1179
|
msg = "The codestream box must be preceeded by a jp2 header box."
|
|
1179
1180
|
raise InvalidJp2kError(msg)
|
|
@@ -1182,8 +1183,7 @@ class Jp2k(Jp2kr):
|
|
|
1182
1183
|
"""Validate the JP2 Header box."""
|
|
1183
1184
|
self._check_jp2h_child_boxes(boxes, 'top-level')
|
|
1184
1185
|
|
|
1185
|
-
|
|
1186
|
-
jp2h = jp2h_lst[0]
|
|
1186
|
+
jp2h = next(filter(lambda x: x.box_id == 'jp2h', boxes), None)
|
|
1187
1187
|
|
|
1188
1188
|
# 1st jp2 header box cannot be empty.
|
|
1189
1189
|
if len(jp2h.box) == 0:
|
|
@@ -1199,20 +1199,18 @@ class Jp2k(Jp2kr):
|
|
|
1199
1199
|
raise InvalidJp2kError(msg)
|
|
1200
1200
|
|
|
1201
1201
|
# colr must be present in jp2 header box.
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
]
|
|
1205
|
-
if len(colr_lst) == 0:
|
|
1202
|
+
colr = next(filter(lambda x: x.box_id == 'colr', jp2h.box), None)
|
|
1203
|
+
if colr is None:
|
|
1206
1204
|
msg = "The jp2 header box must contain a color definition box."
|
|
1207
1205
|
raise InvalidJp2kError(msg)
|
|
1208
|
-
colr = jp2h.box[colr_lst[0]]
|
|
1209
1206
|
|
|
1210
1207
|
self._validate_channel_definition(jp2h, colr)
|
|
1211
1208
|
|
|
1212
1209
|
def _validate_channel_definition(self, jp2h, colr):
|
|
1213
1210
|
"""Validate the channel definition box."""
|
|
1214
|
-
cdef_lst = [
|
|
1215
|
-
|
|
1211
|
+
cdef_lst = [
|
|
1212
|
+
idx for (idx, box) in enumerate(jp2h.box) if box.box_id == 'cdef'
|
|
1213
|
+
]
|
|
1216
1214
|
if len(cdef_lst) > 1:
|
|
1217
1215
|
msg = ("Only one channel definition box is allowed in the "
|
|
1218
1216
|
"JP2 header.")
|
glymur/jp2kr.py
CHANGED
|
@@ -9,11 +9,11 @@ License: MIT
|
|
|
9
9
|
# Standard library imports...
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
from contextlib import ExitStack
|
|
12
|
-
from itertools import filterfalse
|
|
13
12
|
import ctypes
|
|
14
13
|
import pathlib
|
|
15
14
|
import re
|
|
16
15
|
import struct
|
|
16
|
+
import sys
|
|
17
17
|
import warnings
|
|
18
18
|
|
|
19
19
|
# Third party library imports
|
|
@@ -22,7 +22,7 @@ import numpy as np
|
|
|
22
22
|
# Local imports...
|
|
23
23
|
from .codestream import Codestream
|
|
24
24
|
from . import core, version, get_option
|
|
25
|
-
from .jp2box import Jp2kBox, FileTypeBox, InvalidJp2kError
|
|
25
|
+
from .jp2box import Jp2kBox, FileTypeBox, InvalidJp2kError, InvalidJp2kWarning
|
|
26
26
|
from .lib import openjp2 as opj2
|
|
27
27
|
|
|
28
28
|
|
|
@@ -108,8 +108,8 @@ class Jp2kr(Jp2kBox):
|
|
|
108
108
|
num_components = len(cstr.segment[1].xrsiz)
|
|
109
109
|
else:
|
|
110
110
|
# try to get the image size from the IHDR box
|
|
111
|
-
jp2h =
|
|
112
|
-
ihdr =
|
|
111
|
+
jp2h = next(filter(lambda x: x.box_id == 'jp2h', self.box), None)
|
|
112
|
+
ihdr = next(filter(lambda x: x.box_id == 'ihdr', jp2h.box), None)
|
|
113
113
|
|
|
114
114
|
height, width = ihdr.height, ihdr.width
|
|
115
115
|
num_components = ihdr.num_components
|
|
@@ -189,10 +189,10 @@ class Jp2kr(Jp2kBox):
|
|
|
189
189
|
@layer.setter
|
|
190
190
|
def layer(self, layer):
|
|
191
191
|
# Set to the indicated value so long as it is valid.
|
|
192
|
-
cod =
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
cod = next(
|
|
193
|
+
filter(lambda x: x.marker_id == 'COD', self.codestream.segment),
|
|
194
|
+
None
|
|
195
|
+
)
|
|
196
196
|
if layer < 0 or layer >= cod.layers:
|
|
197
197
|
msg = f"Invalid layer number, must be in range [0, {cod.layers})."
|
|
198
198
|
raise ValueError(msg)
|
|
@@ -355,7 +355,13 @@ class Jp2kr(Jp2kBox):
|
|
|
355
355
|
# Don't bother trying to validate JPX.
|
|
356
356
|
return
|
|
357
357
|
|
|
358
|
-
jp2h =
|
|
358
|
+
jp2h = next(filter(lambda x: x.box_id == 'jp2h', self.box), None)
|
|
359
|
+
if jp2h is None:
|
|
360
|
+
msg = (
|
|
361
|
+
"No JP2 header box was located in the outermost jacket of "
|
|
362
|
+
"boxes."
|
|
363
|
+
)
|
|
364
|
+
raise InvalidJp2kError(msg)
|
|
359
365
|
|
|
360
366
|
# An IHDR box is required as the first child box of the JP2H box.
|
|
361
367
|
if jp2h.box[0].box_id != 'ihdr':
|
|
@@ -373,7 +379,7 @@ class Jp2kr(Jp2kBox):
|
|
|
373
379
|
"enumerated colorspace or a restricted ICC profile if the "
|
|
374
380
|
"file type box brand is 'jp2 '."
|
|
375
381
|
)
|
|
376
|
-
warnings.warn(msg,
|
|
382
|
+
warnings.warn(msg, InvalidJp2kWarning)
|
|
377
383
|
|
|
378
384
|
# We need to have one and only one JP2H box if we have a JP2 file.
|
|
379
385
|
num_jp2h_boxes = len([box for box in self.box if box.box_id == 'jp2h'])
|
|
@@ -382,7 +388,7 @@ class Jp2kr(Jp2kBox):
|
|
|
382
388
|
f"This file has {num_jp2h_boxes} JP2H boxes in the outermost "
|
|
383
389
|
"layer of boxes. There should only be one."
|
|
384
390
|
)
|
|
385
|
-
warnings.warn(msg)
|
|
391
|
+
warnings.warn(msg, InvalidJp2kWarning)
|
|
386
392
|
|
|
387
393
|
# We should have one and only one JP2C box if we have a JP2 file.
|
|
388
394
|
num_jp2c_boxes = len([box for box in self.box if box.box_id == 'jp2c'])
|
|
@@ -404,10 +410,10 @@ class Jp2kr(Jp2kBox):
|
|
|
404
410
|
ihdr = jp2h.box[0]
|
|
405
411
|
ihdr_dims = ihdr.height, ihdr.width, ihdr.num_components
|
|
406
412
|
|
|
407
|
-
siz =
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
413
|
+
siz = next(
|
|
414
|
+
filter(lambda x: x.marker_id == 'SIZ', self.codestream.segment),
|
|
415
|
+
None
|
|
416
|
+
)
|
|
411
417
|
|
|
412
418
|
siz_dims = (siz.ysiz, siz.xsiz, len(siz.bitdepth))
|
|
413
419
|
if ihdr_dims != siz_dims:
|
|
@@ -460,9 +466,9 @@ class Jp2kr(Jp2kBox):
|
|
|
460
466
|
if isinstance(pargs, tuple) and any(isinstance(x, int) for x in pargs):
|
|
461
467
|
# Replace the first such integer argument, replace it with a slice.
|
|
462
468
|
lst = list(pargs)
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
469
|
+
idx, _ = next(
|
|
470
|
+
filter(lambda x: isinstance(x[1], int), enumerate(lst)), None
|
|
471
|
+
)
|
|
466
472
|
lst[idx] = slice(pargs[idx], pargs[idx] + 1)
|
|
467
473
|
newindex = tuple(lst)
|
|
468
474
|
|
|
@@ -676,10 +682,13 @@ class Jp2kr(Jp2kBox):
|
|
|
676
682
|
# Must check the specified rlevel against the maximum.
|
|
677
683
|
if rlevel != 0:
|
|
678
684
|
# Must check the specified rlevel against the maximum.
|
|
679
|
-
cod_seg =
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
685
|
+
cod_seg = next(
|
|
686
|
+
filter(
|
|
687
|
+
lambda x: x.marker_id == 'COD',
|
|
688
|
+
self.codestream.segment
|
|
689
|
+
),
|
|
690
|
+
None
|
|
691
|
+
)
|
|
683
692
|
max_rlevel = cod_seg.num_res
|
|
684
693
|
if rlevel == -1:
|
|
685
694
|
# -1 is shorthand for the largest rlevel
|
|
@@ -889,25 +898,45 @@ class Jp2kr(Jp2kBox):
|
|
|
889
898
|
Vertical, Horizontal Subsampling: ((1, 1), (1, 1), (1, 1))
|
|
890
899
|
"""
|
|
891
900
|
with self.path.open('rb') as fptr:
|
|
901
|
+
|
|
902
|
+
# if it's just a raw codestream file, it's easy
|
|
892
903
|
if self._codec_format == opj2.CODEC_J2K:
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
904
|
+
return self._get_codestream(fptr, self.length, header_only)
|
|
905
|
+
|
|
906
|
+
# continue assuming JP2, must seek to the JP2C box and past its
|
|
907
|
+
# header
|
|
908
|
+
box = next(filter(lambda x: x.box_id == 'jp2c', self.box), None)
|
|
909
|
+
|
|
910
|
+
fptr.seek(box.offset)
|
|
911
|
+
read_buffer = fptr.read(8)
|
|
912
|
+
(box_length, _) = struct.unpack('>I4s', read_buffer)
|
|
913
|
+
if box_length == 0:
|
|
914
|
+
# The length of the box is presumed to last until the end
|
|
915
|
+
# of the file. Compute the effective length of the box.
|
|
916
|
+
box_length = self.path.stat().st_size - fptr.tell() + 8
|
|
917
|
+
elif box_length == 1:
|
|
918
|
+
# Seek past the XL field.
|
|
898
919
|
read_buffer = fptr.read(8)
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
codestream = Codestream(fptr, box_length - 8,
|
|
909
|
-
header_only=header_only)
|
|
920
|
+
box_length, = struct.unpack('>Q', read_buffer)
|
|
921
|
+
|
|
922
|
+
return self._get_codestream(fptr, box_length - 8, header_only)
|
|
923
|
+
|
|
924
|
+
def _get_codestream(self, fptr, length, header_only):
|
|
925
|
+
"""
|
|
926
|
+
Parsing errors can make for confusing errors sometimes, so catch any
|
|
927
|
+
such error and add context to it.
|
|
928
|
+
"""
|
|
910
929
|
|
|
930
|
+
try:
|
|
931
|
+
codestream = Codestream(fptr, length, header_only=header_only)
|
|
932
|
+
except Exception:
|
|
933
|
+
_, value, traceback = sys.exc_info()
|
|
934
|
+
msg = (
|
|
935
|
+
f'The file is invalid '
|
|
936
|
+
f'because the codestream could not be parsed: "{value}"'
|
|
937
|
+
)
|
|
938
|
+
raise InvalidJp2kError(msg).with_traceback(traceback)
|
|
939
|
+
else:
|
|
911
940
|
return codestream
|
|
912
941
|
|
|
913
942
|
def _validate_nonzero_image_size(self, nrows, ncols, component_index):
|
glymur/version.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|