merge branch 'issue315' into devel
This commit is contained in:
commit
05e343b2e4
13 changed files with 386 additions and 140 deletions
|
|
@ -15,7 +15,7 @@ or if you use windows, then read on.
|
||||||
|
|
||||||
Glymur uses ctypes to access the openjp2/openjpeg libraries, and
|
Glymur uses ctypes to access the openjp2/openjpeg libraries, and
|
||||||
because ctypes accesses libraries in a platform-dependent manner,
|
because ctypes accesses libraries in a platform-dependent manner,
|
||||||
it is recommended that if you compile and install OpenJPEG into a
|
it is recommended that **if** you compile and install OpenJPEG into a
|
||||||
non-standard location, you should then create a configuration file
|
non-standard location, you should then create a configuration file
|
||||||
to help Glymur properly find the openjpeg or openjp2 libraries
|
to help Glymur properly find the openjpeg or openjp2 libraries
|
||||||
(linux users or macports users don’t need to bother with this if
|
(linux users or macports users don’t need to bother with this if
|
||||||
|
|
@ -50,6 +50,9 @@ installed in a non-standard place, i.e. ::
|
||||||
[library]
|
[library]
|
||||||
openjpeg: /somewhere/lib/libopenjpeg.so
|
openjpeg: /somewhere/lib/libopenjpeg.so
|
||||||
|
|
||||||
|
Once again, you should not have to bother with a configuration file if you use
|
||||||
|
mac or linux and OpenJPEG is provided by your package manager.
|
||||||
|
|
||||||
'''''''
|
'''''''
|
||||||
Testing
|
Testing
|
||||||
'''''''
|
'''''''
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,7 @@ Changes in 0.8.0
|
||||||
=================
|
=================
|
||||||
|
|
||||||
* Simplified writing images by moving data and options into the
|
* Simplified writing images by moving data and options into the
|
||||||
constructor. This is backwards-incompatible with 0.7.x.
|
constructor.
|
||||||
|
* The main_header attribute of the ContiguousCodestream class is now called
|
||||||
|
codestream.
|
||||||
* Deprecated :py:meth:`read` method in favor of array-style slicing.
|
* Deprecated :py:meth:`read` method in favor of array-style slicing.
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import argparse
|
||||||
import os
|
import os
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from . import Jp2k, set_printoptions, lib
|
from . import Jp2k, set_printoptions, set_parseoptions, lib
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
@ -13,23 +13,25 @@ def main():
|
||||||
Entry point for console script jp2dump.
|
Entry point for console script jp2dump.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
description = 'Print JPEG2000 metadata.'
|
kwargs = {'description': 'Print JPEG2000 metadata.',
|
||||||
parser = argparse.ArgumentParser(description=description)
|
'formatter_class': argparse.ArgumentDefaultsHelpFormatter}
|
||||||
|
parser = argparse.ArgumentParser(**kwargs)
|
||||||
|
|
||||||
parser.add_argument('-x', '--noxml',
|
parser.add_argument('-x', '--noxml',
|
||||||
help='Suppress XML.',
|
help='suppress XML',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
parser.add_argument('-s', '--short',
|
parser.add_argument('-s', '--short',
|
||||||
help='Only print box id, offset, and length.',
|
help='only print box id, offset, and length',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
|
|
||||||
chelp = 'Level of codestream information. 0 suppressed all details, '
|
chelp = 'Level of codestream information. 0 suppresses all details, '
|
||||||
chelp += '1 prints headers, 2 prints the full codestream'
|
chelp += '1 prints the main header, 2 prints the full codestream.'
|
||||||
parser.add_argument('-c', '--codestream',
|
parser.add_argument('-c', '--codestream',
|
||||||
help=chelp,
|
help=chelp,
|
||||||
|
metavar='LEVEL',
|
||||||
nargs=1,
|
nargs=1,
|
||||||
type=int,
|
type=int,
|
||||||
default=[0])
|
default=[1])
|
||||||
|
|
||||||
parser.add_argument('filename')
|
parser.add_argument('filename')
|
||||||
|
|
||||||
|
|
@ -45,11 +47,8 @@ def main():
|
||||||
|
|
||||||
if codestream_level == 0:
|
if codestream_level == 0:
|
||||||
set_printoptions(codestream=False)
|
set_printoptions(codestream=False)
|
||||||
print_full_codestream = False
|
elif codestream_level == 2:
|
||||||
elif codestream_level == 1:
|
set_parseoptions(full_codestream=True)
|
||||||
print_full_codestream = False
|
|
||||||
else:
|
|
||||||
print_full_codestream = True
|
|
||||||
|
|
||||||
filename = args.filename
|
filename = args.filename
|
||||||
|
|
||||||
|
|
@ -58,11 +57,14 @@ def main():
|
||||||
# JP2 metadata can be extensive, so don't print any warnings until we
|
# JP2 metadata can be extensive, so don't print any warnings until we
|
||||||
# are done with the metadata.
|
# are done with the metadata.
|
||||||
jp2 = Jp2k(filename)
|
jp2 = Jp2k(filename)
|
||||||
if (((jp2._codec_format == lib.openjp2.CODEC_J2K) and
|
if jp2._codec_format == lib.openjp2.CODEC_J2K:
|
||||||
(codestream_level == 0))):
|
if codestream_level == 0:
|
||||||
print('File: {0}'.format(os.path.basename(filename)))
|
print('File: {0}'.format(os.path.basename(filename)))
|
||||||
elif print_full_codestream:
|
elif codestream_level == 1:
|
||||||
print(jp2.get_codestream(header_only=False))
|
print(jp2)
|
||||||
|
elif codestream_level == 2:
|
||||||
|
print('File: {0}'.format(os.path.basename(filename)))
|
||||||
|
print(jp2.get_codestream(header_only=False))
|
||||||
else:
|
else:
|
||||||
print(jp2)
|
print(jp2)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1001,18 +1001,19 @@ class ContiguousCodestreamBox(Jp2kBox):
|
||||||
offset of the box from the start of the file.
|
offset of the box from the start of the file.
|
||||||
longname : str
|
longname : str
|
||||||
more verbose description of the box.
|
more verbose description of the box.
|
||||||
main_header : Codestream object
|
codestream : Codestream object
|
||||||
contains list of main header marker/segments
|
Contains list of codestream marker/segments. By default, only the main
|
||||||
|
header is retrieved.
|
||||||
main_header_offset : int
|
main_header_offset : int
|
||||||
offset of main header from start of file
|
offset of main header from start of file
|
||||||
"""
|
"""
|
||||||
box_id = 'jp2c'
|
box_id = 'jp2c'
|
||||||
longname = 'Contiguous Codestream'
|
longname = 'Contiguous Codestream'
|
||||||
|
|
||||||
def __init__(self, main_header=None, main_header_offset=None, length=0,
|
def __init__(self, codestream=None, main_header_offset=None, length=0,
|
||||||
offset=-1):
|
offset=-1):
|
||||||
Jp2kBox.__init__(self)
|
Jp2kBox.__init__(self)
|
||||||
self._main_header = main_header
|
self._codestream = codestream
|
||||||
self.length = length
|
self.length = length
|
||||||
self.offset = offset
|
self.offset = offset
|
||||||
self.main_header_offset = main_header_offset
|
self.main_header_offset = main_header_offset
|
||||||
|
|
@ -1021,20 +1022,23 @@ class ContiguousCodestreamBox(Jp2kBox):
|
||||||
self._filename = None
|
self._filename = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def main_header(self):
|
def codestream(self):
|
||||||
if self._main_header is None:
|
if _parseoptions['full_codestream'] is True:
|
||||||
|
header_only = False
|
||||||
|
else:
|
||||||
|
header_only = True
|
||||||
|
if self._codestream is None:
|
||||||
if self._filename is not None:
|
if self._filename is not None:
|
||||||
with open(self._filename, 'rb') as fptr:
|
with open(self._filename, 'rb') as fptr:
|
||||||
fptr.seek(self.main_header_offset)
|
fptr.seek(self.main_header_offset)
|
||||||
main_header = Codestream(fptr,
|
codestream = Codestream(fptr, self._length,
|
||||||
self._length,
|
header_only=header_only)
|
||||||
header_only=True)
|
self._codestream = codestream
|
||||||
self._main_header = main_header
|
return self._codestream
|
||||||
return self._main_header
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
msg = "glymur.jp2box.ContiguousCodeStreamBox(main_header={0})"
|
msg = "glymur.jp2box.ContiguousCodeStreamBox(codestream={0})"
|
||||||
return msg.format(repr(self.main_header))
|
return msg.format(repr(self.codestream))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = Jp2kBox.__str__(self)
|
msg = Jp2kBox.__str__(self)
|
||||||
|
|
@ -1043,9 +1047,8 @@ class ContiguousCodestreamBox(Jp2kBox):
|
||||||
if _printoptions['codestream'] is False:
|
if _printoptions['codestream'] is False:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg += '\n Main header:'
|
for segment in self.codestream.segment:
|
||||||
for segment in self.main_header.segment:
|
msg += '\n' + self._indent(str(segment), indent_level=4)
|
||||||
msg += '\n' + self._indent(str(segment), indent_level=8)
|
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
@ -1067,11 +1070,11 @@ class ContiguousCodestreamBox(Jp2kBox):
|
||||||
ContiguousCodestreamBox instance
|
ContiguousCodestreamBox instance
|
||||||
"""
|
"""
|
||||||
main_header_offset = fptr.tell()
|
main_header_offset = fptr.tell()
|
||||||
if _parseoptions['codestream'] is True:
|
if _parseoptions['full_codestream'] is True:
|
||||||
main_header = Codestream(fptr, length, header_only=True)
|
codestream = Codestream(fptr, length, header_only=False)
|
||||||
else:
|
else:
|
||||||
main_header = None
|
codestream = None
|
||||||
box = cls(main_header, main_header_offset=main_header_offset,
|
box = cls(codestream, main_header_offset=main_header_offset,
|
||||||
length=length, offset=offset)
|
length=length, offset=offset)
|
||||||
box._filename = fptr.name
|
box._filename = fptr.name
|
||||||
box._length = length
|
box._length = length
|
||||||
|
|
@ -1320,7 +1323,7 @@ class FileTypeBox(Jp2kBox):
|
||||||
if sys.hexversion >= 0x03000000:
|
if sys.hexversion >= 0x03000000:
|
||||||
try:
|
try:
|
||||||
entry = entry.decode('utf-8')
|
entry = entry.decode('utf-8')
|
||||||
except UnicodeDecodeError as err:
|
except UnicodeDecodeError:
|
||||||
# The entry is invalid, but we've got code to catch this
|
# The entry is invalid, but we've got code to catch this
|
||||||
# later on.
|
# later on.
|
||||||
pass
|
pass
|
||||||
|
|
@ -3314,19 +3317,20 @@ _BOX_WITH_ID = {
|
||||||
b'uuid': UUIDBox,
|
b'uuid': UUIDBox,
|
||||||
b'xml ': XMLBox}
|
b'xml ': XMLBox}
|
||||||
|
|
||||||
_parseoptions = {'codestream': True}
|
_parseoptions = {'full_codestream': False}
|
||||||
|
|
||||||
|
|
||||||
def set_parseoptions(codestream=True):
|
def set_parseoptions(full_codestream=True):
|
||||||
"""Set parsing options.
|
"""Set parsing options.
|
||||||
|
|
||||||
These options determine the way JPEG 2000 boxes are parsed.
|
These options determine the way JPEG 2000 boxes are parsed.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
codestream : bool, defaults to True
|
full_codestream : bool, defaults to True
|
||||||
When False, the codestream header is only parsed when accessed. This
|
When False, only the codestream header is parsed for metadata. This
|
||||||
can results in faster JP2/JPX parsing.
|
can results in faster JP2/JPX parsing. When True, the entire
|
||||||
|
codestream is parsed for metadata.
|
||||||
|
|
||||||
See also
|
See also
|
||||||
--------
|
--------
|
||||||
|
|
@ -3337,9 +3341,9 @@ def set_parseoptions(codestream=True):
|
||||||
To put back the default options, you can use:
|
To put back the default options, you can use:
|
||||||
|
|
||||||
>>> import glymur
|
>>> import glymur
|
||||||
>>> glymur.set_parseoptions(codestream=True)
|
>>> glymur.set_parseoptions(full_codestream=True)
|
||||||
"""
|
"""
|
||||||
_parseoptions['codestream'] = codestream
|
_parseoptions['full_codestream'] = full_codestream
|
||||||
|
|
||||||
|
|
||||||
def get_parseoptions():
|
def get_parseoptions():
|
||||||
|
|
@ -3378,7 +3382,9 @@ def set_printoptions(**kwargs):
|
||||||
When False, printing of the XML contents of any XML boxes or UUID XMP
|
When False, printing of the XML contents of any XML boxes or UUID XMP
|
||||||
boxes is suppressed.
|
boxes is suppressed.
|
||||||
codestream : bool, optional
|
codestream : bool, optional
|
||||||
When False, printing of the codestream contents is suppressed.
|
When False, only the codestream header is printed. When True, the
|
||||||
|
entire codestream is printed. This option has no effect when the
|
||||||
|
'short' option is set to True.
|
||||||
|
|
||||||
See also
|
See also
|
||||||
--------
|
--------
|
||||||
|
|
|
||||||
|
|
@ -205,28 +205,30 @@ class Jp2k(Jp2kBox):
|
||||||
if self._shape is not None:
|
if self._shape is not None:
|
||||||
return self._shape
|
return self._shape
|
||||||
|
|
||||||
cstr = self.codestream
|
if self._codec_format == opj2.CODEC_J2K:
|
||||||
height = cstr.segment[1].ysiz
|
# get the image size from the codestream
|
||||||
width = cstr.segment[1].xsiz
|
cstr = self.codestream
|
||||||
num_components = len(cstr.segment[1].xrsiz)
|
height = cstr.segment[1].ysiz
|
||||||
|
width = cstr.segment[1].xsiz
|
||||||
|
num_components = len(cstr.segment[1].xrsiz)
|
||||||
|
else:
|
||||||
|
# try to get the image size from the IHDR box
|
||||||
|
jp2h = [box for box in self.box if box.box_id == 'jp2h'][0]
|
||||||
|
ihdr = [box for box in jp2h.box if box.box_id == 'ihdr'][0]
|
||||||
|
|
||||||
|
height, width = ihdr.height, ihdr.width
|
||||||
|
num_components = ihdr.num_components
|
||||||
|
|
||||||
|
if num_components == 1:
|
||||||
|
# but if there is a PCLR box, then we need to check that as
|
||||||
|
# well, as that turns a single-channel image into a
|
||||||
|
# multi-channel image
|
||||||
|
pclr = [box for box in jp2h.box if box.box_id == 'pclr']
|
||||||
|
if len(pclr) > 0:
|
||||||
|
num_components = len(pclr[0].signed)
|
||||||
|
|
||||||
# If JP2 and a palette box is present, then determine the shape from
|
|
||||||
# that.
|
|
||||||
if num_components == 1:
|
if num_components == 1:
|
||||||
if self._codec_format == opj2.CODEC_J2K:
|
self.shape = (height, width)
|
||||||
# There's no palette box or component mapping in a J2K file.
|
|
||||||
# The 3rd component in the shape would then be 1, but we'll
|
|
||||||
# ignore that.
|
|
||||||
self.shape = (height, width)
|
|
||||||
else:
|
|
||||||
jp2h = [box for box in self.box if box.box_id == 'jp2h'][0]
|
|
||||||
pclr = [box for box in jp2h.box if box.box_id == 'pclr']
|
|
||||||
if len(pclr) == 0:
|
|
||||||
# No palette box, so just one component, which we will
|
|
||||||
# ignore.
|
|
||||||
self.shape = (height, width)
|
|
||||||
else:
|
|
||||||
self.shape = (height, width, len(pclr[0].signed))
|
|
||||||
else:
|
else:
|
||||||
self.shape = (height, width, num_components)
|
self.shape = (height, width, num_components)
|
||||||
|
|
||||||
|
|
@ -918,9 +920,11 @@ class Jp2k(Jp2kBox):
|
||||||
"""
|
"""
|
||||||
Slicing protocol.
|
Slicing protocol.
|
||||||
"""
|
"""
|
||||||
numrows = self.codestream.segment[1].ysiz
|
if len(self.shape) == 2:
|
||||||
numcols = self.codestream.segment[1].xsiz
|
numrows, numcols = self.shape
|
||||||
numbands = self.codestream.segment[1].Csiz
|
numbands = 1
|
||||||
|
else:
|
||||||
|
numrows, numcols, numbands = self.shape
|
||||||
|
|
||||||
if isinstance(pargs, int):
|
if isinstance(pargs, int):
|
||||||
# Not a very good use of this protocol, but technically legal.
|
# Not a very good use of this protocol, but technically legal.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
Test fixtures common to more than one test point.
|
Test fixtures common to more than one test point.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
@ -33,6 +34,14 @@ elif re.match('1.[0-6]', six.__version__) is not None:
|
||||||
WARNING_INFRASTRUCTURE_ISSUE = True
|
WARNING_INFRASTRUCTURE_ISSUE = True
|
||||||
msg = "Cannot run test with version {0} of python-six"
|
msg = "Cannot run test with version {0} of python-six"
|
||||||
WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__)
|
WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__)
|
||||||
|
elif ((re.match('1.8', six.__version__) is not None) and
|
||||||
|
(sys.platform.startswith('linux')) and
|
||||||
|
(platform.linux_distribution() == ('LinuxMint', '17', 'qiana'))):
|
||||||
|
WARNING_INFRASTRUCTURE_ISSUE = True
|
||||||
|
linux_distribution = platform.linux_distribution()
|
||||||
|
msg = "Cannot run test with version {0} of python-six on {1}"
|
||||||
|
WARNING_INFRASTRUCTURE_MSG = msg.format(six.__version__,
|
||||||
|
platform.linux_distribution)
|
||||||
|
|
||||||
# Cannot reopen a named temporary file in windows.
|
# Cannot reopen a named temporary file in windows.
|
||||||
WINDOWS_TMP_FILE_MSG = "cannot use NamedTemporaryFile like this in windows"
|
WINDOWS_TMP_FILE_MSG = "cannot use NamedTemporaryFile like this in windows"
|
||||||
|
|
@ -709,6 +718,190 @@ UUID Box (uuid) @ (77, 3146)
|
||||||
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
||||||
Contiguous Codestream Box (jp2c) @ (3223, 1132296)"""
|
Contiguous Codestream Box (jp2c) @ (3223, 1132296)"""
|
||||||
|
|
||||||
|
nemo = """JPEG 2000 Signature Box (jP ) @ (0, 12)
|
||||||
|
Signature: 0d0a870a
|
||||||
|
File Type Box (ftyp) @ (12, 20)
|
||||||
|
Brand: jp2
|
||||||
|
Compatibility: ['jp2 ']
|
||||||
|
JP2 Header Box (jp2h) @ (32, 45)
|
||||||
|
Image Header Box (ihdr) @ (40, 22)
|
||||||
|
Size: [1456 2592 3]
|
||||||
|
Bitdepth: 8
|
||||||
|
Signed: False
|
||||||
|
Compression: wavelet
|
||||||
|
Colorspace Unknown: False
|
||||||
|
Colour Specification Box (colr) @ (62, 15)
|
||||||
|
Method: enumerated colorspace
|
||||||
|
Precedence: 0
|
||||||
|
Colorspace: sRGB
|
||||||
|
UUID Box (uuid) @ (77, 3146)
|
||||||
|
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
||||||
|
UUID Data:
|
||||||
|
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
|
||||||
|
<ns0:xmpmeta xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ns0="adobe:ns:meta/" xmlns:ns2="http://ns.adobe.com/xap/1.0/" xmlns:ns3="http://ns.adobe.com/tiff/1.0/" xmlns:ns4="http://ns.adobe.com/exif/1.0/" xmlns:ns5="http://ns.adobe.com/photoshop/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ns0:xmptk="Exempi + XMP Core 5.1.2">
|
||||||
|
<rdf:RDF>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<ns2:CreatorTool>Google</ns2:CreatorTool>
|
||||||
|
<ns2:CreateDate>2013-02-09T14:47:53</ns2:CreateDate>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<ns3:YCbCrPositioning>1</ns3:YCbCrPositioning>
|
||||||
|
<ns3:XResolution>72/1</ns3:XResolution>
|
||||||
|
<ns3:YResolution>72/1</ns3:YResolution>
|
||||||
|
<ns3:ResolutionUnit>2</ns3:ResolutionUnit>
|
||||||
|
<ns3:Make>HTC</ns3:Make>
|
||||||
|
<ns3:Model>HTC Glacier</ns3:Model>
|
||||||
|
<ns3:ImageWidth>2592</ns3:ImageWidth>
|
||||||
|
<ns3:ImageLength>1456</ns3:ImageLength>
|
||||||
|
<ns3:BitsPerSample>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>8</rdf:li>
|
||||||
|
<rdf:li>8</rdf:li>
|
||||||
|
<rdf:li>8</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns3:BitsPerSample>
|
||||||
|
<ns3:PhotometricInterpretation>2</ns3:PhotometricInterpretation>
|
||||||
|
<ns3:SamplesPerPixel>3</ns3:SamplesPerPixel>
|
||||||
|
<ns3:WhitePoint>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>1343036288/4294967295</rdf:li>
|
||||||
|
<rdf:li>1413044224/4294967295</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns3:WhitePoint>
|
||||||
|
<ns3:PrimaryChromaticities>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>2748779008/4294967295</rdf:li>
|
||||||
|
<rdf:li>1417339264/4294967295</rdf:li>
|
||||||
|
<rdf:li>1288490240/4294967295</rdf:li>
|
||||||
|
<rdf:li>2576980480/4294967295</rdf:li>
|
||||||
|
<rdf:li>644245120/4294967295</rdf:li>
|
||||||
|
<rdf:li>257698032/4294967295</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns3:PrimaryChromaticities>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<ns4:ColorSpace>1</ns4:ColorSpace>
|
||||||
|
<ns4:PixelXDimension>2528</ns4:PixelXDimension>
|
||||||
|
<ns4:PixelYDimension>1424</ns4:PixelYDimension>
|
||||||
|
<ns4:FocalLength>353/100</ns4:FocalLength>
|
||||||
|
<ns4:GPSAltitudeRef>0</ns4:GPSAltitudeRef>
|
||||||
|
<ns4:GPSAltitude>0/1</ns4:GPSAltitude>
|
||||||
|
<ns4:GPSMapDatum>WGS-84</ns4:GPSMapDatum>
|
||||||
|
<ns4:DateTimeOriginal>2013-02-09T14:47:53</ns4:DateTimeOriginal>
|
||||||
|
<ns4:ISOSpeedRatings>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>76</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns4:ISOSpeedRatings>
|
||||||
|
<ns4:ExifVersion>0220</ns4:ExifVersion>
|
||||||
|
<ns4:FlashpixVersion>0100</ns4:FlashpixVersion>
|
||||||
|
<ns4:ComponentsConfiguration>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>1</rdf:li>
|
||||||
|
<rdf:li>2</rdf:li>
|
||||||
|
<rdf:li>3</rdf:li>
|
||||||
|
<rdf:li>0</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</ns4:ComponentsConfiguration>
|
||||||
|
<ns4:GPSLatitude>42,20.56N</ns4:GPSLatitude>
|
||||||
|
<ns4:GPSLongitude>71,5.29W</ns4:GPSLongitude>
|
||||||
|
<ns4:GPSTimeStamp>2013-02-09T19:47:53Z</ns4:GPSTimeStamp>
|
||||||
|
<ns4:GPSProcessingMethod>NETWORK</ns4:GPSProcessingMethod>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<ns5:DateCreated>2013-02-09T14:47:53</ns5:DateCreated>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about="">
|
||||||
|
<dc:Creator>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>Glymur</rdf:li>
|
||||||
|
<rdf:li>Python XMP Toolkit</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</dc:Creator>
|
||||||
|
</rdf:Description>
|
||||||
|
</rdf:RDF>
|
||||||
|
</ns0:xmpmeta>
|
||||||
|
<?xpacket end="w"?>
|
||||||
|
Contiguous Codestream Box (jp2c) @ (3223, 1132296)
|
||||||
|
SOC marker segment @ (3231, 0)
|
||||||
|
SIZ marker segment @ (3233, 47)
|
||||||
|
Profile: no profile
|
||||||
|
Reference Grid Height, Width: (1456 x 2592)
|
||||||
|
Vertical, Horizontal Reference Grid Offset: (0 x 0)
|
||||||
|
Reference Tile Height, Width: (1456 x 2592)
|
||||||
|
Vertical, Horizontal Reference Tile Offset: (0 x 0)
|
||||||
|
Bitdepth: (8, 8, 8)
|
||||||
|
Signed: (False, False, False)
|
||||||
|
Vertical, Horizontal Subsampling: ((1, 1), (1, 1), (1, 1))
|
||||||
|
COD marker segment @ (3282, 12)
|
||||||
|
Coding style:
|
||||||
|
Entropy coder, without partitions
|
||||||
|
SOP marker segments: False
|
||||||
|
EPH marker segments: False
|
||||||
|
Coding style parameters:
|
||||||
|
Progression order: LRCP
|
||||||
|
Number of layers: 2
|
||||||
|
Multiple component transformation usage: reversible
|
||||||
|
Number of resolutions: 2
|
||||||
|
Code block height, width: (64 x 64)
|
||||||
|
Wavelet transform: 5-3 reversible
|
||||||
|
Precinct size: default, 2^15 x 2^15
|
||||||
|
Code block context:
|
||||||
|
Selective arithmetic coding bypass: False
|
||||||
|
Reset context probabilities on coding pass boundaries: False
|
||||||
|
Termination on each coding pass: False
|
||||||
|
Vertically stripe causal context: False
|
||||||
|
Predictable termination: False
|
||||||
|
Segmentation symbols: False
|
||||||
|
QCD marker segment @ (3296, 7)
|
||||||
|
Quantization style: no quantization, 2 guard bits
|
||||||
|
Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]
|
||||||
|
CME marker segment @ (3305, 37)
|
||||||
|
"Created by OpenJPEG version 2.0.0"
|
||||||
|
SOT marker segment @ (3344, 10)
|
||||||
|
Tile part index: 0
|
||||||
|
Tile part length: 1132173
|
||||||
|
Tile part instance: 0
|
||||||
|
Number of tile parts: 1
|
||||||
|
COC marker segment @ (3356, 9)
|
||||||
|
Associated component: 1
|
||||||
|
Coding style for this component: Entropy coder, PARTITION = 0
|
||||||
|
Coding style parameters:
|
||||||
|
Number of resolutions: 2
|
||||||
|
Code block height, width: (64 x 64)
|
||||||
|
Wavelet transform: 5-3 reversible
|
||||||
|
Code block context:
|
||||||
|
Selective arithmetic coding bypass: False
|
||||||
|
Reset context probabilities on coding pass boundaries: False
|
||||||
|
Termination on each coding pass: False
|
||||||
|
Vertically stripe causal context: False
|
||||||
|
Predictable termination: False
|
||||||
|
Segmentation symbols: False
|
||||||
|
QCC marker segment @ (3367, 8)
|
||||||
|
Associated Component: 1
|
||||||
|
Quantization style: no quantization, 2 guard bits
|
||||||
|
Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]
|
||||||
|
COC marker segment @ (3377, 9)
|
||||||
|
Associated component: 2
|
||||||
|
Coding style for this component: Entropy coder, PARTITION = 0
|
||||||
|
Coding style parameters:
|
||||||
|
Number of resolutions: 2
|
||||||
|
Code block height, width: (64 x 64)
|
||||||
|
Wavelet transform: 5-3 reversible
|
||||||
|
Code block context:
|
||||||
|
Selective arithmetic coding bypass: False
|
||||||
|
Reset context probabilities on coding pass boundaries: False
|
||||||
|
Termination on each coding pass: False
|
||||||
|
Vertically stripe causal context: False
|
||||||
|
Predictable termination: False
|
||||||
|
Segmentation symbols: False
|
||||||
|
QCC marker segment @ (3388, 8)
|
||||||
|
Associated Component: 2
|
||||||
|
Quantization style: no quantization, 2 guard bits
|
||||||
|
Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]
|
||||||
|
SOD marker segment @ (3398, 0)
|
||||||
|
EOC marker segment @ (1135517, 0)"""
|
||||||
|
|
||||||
# Output of reader requirements printing for text_GBR.jp2
|
# Output of reader requirements printing for text_GBR.jp2
|
||||||
text_GBR_rreq = r"""Reader Requirements Box (rreq) @ (40, 109)
|
text_GBR_rreq = r"""Reader Requirements Box (rreq) @ (40, 109)
|
||||||
Fully Understands Aspect Mask: 0xffff
|
Fully Understands Aspect Mask: 0xffff
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,13 @@ from .fixtures import WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG
|
||||||
class TestWarnings(unittest.TestCase):
|
class TestWarnings(unittest.TestCase):
|
||||||
"""Test suite for warnings issued by glymur."""
|
"""Test suite for warnings issued by glymur."""
|
||||||
|
|
||||||
|
def test_invalid_compatibility_list_entry(self):
|
||||||
|
"""should not error out with invalid compatibility list entry"""
|
||||||
|
filename = opj_data_file('input/nonregression/issue397.jp2')
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
Jp2k(filename)
|
||||||
|
self.assertTrue(True)
|
||||||
|
|
||||||
def test_exceeded_box_length(self):
|
def test_exceeded_box_length(self):
|
||||||
"""
|
"""
|
||||||
should warn if reading past end of a box
|
should warn if reading past end of a box
|
||||||
|
|
@ -62,7 +69,7 @@ class TestWarnings(unittest.TestCase):
|
||||||
\(\d+\)\.""",
|
\(\d+\)\.""",
|
||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
@unittest.skipIf(re.match("1.5|2.0.0", glymur.version.openjpeg_version),
|
@unittest.skipIf(re.match("1.5|2.0.0", glymur.version.openjpeg_version),
|
||||||
"Test not passing on 1.5.x, not introduced until 2.x")
|
"Test not passing on 1.5.x, not introduced until 2.x")
|
||||||
|
|
@ -77,7 +84,7 @@ class TestWarnings(unittest.TestCase):
|
||||||
\(\d+\)\.""",
|
\(\d+\)\.""",
|
||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self):
|
def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -90,7 +97,7 @@ class TestWarnings(unittest.TestCase):
|
||||||
dx=\d+,\s*dy=\d+""",
|
dx=\d+,\s*dy=\d+""",
|
||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(self):
|
def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(self):
|
||||||
lst = ['input', 'nonregression',
|
lst = ['input', 'nonregression',
|
||||||
|
|
@ -100,32 +107,32 @@ class TestWarnings(unittest.TestCase):
|
||||||
number\sof\scomponents\sis\sonly\s\d+""",
|
number\sof\scomponents\sis\sonly\s\d+""",
|
||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
with self.assertWarnsRegex(UserWarning, regex):
|
with self.assertWarnsRegex(UserWarning, regex):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
def test_bad_rsiz(self):
|
def test_bad_rsiz(self):
|
||||||
"""Should warn if RSIZ is bad. Issue196"""
|
"""Should warn if RSIZ is bad. Issue196"""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||||
with self.assertWarnsRegex(UserWarning, 'Invalid profile'):
|
with self.assertWarnsRegex(UserWarning, 'Invalid profile'):
|
||||||
Jp2k(filename)
|
Jp2k(filename).get_codestream()
|
||||||
|
|
||||||
def test_bad_wavelet_transform(self):
|
def test_bad_wavelet_transform(self):
|
||||||
"""Should warn if wavelet transform is bad. Issue195"""
|
"""Should warn if wavelet transform is bad. Issue195"""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_10025.jp2')
|
||||||
with self.assertWarnsRegex(UserWarning, 'Invalid wavelet transform'):
|
with self.assertWarnsRegex(UserWarning, 'Invalid wavelet transform'):
|
||||||
Jp2k(filename)
|
Jp2k(filename).get_codestream()
|
||||||
|
|
||||||
def test_invalid_progression_order(self):
|
def test_invalid_progression_order(self):
|
||||||
"""Should still be able to parse even if prog order is invalid."""
|
"""Should still be able to parse even if prog order is invalid."""
|
||||||
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
|
jfile = opj_data_file('input/nonregression/2977.pdf.asan.67.2198.jp2')
|
||||||
with self.assertWarnsRegex(UserWarning, 'Invalid progression order'):
|
with self.assertWarnsRegex(UserWarning, 'Invalid progression order'):
|
||||||
Jp2k(jfile)
|
Jp2k(jfile).get_codestream()
|
||||||
|
|
||||||
def test_tile_height_is_zero(self):
|
def test_tile_height_is_zero(self):
|
||||||
"""Zero tile height should not cause an exception."""
|
"""Zero tile height should not cause an exception."""
|
||||||
filename = 'input/nonregression/2539.pdf.SIGFPE.706.1712.jp2'
|
filename = 'input/nonregression/2539.pdf.SIGFPE.706.1712.jp2'
|
||||||
filename = opj_data_file(filename)
|
filename = opj_data_file(filename)
|
||||||
with self.assertWarnsRegex(UserWarning, 'Invalid tile dimensions'):
|
with self.assertWarnsRegex(UserWarning, 'Invalid tile dimensions'):
|
||||||
Jp2k(filename)
|
Jp2k(filename).get_codestream()
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||||
def test_unknown_marker_segment(self):
|
def test_unknown_marker_segment(self):
|
||||||
|
|
|
||||||
|
|
@ -1016,7 +1016,7 @@ class TestJp2Boxes(unittest.TestCase):
|
||||||
"""Raw instantiation should not produce a main_header."""
|
"""Raw instantiation should not produce a main_header."""
|
||||||
box = ContiguousCodestreamBox()
|
box = ContiguousCodestreamBox()
|
||||||
self.assertEqual(box.box_id, 'jp2c')
|
self.assertEqual(box.box_id, 'jp2c')
|
||||||
self.assertIsNone(box.main_header)
|
self.assertIsNone(box.codestream)
|
||||||
|
|
||||||
def test_codestream_main_header_offset(self):
|
def test_codestream_main_header_offset(self):
|
||||||
"""main_header_offset is an attribute of the CCS box"""
|
"""main_header_offset is an attribute of the CCS box"""
|
||||||
|
|
@ -1318,7 +1318,7 @@ class TestRepr(MetadataBase):
|
||||||
|
|
||||||
# Difficult to eval(repr()) this, so just match the general pattern.
|
# Difficult to eval(repr()) this, so just match the general pattern.
|
||||||
regexp = "glymur.jp2box.ContiguousCodeStreamBox"
|
regexp = "glymur.jp2box.ContiguousCodeStreamBox"
|
||||||
regexp += "[(]main_header=<glymur.codestream.Codestream\sobject\s"
|
regexp += "[(]codestream=<glymur.codestream.Codestream\sobject\s"
|
||||||
regexp += "at\s0x([a-fA-F0-9]*)>[)]"
|
regexp += "at\s0x([a-fA-F0-9]*)>[)]"
|
||||||
|
|
||||||
if sys.hexversion < 0x03000000:
|
if sys.hexversion < 0x03000000:
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,9 @@ from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
||||||
from . import fixtures
|
from . import fixtures
|
||||||
|
|
||||||
|
|
||||||
|
def docTearDown(doctest_obj):
|
||||||
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
# Doc tests should be run as well.
|
# Doc tests should be run as well.
|
||||||
def load_tests(loader, tests, ignore):
|
def load_tests(loader, tests, ignore):
|
||||||
"""Should run doc tests as well"""
|
"""Should run doc tests as well"""
|
||||||
|
|
@ -43,7 +46,8 @@ def load_tests(loader, tests, ignore):
|
||||||
# Can't do it on windows, temporary file issue.
|
# Can't do it on windows, temporary file issue.
|
||||||
return tests
|
return tests
|
||||||
if glymur.lib.openjp2.OPENJP2 is not None:
|
if glymur.lib.openjp2.OPENJP2 is not None:
|
||||||
tests.addTests(doctest.DocTestSuite('glymur.jp2k'))
|
tests.addTests(doctest.DocTestSuite('glymur.jp2k',
|
||||||
|
tearDown=docTearDown))
|
||||||
return tests
|
return tests
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -272,15 +276,6 @@ class TestJp2k(unittest.TestCase):
|
||||||
jp2 = Jp2k(jfile)
|
jp2 = Jp2k(jfile)
|
||||||
self.assertEqual(jp2.shape, (128, 128))
|
self.assertEqual(jp2.shape, (128, 128))
|
||||||
|
|
||||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
|
||||||
"OPJ_DATA_ROOT environment variable not set")
|
|
||||||
def test_invalid_compatibility_list_entry(self):
|
|
||||||
"""should not error out with invalid compatibility list entry"""
|
|
||||||
filename = opj_data_file('input/nonregression/issue397.jp2')
|
|
||||||
with self.assertWarns(UserWarning):
|
|
||||||
Jp2k(filename)
|
|
||||||
self.assertTrue(True)
|
|
||||||
|
|
||||||
def test_shape_j2k(self):
|
def test_shape_j2k(self):
|
||||||
"""verify shape attribute for J2K file
|
"""verify shape attribute for J2K file
|
||||||
"""
|
"""
|
||||||
|
|
@ -1052,31 +1047,30 @@ class TestParsing(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.jp2file = glymur.data.nemo()
|
self.jp2file = glymur.data.nemo()
|
||||||
# Reset parseoptions for every test.
|
# Reset parseoptions for every test.
|
||||||
glymur.set_parseoptions(codestream=True)
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
glymur.set_parseoptions(codestream=True)
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
def test_bad_rsiz(self):
|
def test_bad_rsiz(self):
|
||||||
"""Should not warn if RSIZ when parsing is turned off."""
|
"""Should not warn if RSIZ when parsing is turned off."""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||||
glymur.set_parseoptions(codestream=False)
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
Jp2k(filename)
|
Jp2k(filename)
|
||||||
|
|
||||||
glymur.set_parseoptions(codestream=True)
|
glymur.set_parseoptions(full_codestream=True)
|
||||||
with self.assertWarnsRegex(UserWarning, 'Invalid profile'):
|
with self.assertWarnsRegex(UserWarning, 'Invalid profile'):
|
||||||
Jp2k(filename)
|
Jp2k(filename)
|
||||||
|
|
||||||
def test_main_header(self):
|
def test_main_header(self):
|
||||||
"""Verify that the main header isn't loaded when parsing turned off."""
|
"""verify that the main header isn't loaded during normal parsing"""
|
||||||
# The hidden _main_header attribute should show up after accessing it.
|
# The hidden _main_header attribute should show up after accessing it.
|
||||||
glymur.set_parseoptions(codestream=False)
|
|
||||||
jp2 = Jp2k(self.jp2file)
|
jp2 = Jp2k(self.jp2file)
|
||||||
jp2c = jp2.box[4]
|
jp2c = jp2.box[4]
|
||||||
self.assertIsNone(jp2c._main_header)
|
self.assertIsNone(jp2c._codestream)
|
||||||
jp2c.main_header
|
jp2c.codestream
|
||||||
self.assertIsNotNone(jp2c._main_header)
|
self.assertIsNotNone(jp2c._codestream)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
@unittest.skipIf(WARNING_INFRASTRUCTURE_ISSUE, WARNING_INFRASTRUCTURE_MSG)
|
||||||
|
|
@ -1085,6 +1079,9 @@ class TestParsing(unittest.TestCase):
|
||||||
class TestJp2kOpjDataRootWarnings(unittest.TestCase):
|
class TestJp2kOpjDataRootWarnings(unittest.TestCase):
|
||||||
"""These tests should be run by just about all configuration."""
|
"""These tests should be run by just about all configuration."""
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
def test_undecodeable_box_id(self):
|
def test_undecodeable_box_id(self):
|
||||||
"""Should warn in case of undecodeable box ID but not error out."""
|
"""Should warn in case of undecodeable box ID but not error out."""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1013627.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1013627.jp2')
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,7 @@ class TestSuiteWarns(MetadataBase):
|
||||||
expected = ColourSpecificationBox(colorspace=glymur.core.SRGB)
|
expected = ColourSpecificationBox(colorspace=glymur.core.SRGB)
|
||||||
self.verifyColourSpecificationBox(jp2.box[2].box[1], expected)
|
self.verifyColourSpecificationBox(jp2.box[2].box[1], expected)
|
||||||
|
|
||||||
c = jp2.box[3].main_header
|
c = jp2.box[3].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
|
expected = ['SOC', 'SIZ', 'CME', 'COD', 'QCD', 'QCC', 'QCC']
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ suite.
|
||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
@ -52,7 +53,7 @@ class TestSuite(MetadataBase):
|
||||||
colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.YCC)
|
colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.YCC)
|
||||||
self.verifyColourSpecificationBox(jp2.box[2].box[1], colr)
|
self.verifyColourSpecificationBox(jp2.box[2].box[1], colr)
|
||||||
|
|
||||||
c = jp2.box[3].main_header
|
c = jp2.box[3].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
||||||
|
|
@ -2584,7 +2585,7 @@ class TestSuite(MetadataBase):
|
||||||
self.assertEqual(jp2.box[3].box[3].mapping_type, (1, 1, 1))
|
self.assertEqual(jp2.box[3].box[3].mapping_type, (1, 1, 1))
|
||||||
self.assertEqual(jp2.box[3].box[3].palette_index, (0, 1, 2))
|
self.assertEqual(jp2.box[3].box[3].palette_index, (0, 1, 2))
|
||||||
|
|
||||||
c = jp2.box[4].main_header
|
c = jp2.box[4].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
||||||
|
|
@ -2648,7 +2649,7 @@ class TestSuite(MetadataBase):
|
||||||
precedence=2)
|
precedence=2)
|
||||||
self.verifyColourSpecificationBox(jp2.box[3].box[1], colr)
|
self.verifyColourSpecificationBox(jp2.box[3].box[1], colr)
|
||||||
|
|
||||||
c = jp2.box[4].main_header
|
c = jp2.box[4].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
||||||
|
|
@ -2711,7 +2712,7 @@ class TestSuite(MetadataBase):
|
||||||
self.assertEqual(jp2.box[2].box[2].channel_type, (0, 1)) # opacity
|
self.assertEqual(jp2.box[2].box[2].channel_type, (0, 1)) # opacity
|
||||||
self.assertEqual(jp2.box[2].box[2].association, (0, 0)) # both main
|
self.assertEqual(jp2.box[2].box[2].association, (0, 0)) # both main
|
||||||
|
|
||||||
c = jp2.box[3].main_header
|
c = jp2.box[3].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'COD', 'QCD', 'CME']
|
expected = ['SOC', 'SIZ', 'COD', 'QCD', 'CME']
|
||||||
|
|
@ -2794,7 +2795,7 @@ class TestSuite(MetadataBase):
|
||||||
self.assertEqual(jp2.box[3].box[3].mapping_type, (1, 1, 1))
|
self.assertEqual(jp2.box[3].box[3].mapping_type, (1, 1, 1))
|
||||||
self.assertEqual(jp2.box[3].box[3].palette_index, (0, 1, 2))
|
self.assertEqual(jp2.box[3].box[3].palette_index, (0, 1, 2))
|
||||||
|
|
||||||
c = jp2.box[4].main_header
|
c = jp2.box[4].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
||||||
|
|
@ -2848,7 +2849,7 @@ class TestSuite(MetadataBase):
|
||||||
colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.YCC)
|
colr = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.YCC)
|
||||||
self.verifyColourSpecificationBox(jp2.box[2].box[1], colr)
|
self.verifyColourSpecificationBox(jp2.box[2].box[1], colr)
|
||||||
|
|
||||||
c = jp2.box[3].main_header
|
c = jp2.box[3].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'COD', 'QCD', 'POD']
|
expected = ['SOC', 'SIZ', 'COD', 'QCD', 'POD']
|
||||||
|
|
@ -2913,21 +2914,29 @@ class TestSuiteWarns(MetadataBase):
|
||||||
|
|
||||||
def test_NR_broken4_jp2_dump(self):
|
def test_NR_broken4_jp2_dump(self):
|
||||||
jfile = opj_data_file('input/nonregression/broken4.jp2')
|
jfile = opj_data_file('input/nonregression/broken4.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings():
|
||||||
jp2 = Jp2k(jfile)
|
# Suppress a warning, all we really care is parsing the entire
|
||||||
|
# file.
|
||||||
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
|
warnings.simplefilter("ignore")
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
self.assertEqual(jp2.box[-1].codestream.segment[-1].marker_id,
|
||||||
|
'QCC')
|
||||||
|
|
||||||
def test_NR_broken2_jp2_dump(self):
|
def test_NR_broken2_jp2_dump(self):
|
||||||
"""
|
"""
|
||||||
Invalid marker ID in the codestream.
|
Invalid marker ID in the codestream.
|
||||||
"""
|
"""
|
||||||
jfile = opj_data_file('input/nonregression/broken2.jp2')
|
jfile = opj_data_file('input/nonregression/broken2.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with warnings.catch_warnings():
|
||||||
# Invalid marker ID on codestream.
|
# Suppress a warning, all we really care is parsing the entire
|
||||||
jp2 = Jp2k(jfile)
|
# file.
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
|
with self.assertWarns(UserWarning):
|
||||||
|
# Invalid marker ID on codestream.
|
||||||
|
jp2 = Jp2k(jfile)
|
||||||
|
self.assertEqual(jp2.box[-1].codestream.segment[-1].marker_id,
|
||||||
|
'QCC')
|
||||||
|
|
||||||
def test_NR_file1_dump(self):
|
def test_NR_file1_dump(self):
|
||||||
jfile = opj_data_file('input/conformance/file1.jp2')
|
jfile = opj_data_file('input/conformance/file1.jp2')
|
||||||
|
|
@ -3243,7 +3252,7 @@ class TestSuiteWarns(MetadataBase):
|
||||||
|
|
||||||
# Skip the 4th box, it is uknown.
|
# Skip the 4th box, it is uknown.
|
||||||
|
|
||||||
c = jp2.box[4].main_header
|
c = jp2.box[4].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'COD', 'QCD', 'CME', 'CME']
|
expected = ['SOC', 'SIZ', 'COD', 'QCD', 'CME', 'CME']
|
||||||
|
|
@ -3303,7 +3312,7 @@ class TestSuiteWarns(MetadataBase):
|
||||||
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
||||||
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
||||||
|
|
||||||
c = jp2.box[3].main_header
|
c = jp2.box[3].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
||||||
|
|
@ -3366,7 +3375,7 @@ class TestSuiteWarns(MetadataBase):
|
||||||
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
||||||
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
||||||
|
|
||||||
c = jp2.box[3].main_header
|
c = jp2.box[3].codestream
|
||||||
|
|
||||||
ids = [x.marker_id for x in c.segment]
|
ids = [x.marker_id for x in c.segment]
|
||||||
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
expected = ['SOC', 'SIZ', 'COD', 'QCD']
|
||||||
|
|
|
||||||
|
|
@ -632,7 +632,7 @@ class TestSuiteWrite(fixtures.MetadataBase):
|
||||||
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
||||||
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||||
|
|
||||||
codestream = jp2.box[3].main_header
|
codestream = jp2.box[3].codestream
|
||||||
|
|
||||||
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
kwargs = {'rsiz': 0, 'xysiz': (640, 480), 'xyosiz': (0, 0),
|
||||||
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
'xytsiz': (640, 480), 'xytosiz': (0, 0),
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class TestPrinting(unittest.TestCase):
|
||||||
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
def test_version_info(self):
|
def test_version_info(self):
|
||||||
"""Should be able to print(glymur.version.info)"""
|
"""Should be able to print(glymur.version.info)"""
|
||||||
|
|
@ -854,7 +854,7 @@ class TestPrintingOpjDataRootWarns(unittest.TestCase):
|
||||||
"""Should still be able to print if rsiz is bad, issue196"""
|
"""Should still be able to print if rsiz is bad, issue196"""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||||
with self.assertWarns(UserWarning):
|
with self.assertWarns(UserWarning):
|
||||||
j = Jp2k(filename)
|
j = Jp2k(filename).get_codestream()
|
||||||
with patch('sys.stdout', new=StringIO()):
|
with patch('sys.stdout', new=StringIO()):
|
||||||
print(j)
|
print(j)
|
||||||
|
|
||||||
|
|
@ -1040,9 +1040,10 @@ class TestJp2dump(unittest.TestCase):
|
||||||
|
|
||||||
# Reset printoptions for every test.
|
# Reset printoptions for every test.
|
||||||
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
glymur.set_printoptions(short=False, xml=True, codestream=True)
|
||||||
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
glymur.set_parseoptions(full_codestream=False)
|
||||||
|
|
||||||
def run_jp2dump(self, args):
|
def run_jp2dump(self, args):
|
||||||
sys.argv = args
|
sys.argv = args
|
||||||
|
|
@ -1055,25 +1056,51 @@ class TestJp2dump(unittest.TestCase):
|
||||||
return actual
|
return actual
|
||||||
|
|
||||||
def test_default_nemo(self):
|
def test_default_nemo(self):
|
||||||
"""Should be able to dump a JP2 file's metadata with no codestream."""
|
"""by default one should get the main header"""
|
||||||
actual = self.run_jp2dump(['', self.jp2file])
|
actual = self.run_jp2dump(['', self.jp2file])
|
||||||
|
|
||||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream)
|
# shave off the non-main-header segments
|
||||||
|
lines = fixtures.nemo.split('\n')
|
||||||
|
expected = lines[0:140]
|
||||||
|
expected = '\n'.join(expected)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
def test_codestream_0(self):
|
@unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7")
|
||||||
|
def test_jp2_codestream_0(self):
|
||||||
"""Verify dumping with -c 0, supressing all codestream details."""
|
"""Verify dumping with -c 0, supressing all codestream details."""
|
||||||
actual = self.run_jp2dump(['', '-c', '0', self.jp2file])
|
actual = self.run_jp2dump(['', '-c', '0', self.jp2file])
|
||||||
|
|
||||||
expected = fixtures.nemo_dump_no_codestream
|
expected = fixtures.nemo_dump_no_codestream
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
def test_codestream_1(self):
|
def test_jp2_codestream_1(self):
|
||||||
"""Verify dumping with -c 1, print just the header."""
|
"""Verify dumping with -c 1, print just the header."""
|
||||||
actual = self.run_jp2dump(['', '-c', '1', self.jp2file])
|
actual = self.run_jp2dump(['', '-c', '1', self.jp2file])
|
||||||
|
|
||||||
self.assertEqual(actual, fixtures.nemo_with_codestream_header)
|
# shave off the non-main-header segments
|
||||||
|
lines = fixtures.nemo.split('\n')
|
||||||
|
expected = lines[0:140]
|
||||||
|
expected = '\n'.join(expected)
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
def test_codestream_2(self):
|
def test_jp2_codestream_2(self):
|
||||||
|
"""Verify dumping with -c 2, print entire jp2 jacket, codestream."""
|
||||||
|
actual = self.run_jp2dump(['', '-c', '2', self.jp2file])
|
||||||
|
|
||||||
|
# shave off the non-main-header segments
|
||||||
|
expected = fixtures.nemo
|
||||||
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7")
|
||||||
|
def test_j2k_codestream_0(self):
|
||||||
|
"""-c 0 should print just a single line when used on a codestream."""
|
||||||
|
sys.argv = ['', '-c', '0', self.j2kfile]
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
command_line.main()
|
||||||
|
actual = fake_out.getvalue().strip()
|
||||||
|
self.assertRegex(actual, "File: .*")
|
||||||
|
|
||||||
|
def test_j2k_codestream_2(self):
|
||||||
"""Verify dumping with -c 2, full details."""
|
"""Verify dumping with -c 2, full details."""
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
sys.argv = ['', '-c', '2', self.j2kfile]
|
sys.argv = ['', '-c', '2', self.j2kfile]
|
||||||
|
|
@ -1098,13 +1125,9 @@ class TestJp2dump(unittest.TestCase):
|
||||||
"""Verify dumping with -x, suppress XML."""
|
"""Verify dumping with -x, suppress XML."""
|
||||||
actual = self.run_jp2dump(['', '-x', self.jp2file])
|
actual = self.run_jp2dump(['', '-x', self.jp2file])
|
||||||
|
|
||||||
self.assertEqual(actual, fixtures.nemo_dump_no_codestream_no_xml)
|
# shave off the XML and non-main-header segments
|
||||||
|
lines = fixtures.nemo.split('\n')
|
||||||
@unittest.skipIf(sys.hexversion < 0x03000000, "assertRegex not in 2.7")
|
expected = lines[0:18]
|
||||||
def test_codestream_0_with_j2k_file(self):
|
expected.extend(lines[104:140])
|
||||||
"""-c 0 should print just a single line when used on a codestream."""
|
expected = '\n'.join(expected)
|
||||||
sys.argv = ['', '-c', '0', self.j2kfile]
|
self.assertEqual(actual, expected)
|
||||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
|
||||||
command_line.main()
|
|
||||||
actual = fake_out.getvalue().strip()
|
|
||||||
self.assertRegex(actual, "File: .*")
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue