Glymur 0.13.4__tar.gz → 0.13.5__tar.gz
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.4 → glymur-0.13.5}/CHANGES.txt +5 -0
- {glymur-0.13.4 → glymur-0.13.5}/Glymur.egg-info/PKG-INFO +1 -1
- {glymur-0.13.4 → glymur-0.13.5}/PKG-INFO +1 -1
- {glymur-0.13.4 → glymur-0.13.5}/glymur/codestream.py +75 -1
- {glymur-0.13.4 → glymur-0.13.5}/glymur/jp2k.py +2 -38
- {glymur-0.13.4 → glymur-0.13.5}/glymur/jp2kr.py +22 -2
- {glymur-0.13.4 → glymur-0.13.5}/glymur/version.py +1 -1
- {glymur-0.13.4 → glymur-0.13.5}/setup.cfg +1 -1
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_codestream.py +13 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_jp2k.py +2 -2
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_jp2kr.py +2 -2
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_printing.py +16 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_threading.py +3 -3
- {glymur-0.13.4 → glymur-0.13.5}/Glymur.egg-info/SOURCES.txt +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/Glymur.egg-info/dependency_links.txt +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/Glymur.egg-info/entry_points.txt +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/Glymur.egg-info/not-zip-safe +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/Glymur.egg-info/requires.txt +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/Glymur.egg-info/top_level.txt +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/LICENSE.txt +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/MANIFEST.in +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/README.md +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/__init__.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/_iccprofile.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/command_line.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/config.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/core.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/data/__init__.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/data/goodstuff.j2k +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/data/heliov.jpx +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/data/nemo.jp2 +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/jp2box.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/lib/__init__.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/lib/openjp2.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/lib/tiff.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/options.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/glymur/tiff.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/pyproject.toml +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_callbacks.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_cinema.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_colour_specification_box.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_config.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_geo.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_jp2box.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_jp2box_jpx.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_jp2box_uuid.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_jp2box_xml.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_jp2k_writes.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_libtiff.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_openjp2.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_set_decoded_components.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_slicing.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_tiff2jp2.py +0 -0
- {glymur-0.13.4 → glymur-0.13.5}/tests/test_warnings.py +0 -0
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
July 26, 2024 - v0.13.5
|
|
2
|
+
Add support for parsing the CAP segment.
|
|
3
|
+
End official support for OpenJPEG 2.3.x.
|
|
4
|
+
Fix issue preventing API docs from building.
|
|
5
|
+
|
|
1
6
|
July 4, 2024 - v0.13.4
|
|
2
7
|
Don't reset openjpeg codec in Jp2k if already set in Jp2kr.
|
|
3
8
|
Update CI configuration to specify openjpeg versions.
|
|
@@ -189,7 +189,7 @@ class Codestream(object):
|
|
|
189
189
|
0xff3f: self._parse_reserved_marker,
|
|
190
190
|
|
|
191
191
|
# 0xff4f: SOC (already encountered by the time we get here)
|
|
192
|
-
0xff50: self.
|
|
192
|
+
0xff50: self._parse_cap_segment,
|
|
193
193
|
0xff51: self._parse_siz_segment,
|
|
194
194
|
0xff52: self._parse_cod_segment,
|
|
195
195
|
0xff53: self._parse_coc_segment,
|
|
@@ -713,6 +713,37 @@ class Codestream(object):
|
|
|
713
713
|
|
|
714
714
|
return RGNsegment(crgn, srgn, sprgn, length, offset)
|
|
715
715
|
|
|
716
|
+
@classmethod
|
|
717
|
+
def _parse_cap_segment(cls, fptr):
|
|
718
|
+
"""Parse the SIZ segment.
|
|
719
|
+
|
|
720
|
+
Parameters
|
|
721
|
+
----------
|
|
722
|
+
fptr : file
|
|
723
|
+
Open file object.
|
|
724
|
+
|
|
725
|
+
Returns
|
|
726
|
+
-------
|
|
727
|
+
SIZSegment
|
|
728
|
+
The current SIZ segment.
|
|
729
|
+
"""
|
|
730
|
+
offset = fptr.tell() - 2
|
|
731
|
+
|
|
732
|
+
read_buffer = fptr.read(2)
|
|
733
|
+
length, = struct.unpack('>H', read_buffer)
|
|
734
|
+
read_buffer = fptr.read(length - 2)
|
|
735
|
+
|
|
736
|
+
pcap, = struct.unpack('>I', read_buffer[:4])
|
|
737
|
+
|
|
738
|
+
n = (length - 6) // 2
|
|
739
|
+
ccap = struct.unpack('>' + 'H' * n, read_buffer[4:])
|
|
740
|
+
|
|
741
|
+
segment = CAPsegment(
|
|
742
|
+
pcap=pcap, ccap=ccap, length=length, offset=offset,
|
|
743
|
+
)
|
|
744
|
+
|
|
745
|
+
return segment
|
|
746
|
+
|
|
716
747
|
@classmethod
|
|
717
748
|
def _parse_siz_segment(cls, fptr):
|
|
718
749
|
"""Parse the SIZ segment.
|
|
@@ -934,6 +965,49 @@ class Segment(object):
|
|
|
934
965
|
return msg
|
|
935
966
|
|
|
936
967
|
|
|
968
|
+
class CAPsegment(Segment):
|
|
969
|
+
"""CAP (Extended Capabilities) segment information.
|
|
970
|
+
|
|
971
|
+
Attributes
|
|
972
|
+
----------
|
|
973
|
+
marker_id : str
|
|
974
|
+
Identifier for the segment.
|
|
975
|
+
offset : int
|
|
976
|
+
Offset of marker segment in bytes from beginning of file.
|
|
977
|
+
length : int
|
|
978
|
+
Length of marker segment in bytes. This number does not include the
|
|
979
|
+
two bytes constituting the marker.
|
|
980
|
+
pcap : 32-bit unsigned int
|
|
981
|
+
bitmask where the kth 1 represents use of capabilities in Part k of
|
|
982
|
+
ISO/IEC 15444-k.
|
|
983
|
+
ccap : 16-bit unsigned int
|
|
984
|
+
The precise meaning depends on the related parts of ISO/IEC 15444-k.
|
|
985
|
+
"""
|
|
986
|
+
def __init__(self, pcap, ccap, length, offset):
|
|
987
|
+
super().__init__(marker_id='CAP')
|
|
988
|
+
self.pcap = pcap
|
|
989
|
+
self.ccap = ccap
|
|
990
|
+
self.length = length
|
|
991
|
+
self.offset = offset
|
|
992
|
+
|
|
993
|
+
def __str__(self):
|
|
994
|
+
msg = Segment.__str__(self)
|
|
995
|
+
|
|
996
|
+
msg += '\n'
|
|
997
|
+
|
|
998
|
+
# have to cast to uint64 because, you know, stupid windows
|
|
999
|
+
parts = [
|
|
1000
|
+
k for k in range(32)
|
|
1001
|
+
if np.bitwise_and(np.uint64(self.pcap), np.uint64(1 << (32 - k)))
|
|
1002
|
+
]
|
|
1003
|
+
|
|
1004
|
+
for b in parts:
|
|
1005
|
+
msg += f' Pcap: Part {b} (ISO/IEC 15444-{b})\n'
|
|
1006
|
+
msg += f' Ccap: {self.ccap}'
|
|
1007
|
+
|
|
1008
|
+
return msg
|
|
1009
|
+
|
|
1010
|
+
|
|
937
1011
|
class COCsegment(Segment):
|
|
938
1012
|
"""COC (Coding style Component) segment information.
|
|
939
1013
|
|
|
@@ -34,13 +34,12 @@ from .lib import openjp2 as opj2
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class Jp2k(Jp2kr):
|
|
37
|
-
"""Write JPEG 2000 files.
|
|
37
|
+
"""Write JPEG 2000 files (and optionally read them as well).
|
|
38
38
|
|
|
39
39
|
Parameters
|
|
40
40
|
----------
|
|
41
41
|
filename : str or path
|
|
42
|
-
The path to JPEG 2000 file.
|
|
43
|
-
this is the only argument you need to supply.
|
|
42
|
+
The path to JPEG 2000 file.
|
|
44
43
|
data : np.ndarray, optional
|
|
45
44
|
Image data to be written to file.
|
|
46
45
|
shape : Tuple[int, int, ...], optional
|
|
@@ -105,35 +104,6 @@ class Jp2k(Jp2kr):
|
|
|
105
104
|
verbose : bool, optional
|
|
106
105
|
Print informational messages produced by the OpenJPEG library.
|
|
107
106
|
|
|
108
|
-
Examples
|
|
109
|
-
--------
|
|
110
|
-
>>> jfile = glymur.data.nemo()
|
|
111
|
-
>>> jp2 = glymur.Jp2k(jfile)
|
|
112
|
-
>>> jp2.shape
|
|
113
|
-
(1456, 2592, 3)
|
|
114
|
-
>>> image = jp2[:]
|
|
115
|
-
>>> image.shape
|
|
116
|
-
(1456, 2592, 3)
|
|
117
|
-
|
|
118
|
-
Read a lower resolution thumbnail.
|
|
119
|
-
|
|
120
|
-
>>> thumbnail = jp2[::2, ::2]
|
|
121
|
-
>>> thumbnail.shape
|
|
122
|
-
(728, 1296, 3)
|
|
123
|
-
|
|
124
|
-
Make use of OpenJPEG's thread support
|
|
125
|
-
|
|
126
|
-
>>> import time
|
|
127
|
-
>>> if glymur.version.openjpeg_version >= '2.2.0':
|
|
128
|
-
... jp2file = glymur.data.nemo()
|
|
129
|
-
... jp2 = glymur.Jp2k(jp2file)
|
|
130
|
-
... t0 = time.time(); data = jp2[:]; t1 = time.time()
|
|
131
|
-
... t1 - t0 #doctest: +SKIP
|
|
132
|
-
0.9024193286895752
|
|
133
|
-
... glymur.set_options('lib.num_threads', 4)
|
|
134
|
-
... t0 = time.time(); data = jp2[:]; t1 = time.time()
|
|
135
|
-
... t1 - t0 #doctest: +SKIP
|
|
136
|
-
0.4060473537445068
|
|
137
107
|
"""
|
|
138
108
|
|
|
139
109
|
def __init__(
|
|
@@ -800,12 +770,6 @@ class Jp2k(Jp2kr):
|
|
|
800
770
|
-------
|
|
801
771
|
Jp2k
|
|
802
772
|
Newly wrapped Jp2k object.
|
|
803
|
-
|
|
804
|
-
Examples
|
|
805
|
-
--------
|
|
806
|
-
>>> jfile = glymur.data.goodstuff()
|
|
807
|
-
>>> j2k = glymur.Jp2k(jfile)
|
|
808
|
-
>>> jp2 = j2k.wrap('jp2_from_j2k.jp2')
|
|
809
773
|
"""
|
|
810
774
|
if boxes is None:
|
|
811
775
|
boxes = self._get_default_jp2_boxes()
|
|
@@ -55,6 +55,19 @@ class Jp2kr(Jp2kBox):
|
|
|
55
55
|
>>> thumbnail = jp2[::2, ::2]
|
|
56
56
|
>>> thumbnail.shape
|
|
57
57
|
(728, 1296, 3)
|
|
58
|
+
|
|
59
|
+
Make use of OpenJPEG's thread support
|
|
60
|
+
|
|
61
|
+
>>> import time
|
|
62
|
+
>>> jp2file = glymur.data.nemo()
|
|
63
|
+
>>> jp2 = glymur.Jp2k(jp2file)
|
|
64
|
+
>>> t0 = time.time(); data = jp2[:]; t1 = time.time()
|
|
65
|
+
>>> t1 - t0 #doctest: +SKIP
|
|
66
|
+
0.9024193286895752
|
|
67
|
+
>>> glymur.set_option('lib.num_threads', 4)
|
|
68
|
+
>>> t0 = time.time(); data = jp2[:]; t1 = time.time()
|
|
69
|
+
>>> t1 - t0 #doctest: +SKIP
|
|
70
|
+
0.4060473537445068
|
|
58
71
|
"""
|
|
59
72
|
|
|
60
73
|
def __init__(
|
|
@@ -233,7 +246,7 @@ class Jp2kr(Jp2kBox):
|
|
|
233
246
|
|
|
234
247
|
@property
|
|
235
248
|
def codestream(self):
|
|
236
|
-
"""Metadata for JP2 or J2K codestream
|
|
249
|
+
"""Metadata for JP2 or J2K codestream header."""
|
|
237
250
|
if self._codestream is None:
|
|
238
251
|
self._codestream = self.get_codestream(header_only=True)
|
|
239
252
|
return self._codestream
|
|
@@ -523,6 +536,9 @@ class Jp2kr(Jp2kBox):
|
|
|
523
536
|
def read(self, **kwargs):
|
|
524
537
|
"""Read a JPEG 2000 image.
|
|
525
538
|
|
|
539
|
+
.. deprecated:: 0.13.5
|
|
540
|
+
Use numpy-style slicing instead.
|
|
541
|
+
|
|
526
542
|
Returns
|
|
527
543
|
-------
|
|
528
544
|
img_array : ndarray
|
|
@@ -724,7 +740,7 @@ class Jp2kr(Jp2kBox):
|
|
|
724
740
|
verbose=False, ignore_pclr_cmap_cdef=False):
|
|
725
741
|
"""Read a JPEG 2000 image.
|
|
726
742
|
|
|
727
|
-
The only time you should use this method is when the image has
|
|
743
|
+
The only time you should ever use this method is when the image has
|
|
728
744
|
different subsampling factors across components. Otherwise you should
|
|
729
745
|
use the read method.
|
|
730
746
|
|
|
@@ -870,6 +886,10 @@ class Jp2kr(Jp2kBox):
|
|
|
870
886
|
def get_codestream(self, header_only=True):
|
|
871
887
|
"""Retrieve codestream.
|
|
872
888
|
|
|
889
|
+
This differs from the codestream property in that segment
|
|
890
|
+
metadata that lies past the end of the codestream header
|
|
891
|
+
can be retrieved.
|
|
892
|
+
|
|
873
893
|
Parameters
|
|
874
894
|
----------
|
|
875
895
|
header_only : bool, optional
|
|
@@ -30,6 +30,19 @@ class TestSuite(fixtures.TestCommon):
|
|
|
30
30
|
self.p1_06 = ir.files('tests.data').joinpath('p1_06.j2k')
|
|
31
31
|
self.issue142 = ir.files('tests.data').joinpath('issue142.j2k')
|
|
32
32
|
self.edf_c2_1178956 = ir.files('tests.data').joinpath('edf_c2_1178956.jp2') # noqa : E501
|
|
33
|
+
self.htj2k = ir.files('tests.data').joinpath('oj-ht-byte.jph')
|
|
34
|
+
|
|
35
|
+
def test_cap_marker_segment(self):
|
|
36
|
+
"""
|
|
37
|
+
SCENARIO: the file has a CAP marker segment for the 3rd segment
|
|
38
|
+
|
|
39
|
+
EXPECTED RESULT: the segment metadata is verified
|
|
40
|
+
"""
|
|
41
|
+
j = Jp2k(self.htj2k)
|
|
42
|
+
cap = j.codestream.segment[2]
|
|
43
|
+
|
|
44
|
+
self.assertEqual(cap.pcap, 131072)
|
|
45
|
+
self.assertEqual(cap.ccap, (3,))
|
|
33
46
|
|
|
34
47
|
def test_unrecognized_marker(self):
|
|
35
48
|
"""
|
|
@@ -29,8 +29,8 @@ from . import fixtures
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
@unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG)
|
|
32
|
-
@unittest.skipIf(glymur.version.openjpeg_version < '2.
|
|
33
|
-
"Requires as least v2.
|
|
32
|
+
@unittest.skipIf(glymur.version.openjpeg_version < '2.4.0',
|
|
33
|
+
"Requires as least v2.4.0")
|
|
34
34
|
class TestJp2k(fixtures.TestCommon):
|
|
35
35
|
"""These tests should be run by just about all configuration."""
|
|
36
36
|
|
|
@@ -29,8 +29,8 @@ from . import fixtures
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
@unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG)
|
|
32
|
-
@unittest.skipIf(glymur.version.openjpeg_version < '2.
|
|
33
|
-
"Requires as least v2.
|
|
32
|
+
@unittest.skipIf(glymur.version.openjpeg_version < '2.4.0',
|
|
33
|
+
"Requires as least v2.4.0")
|
|
34
34
|
class TestJp2kr(fixtures.TestCommon):
|
|
35
35
|
"""These tests should be run by just about all configuration."""
|
|
36
36
|
|
|
@@ -42,6 +42,22 @@ class TestPrinting(fixtures.TestCommon):
|
|
|
42
42
|
super().tearDown()
|
|
43
43
|
glymur.reset_option('all')
|
|
44
44
|
|
|
45
|
+
def test_cap_segment(self):
|
|
46
|
+
"""
|
|
47
|
+
Scenario: Print a CAP segment
|
|
48
|
+
|
|
49
|
+
Expected Result: segment is verified
|
|
50
|
+
"""
|
|
51
|
+
htj2k_file = ir.files('tests.data').joinpath('oj-ht-byte.jph')
|
|
52
|
+
j = glymur.Jp2kr(htj2k_file)
|
|
53
|
+
actual = str(j.codestream.segment[2])
|
|
54
|
+
expected = (
|
|
55
|
+
'CAP marker segment @ (467, 8)\n'
|
|
56
|
+
' Pcap: Part 15 (ISO/IEC 15444-15)\n'
|
|
57
|
+
' Ccap: (3,)'
|
|
58
|
+
)
|
|
59
|
+
self.assertEqual(actual, expected)
|
|
60
|
+
|
|
45
61
|
def test_empty_file(self):
|
|
46
62
|
"""
|
|
47
63
|
SCENARIO: Print the file after with object is constructed, but
|
|
@@ -22,8 +22,8 @@ from . import fixtures
|
|
|
22
22
|
|
|
23
23
|
@unittest.skipIf(os.cpu_count() < 2, "makes no sense if 2 cores not there")
|
|
24
24
|
@unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG)
|
|
25
|
-
@unittest.skipIf(glymur.version.openjpeg_version < '2.
|
|
26
|
-
"Requires as least v2.
|
|
25
|
+
@unittest.skipIf(glymur.version.openjpeg_version < '2.4.0',
|
|
26
|
+
"Requires as least v2.4.0")
|
|
27
27
|
class TestSuite(fixtures.TestCommon):
|
|
28
28
|
"""Test behavior when multiple threads are possible."""
|
|
29
29
|
|
|
@@ -79,7 +79,7 @@ class TestSuite(fixtures.TestCommon):
|
|
|
79
79
|
glymur.set_option('lib.num_threads', 2)
|
|
80
80
|
|
|
81
81
|
@unittest.skipIf(
|
|
82
|
-
glymur.version.openjpeg_version < '2.4.0', "Requires as least v2.
|
|
82
|
+
glymur.version.openjpeg_version < '2.4.0', "Requires as least v2.4.0"
|
|
83
83
|
)
|
|
84
84
|
def test_threads_write_support__ge_2p4(self):
|
|
85
85
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|