Glymur 0.13.2__py3-none-any.whl → 0.13.3__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
3
+ Version: 0.13.3
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=qZbCCJGrsIy4Q9zzeITNN_bP90HtCHFOcbZdInDfAAY,60011
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=-fprGcnwgm4HC9D8jxWmvsMZbDdum6C1Zc4cCJWNIZM,112390
8
+ glymur/jp2k.py,sha256=QS1bIi013b0AWRPvc90kwdVXMwblbJXU8MvP9zigy3g,54455
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=cZkWxcbr-Q_AtvUzLgMC56iNcQlSQAlxP7cAdc_gDMQ,981
12
+ glymur/version.py,sha256=dGkLU9MNyK0Ikb9XIC4M4aoDNPJQDZ0zq1OTF7zgtiU,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.dist-info/LICENSE.txt,sha256=G9pvBgkJdPTtZqQmoRyIgAydtic1ZwWtOWBea9VMW7I,1077
21
- Glymur-0.13.2.dist-info/METADATA,sha256=PDbSJZb5dVVoi8a2wYuFW2-Sr_4RK6teOaaQBcvQ7mM,1020
22
- Glymur-0.13.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
23
- Glymur-0.13.2.dist-info/entry_points.txt,sha256=inzxpDbDDfIxtdXpCncAHdAdwJfjtXt3xKvIOsuZsG8,93
24
- Glymur-0.13.2.dist-info/top_level.txt,sha256=D0SvtBUoPxOs40OTRW3l-kjGFHM6VrXS8yZPK5Fx2wY,7
25
- Glymur-0.13.2.dist-info/RECORD,,
20
+ Glymur-0.13.3.dist-info/LICENSE.txt,sha256=G9pvBgkJdPTtZqQmoRyIgAydtic1ZwWtOWBea9VMW7I,1077
21
+ Glymur-0.13.3.dist-info/METADATA,sha256=dCBeH__9F8mkVEsr9w8_5KpWn92be25pGQY7IAlqGy0,1020
22
+ Glymur-0.13.3.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
23
+ Glymur-0.13.3.dist-info/entry_points.txt,sha256=inzxpDbDDfIxtdXpCncAHdAdwJfjtXt3xKvIOsuZsG8,93
24
+ Glymur-0.13.3.dist-info/top_level.txt,sha256=D0SvtBUoPxOs40OTRW3l-kjGFHM6VrXS8yZPK5Fx2wY,7
25
+ Glymur-0.13.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
glymur/codestream.py CHANGED
@@ -767,11 +767,10 @@ class Codestream(object):
767
767
  num_tiles_y = (xysiz[1] - xyosiz[1]) / (xytsiz[1] - xytosiz[1])
768
768
  except ZeroDivisionError:
769
769
  msg = (
770
- f"Invalid tile specification: "
771
- f"size of {xytsiz[1]} x {xytsiz[0]}, "
772
- f"offset of {xytosiz[1]} x {xytsiz[0]}."
770
+ f"Invalid tile specification in SIZ segment at byte offset "
771
+ f"{offset}: tile size of {xytsiz[1]} x {xytsiz[0]}."
773
772
  )
774
- warnings.warn(msg, UserWarning)
773
+ raise ZeroDivisionError(msg)
775
774
  else:
776
775
  numtiles = np.ceil(num_tiles_x) * np.ceil(num_tiles_y)
777
776
  if numtiles > 65535:
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
  """
glymur/jp2k.py CHANGED
@@ -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"
23
+ version = "0.13.3"
24
24
 
25
25
  version_tuple = parse(version).release
26
26