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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Glymur
3
- Version: 0.13.2.post1
3
+ Version: 0.13.4
4
4
  Home-page: https://github.com/quintusdias/glymur
5
5
  Author: 'John Evans'
6
6
  Author-email: "John Evans" <jevans667cc@proton.me>
@@ -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=SEAudOSnGT1yWz-zDeIvDPmr7T1Gqhwc0tfErCHOBQw,60028
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=bRzsq3UtZDVkM-_swwAdieSNZM7RsIE4tRNvOM1vnVo,112391
8
- glymur/jp2k.py,sha256=TfHsP6ozMCKFcP26r_ouHw-GVD3OY_UChAh-EAJsKD4,54555
9
- glymur/jp2kr.py,sha256=Jju0hNfLane24wqR8amQqiSR1qSNCxNydVC8FXQMOFQ,31497
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=SyTlhhJibQo-BAOWfdWM6AHvrP2kTaf9LwDg1wmpCwY,987
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.2.post1.dist-info/LICENSE.txt,sha256=G9pvBgkJdPTtZqQmoRyIgAydtic1ZwWtOWBea9VMW7I,1077
21
- Glymur-0.13.2.post1.dist-info/METADATA,sha256=mwhG68eNzkHr3io8UL_arGeWPK0Mu0ygYezBTS3g9uE,1026
22
- Glymur-0.13.2.post1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
23
- Glymur-0.13.2.post1.dist-info/entry_points.txt,sha256=inzxpDbDDfIxtdXpCncAHdAdwJfjtXt3xKvIOsuZsG8,93
24
- Glymur-0.13.2.post1.dist-info/top_level.txt,sha256=D0SvtBUoPxOs40OTRW3l-kjGFHM6VrXS8yZPK5Fx2wY,7
25
- Glymur-0.13.2.post1.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
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
- if rsiz not in _KNOWN_PROFILES:
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
- warnings.warn(msg, UserWarning)
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
- profile = f'{self.rsiz} (invalid)'
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(RuntimeError):
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
- """Validate the box before writing to file."""
1308
- if self.brand not in ['jp2 ', 'jpx ']:
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 'jpx '."
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
- # If there already was a shape attribute, then don't mess with it,
210
- # it was set by the reader superclass.
211
-
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
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 = [box for box in self.box if box.box_id == 'jp2h'][0]
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
- lst = [box for box in boxes if box.box_id == 'jp2h']
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
- jp2h_lst = [idx for (idx, box) in enumerate(boxes)
1165
- if box.box_id == 'jp2h']
1166
- jp2h_idx = jp2h_lst[0]
1167
- jp2c_lst = [idx for (idx, box) in enumerate(boxes)
1168
- if box.box_id == 'jp2c']
1169
- if len(jp2c_lst) == 0:
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
- jp2h_lst = [box for box in boxes if box.box_id == 'jp2h']
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
- colr_lst = [
1203
- j for (j, box) in enumerate(jp2h.box) if box.box_id == 'colr'
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 = [j for (j, box) in enumerate(jp2h.box)
1215
- if box.box_id == 'cdef']
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 = [box for box in self.box if box.box_id == 'jp2h'][0]
112
- ihdr = [box for box in jp2h.box if box.box_id == 'ihdr'][0]
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
- segment for segment in self.codestream.segment
194
- if segment.marker_id == 'COD'
195
- ][0]
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 = [box for box in self.box if box.box_id == 'jp2h'][0]
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, UserWarning)
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
- segment for segment in self.codestream.segment
409
- if segment.marker_id == 'SIZ'
410
- ][0]
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
- g = filterfalse(lambda x: not isinstance(x[1], int),
464
- enumerate(pargs))
465
- idx = next(g)[0]
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
- segment for segment in self.codestream.segment
681
- if segment.marker_id == 'COD'
682
- ][0]
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
- codestream = Codestream(fptr, self.length,
894
- header_only=header_only)
895
- else:
896
- box = [x for x in self.box if x.box_id == 'jp2c']
897
- fptr.seek(box[0].offset)
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
- (box_length, _) = struct.unpack('>I4s', read_buffer)
900
- if box_length == 0:
901
- # The length of the box is presumed to last until the end
902
- # of the file. Compute the effective length of the box.
903
- box_length = self.path.stat().st_size - fptr.tell() + 8
904
- elif box_length == 1:
905
- # Seek past the XL field.
906
- read_buffer = fptr.read(8)
907
- box_length, = struct.unpack('>Q', read_buffer)
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
@@ -20,7 +20,7 @@ from .lib import tiff
20
20
 
21
21
  # Do not change the format of this next line! Doing so risks breaking
22
22
  # setup.py
23
- version = "0.13.2.post1"
23
+ version = "0.13.4"
24
24
 
25
25
  version_tuple = parse(version).release
26
26