Merge branch 'devel' into issue179
This commit is contained in:
commit
0ad00be004
16 changed files with 129 additions and 248 deletions
|
|
@ -9,6 +9,7 @@ ChangeLog
|
|||
* Added lxml requirement.
|
||||
* added set_printoptions, get_printoptions function
|
||||
* dropped support for Python 2.6, added support for Python 3.4
|
||||
* dropped support for OpenJPEG versions 1.3 and 1.4
|
||||
* dropped windows support (it might work, it might not, I don't much care)
|
||||
* added write support for JP2 UUID, dataEntryURL, palette, and component mapping boxes
|
||||
* added read/write support for JPX free, number list, and data reference boxes
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ both read and write JPEG 2000 files, but you may wish to install version 2.0
|
|||
or the 2.0+ version from OpenJPEG's development trunk for better performance.
|
||||
If you do that, you should compile it as a shared library (named *openjp2*
|
||||
instead of *openjpeg*) from the developmental source that you can retrieve
|
||||
via subversion. As of this time of writing, svn revision r2651 works.
|
||||
via subversion. As of this time of writing, svn revision r2691 works.
|
||||
You should also download the test data for the purpose of configuring
|
||||
and running OpenJPEG's test suite, check their instructions for all this.
|
||||
You should set the **OPJ_DATA_ROOT** environment variable for the purpose
|
||||
|
|
|
|||
|
|
@ -14,17 +14,7 @@ XMP UUIDs. There is some very limited support for reading JPX metadata.
|
|||
Glymur 0.6 works on Python versions 2.7, 3.3 and 3.4. If you have Python 2.6,
|
||||
you should use the 0.5 series of Glymur.
|
||||
|
||||
OpenJPEG Installation
|
||||
=====================
|
||||
Glymur will read JPEG 2000 images with versions 1.3, 1.4, 1.5, 2.0,
|
||||
and the trunk/development version of OpenJPEG. Writing images is
|
||||
only supported with the 1.5 or better, however, and the trunk/development
|
||||
version of OpenJPEG is strongly recommended. For more information about
|
||||
OpenJPEG, please consult http://www.openjpeg.org.
|
||||
|
||||
If you use MacPorts or if you have a sufficiently recent version of
|
||||
Linux, your package manager should already provide you with a version of
|
||||
OpenJPEG 1.X which glymur can already use.
|
||||
For more information about OpenJPEG, please consult http://www.openjpeg.org.
|
||||
|
||||
Glymur Installation
|
||||
===================
|
||||
|
|
|
|||
|
|
@ -673,6 +673,18 @@ class Codestream(object):
|
|||
msg = msg.format(j, subsampling[0], subsampling[1])
|
||||
warnings.warn(msg)
|
||||
|
||||
try:
|
||||
num_tiles_x = (xysiz[0] - xyosiz[0]) / (xytsiz[0] - xytosiz[0])
|
||||
num_tiles_y = (xysiz[1] - xyosiz[1]) / (xytsiz[1] - xytosiz[1])
|
||||
except ZeroDivisionError as err:
|
||||
warnings.warn("Invalid tile dimensions.")
|
||||
else:
|
||||
numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y)
|
||||
if numtiles > 65535:
|
||||
msg = "Invalid number of tiles ({0}).".format(numtiles)
|
||||
warnings.warn(msg)
|
||||
|
||||
|
||||
kwargs = {'rsiz': rsiz,
|
||||
'xysiz': xysiz,
|
||||
'xyosiz': xyosiz,
|
||||
|
|
@ -1514,14 +1526,6 @@ class SIZsegment(Segment):
|
|||
lst.append(bitdepth - 1)
|
||||
self.ssiz = tuple(lst)
|
||||
|
||||
num_tiles_x = (self.xsiz - self.xosiz) / (self.xtsiz - self.xtosiz)
|
||||
num_tiles_y = (self.ysiz - self.yosiz) / (self.ytsiz - self.ytosiz)
|
||||
numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y)
|
||||
if numtiles > 65535:
|
||||
msg = "Invalid number of tiles ({0}).".format(numtiles)
|
||||
warnings.warn(msg)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
msg = "glymur.codestream.SIZsegment(rsiz={rsiz}, xysiz={xysiz}, "
|
||||
msg += "xyosiz={xyosiz}, xytsiz={xytsiz}, xytosiz={xytosiz}, "
|
||||
|
|
|
|||
|
|
@ -359,13 +359,16 @@ class ColourSpecificationBox(Jp2kBox):
|
|||
else:
|
||||
# 2.7 has trouble pretty-printing ordered dicts so we just have
|
||||
# to print as a regular dict in this case.
|
||||
if sys.hexversion < 0x03000000:
|
||||
icc_profile = dict(self.icc_profile)
|
||||
if self.icc_profile is None:
|
||||
msg += '\n ICC Profile: None'
|
||||
else:
|
||||
icc_profile = self.icc_profile
|
||||
dispvalue = pprint.pformat(icc_profile)
|
||||
lines = [' ' * 8 + y for y in dispvalue.split('\n')]
|
||||
msg += '\n ICC Profile:\n{0}'.format('\n'.join(lines))
|
||||
if sys.hexversion < 0x03000000:
|
||||
icc_profile = dict(self.icc_profile)
|
||||
else:
|
||||
icc_profile = self.icc_profile
|
||||
dispvalue = pprint.pformat(icc_profile)
|
||||
lines = [' ' * 8 + y for y in dispvalue.split('\n')]
|
||||
msg += '\n ICC Profile:\n{0}'.format('\n'.join(lines))
|
||||
|
||||
return msg
|
||||
|
||||
|
|
@ -829,7 +832,7 @@ class ComponentMappingBox(Jp2kBox):
|
|||
msg = msg.format(self.component_index[k],
|
||||
self.palette_index[k])
|
||||
else:
|
||||
msg += '\n Component %d ==> %d'
|
||||
msg += '\n Component {0} ==> {1}'
|
||||
msg = msg.format(self.component_index[k], k)
|
||||
return msg
|
||||
|
||||
|
|
@ -2628,19 +2631,22 @@ class XMLBox(Jp2kBox):
|
|||
read_buffer = fptr.read(num_bytes)
|
||||
try:
|
||||
text = read_buffer.decode('utf-8')
|
||||
except UnicodeDecodeError as ude:
|
||||
except UnicodeDecodeError as err:
|
||||
# Possibly bad string of bytes to begin with.
|
||||
# Try to search for <?xml and go from there.
|
||||
decl_start = read_buffer.find(b'<?xml')
|
||||
if decl_start > -1:
|
||||
text = read_buffer[decl_start:].decode('utf-8')
|
||||
else:
|
||||
raise
|
||||
if decl_start <= -1:
|
||||
msg = 'A problem was encountered while parsing an XML box:'
|
||||
msg += '\n\n\t"{0}"\n\nNo XML was retrieved.'
|
||||
warnings.warn(msg.format(str(err)))
|
||||
return XMLBox(xml=None, length=length, offset=offset)
|
||||
|
||||
text = read_buffer[decl_start:].decode('utf-8')
|
||||
|
||||
# Let the user know that the XML box was problematic.
|
||||
msg = 'A UnicodeDecodeError was encountered parsing an XML box at '
|
||||
msg += 'byte position {0} ({1}), but the XML was still recovered.'
|
||||
msg = msg.format(offset, ude.reason)
|
||||
msg = msg.format(offset, err.reason)
|
||||
warnings.warn(msg, UserWarning)
|
||||
|
||||
# Strip out any trailing nulls, as they can foul up XML parsing.
|
||||
|
|
|
|||
|
|
@ -774,18 +774,18 @@ class Jp2k(Jp2kBox):
|
|||
"""
|
||||
self._subsampling_sanity_check()
|
||||
|
||||
# Must check the specified rlevel against the maximum.
|
||||
if rlevel != 0:
|
||||
# Must check the specified rlevel against the maximum.
|
||||
# OpenJPEG 1.3 will segfault if rlevel is too high.
|
||||
codestream = self.get_codestream()
|
||||
max_rlevel = codestream.segment[2].spcod[4]
|
||||
if rlevel == -1:
|
||||
# -1 is shorthand for the largest rlevel
|
||||
rlevel = max_rlevel
|
||||
if rlevel < -1 or rlevel > max_rlevel:
|
||||
msg = "rlevel must be in the range [-1, {0}] for this image."
|
||||
msg = msg.format(max_rlevel)
|
||||
raise IOError(msg)
|
||||
elif rlevel < -1 or rlevel > max_rlevel:
|
||||
msg = "rlevel must be in the range [-1, {0}] for this image."
|
||||
msg = msg.format(max_rlevel)
|
||||
raise IOError(msg)
|
||||
|
||||
with ExitStack() as stack:
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ class ImageCompType(ctypes.Structure):
|
|||
|
||||
# alpha channel
|
||||
# TODO: exclude for 2.0, 1.5
|
||||
("alpha", ctypes.POINTER(ctypes.c_uint16))]
|
||||
("alpha", ctypes.c_uint16)]
|
||||
|
||||
|
||||
class ImageType(ctypes.Structure):
|
||||
|
|
|
|||
|
|
@ -577,3 +577,13 @@ file1_xml = """XML Box (xml ) @ (36, 439)
|
|||
\t\t<IMAGE_SOURCE>Professional 120 Image</IMAGE_SOURCE>
|
||||
\t</GENERAL_CREATION_INFO>
|
||||
</IMAGE_CREATION>"""
|
||||
|
||||
issue_182_cmap = """Component Mapping Box (cmap) @ (130, 24)
|
||||
Component 0 ==> palette column 0
|
||||
Component 1 ==> palette column 0
|
||||
Component 2 ==> 2"""
|
||||
|
||||
issue_183_colr = """Colour Specification Box (colr) @ (62, 12)
|
||||
Method: restricted ICC profile
|
||||
Precedence: 0
|
||||
ICC Profile: None"""
|
||||
|
|
|
|||
|
|
@ -13,17 +13,12 @@ import struct
|
|||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from glymur import Jp2k
|
||||
import glymur
|
||||
|
||||
try:
|
||||
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
|
||||
except KeyError:
|
||||
DATA_ROOT = None
|
||||
except:
|
||||
raise
|
||||
|
||||
from .fixtures import opj_data_file, OPJ_DATA_ROOT
|
||||
|
||||
class TestCodestream(unittest.TestCase):
|
||||
"""Test suite for unusual codestream cases."""
|
||||
|
|
@ -34,7 +29,21 @@ class TestCodestream(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(DATA_ROOT is None,
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
def test_tile_height_is_zero(self):
|
||||
"""Zero tile height should not cause an exception."""
|
||||
filename = opj_data_file('input/nonregression/2539.pdf.SIGFPE.706.1712.jp2')
|
||||
if sys.hexversion < 0x03000000:
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
Jp2k(filename)
|
||||
else:
|
||||
with self.assertWarns(UserWarning):
|
||||
Jp2k(filename)
|
||||
|
||||
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
def test_reserved_marker_segment(self):
|
||||
|
|
@ -45,7 +54,7 @@ class TestCodestream(unittest.TestCase):
|
|||
#
|
||||
# Let's inject a reserved marker segment into a file that
|
||||
# we know something about to make sure we can still parse it.
|
||||
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_01.j2k')
|
||||
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k')
|
||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||
with open(filename, 'rb') as ifile:
|
||||
# Everything up until the first QCD marker.
|
||||
|
|
@ -67,7 +76,7 @@ class TestCodestream(unittest.TestCase):
|
|||
self.assertEqual(codestream.segment[2].length, 3)
|
||||
self.assertEqual(codestream.segment[2].data, b'\x00')
|
||||
|
||||
@unittest.skipIf(DATA_ROOT is None,
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
|
|
@ -77,7 +86,7 @@ class TestCodestream(unittest.TestCase):
|
|||
# Let's inject a marker segment whose marker does not appear to
|
||||
# be valid. We still parse the file, but warn about the offending
|
||||
# marker.
|
||||
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_01.j2k')
|
||||
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_01.j2k')
|
||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||
with open(filename, 'rb') as ifile:
|
||||
# Everything up until the first QCD marker.
|
||||
|
|
@ -100,11 +109,11 @@ class TestCodestream(unittest.TestCase):
|
|||
self.assertEqual(codestream.segment[2].length, 3)
|
||||
self.assertEqual(codestream.segment[2].data, b'\x00')
|
||||
|
||||
@unittest.skipIf(DATA_ROOT is None,
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
def test_psot_is_zero(self):
|
||||
"""Psot=0 in SOT is perfectly legal. Issue #78."""
|
||||
filename = os.path.join(DATA_ROOT,
|
||||
filename = os.path.join(OPJ_DATA_ROOT,
|
||||
'input/nonregression/123.j2c')
|
||||
j = Jp2k(filename)
|
||||
codestream = j.get_codestream(header_only=False)
|
||||
|
|
@ -125,11 +134,11 @@ class TestCodestream(unittest.TestCase):
|
|||
self.assertEqual(codestream.segment[1].ssiz, (7, 7, 7))
|
||||
|
||||
|
||||
@unittest.skipIf(DATA_ROOT is None,
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
def test_siz_segment_ssiz_signed(self):
|
||||
"""ssiz attribute to be removed in future release"""
|
||||
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k')
|
||||
filename = os.path.join(OPJ_DATA_ROOT, 'input/conformance/p0_03.j2k')
|
||||
j = Jp2k(filename)
|
||||
codestream = j.get_codestream()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,148 +0,0 @@
|
|||
"""
|
||||
These tests deal with JPX/JP2/J2K images in the format-corpus repository.
|
||||
"""
|
||||
# R0904: Not too many methods in unittest.
|
||||
# pylint: disable=R0904
|
||||
|
||||
# E1101: assertWarns introduced in python 3.2
|
||||
# pylint: disable=E1101
|
||||
|
||||
import os
|
||||
from os.path import join
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import glymur
|
||||
from glymur import Jp2k
|
||||
|
||||
try:
|
||||
FORMAT_CORPUS_DATA_ROOT = os.environ['FORMAT_CORPUS_DATA_ROOT']
|
||||
except KeyError:
|
||||
FORMAT_CORPUS_DATA_ROOT = None
|
||||
|
||||
try:
|
||||
OPJ_DATA_ROOT = os.environ['OPJ_DATA_ROOT']
|
||||
except KeyError:
|
||||
OPJ_DATA_ROOT = None
|
||||
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Requires features introduced in 3.2 (assertWarns)")
|
||||
class TestSuiteConformance(unittest.TestCase):
|
||||
"""Test suite for conformance."""
|
||||
|
||||
def setUp(self):
|
||||
self.j2kfile = glymur.data.goodstuff()
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(re.match(r"""1\.[0123]""",
|
||||
glymur.version.openjpeg_version) is not None,
|
||||
"Needs 1.3+ to catch this.")
|
||||
def test_truncated_eoc(self):
|
||||
"""Has one byte shaved off of EOC marker."""
|
||||
with open(self.j2kfile, 'rb') as ifile:
|
||||
data = ifile.read()
|
||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as ofile:
|
||||
ofile.write(data[:-1])
|
||||
ofile.flush()
|
||||
|
||||
j2k = Jp2k(ofile.name)
|
||||
with self.assertWarns(UserWarning):
|
||||
codestream = j2k.get_codestream(header_only=False)
|
||||
|
||||
# The last segment is truncated, so there should not be an EOC
|
||||
# marker.
|
||||
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
|
||||
|
||||
# The codestream is not as long as claimed.
|
||||
with self.assertRaises(OSError):
|
||||
j2k.read(rlevel=-1)
|
||||
|
||||
|
||||
@unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None,
|
||||
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Requires features introduced in 3.2 (assertWarns)")
|
||||
class TestSuiteFormatCorpus(unittest.TestCase):
|
||||
"""Test suite for files in format corpus repository."""
|
||||
|
||||
@unittest.skipIf(re.match(r"""1\.[01234]""",
|
||||
glymur.version.openjpeg_version) is not None,
|
||||
"Needs 1.4+ to catch this.")
|
||||
def test_balloon_trunc2(self):
|
||||
"""Shortened by 5000 bytes."""
|
||||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
||||
'jp2k-test/byteCorruption/balloon_trunc2.jp2')
|
||||
j2k = Jp2k(jfile)
|
||||
with self.assertWarns(UserWarning):
|
||||
codestream = j2k.get_codestream(header_only=False)
|
||||
|
||||
# The last segment is truncated, so there should not be an EOC marker.
|
||||
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
|
||||
|
||||
# The codestream is not as long as claimed.
|
||||
with self.assertRaises(OSError):
|
||||
j2k.read(rlevel=-1)
|
||||
|
||||
def test_balloon_trunc3(self):
|
||||
"""Most of last tile is missing."""
|
||||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
||||
'jp2k-test/byteCorruption/balloon_trunc3.jp2')
|
||||
j2k = Jp2k(jfile)
|
||||
with self.assertWarns(UserWarning):
|
||||
codestream = j2k.get_codestream(header_only=False)
|
||||
|
||||
# The last segment is truncated, so there should not be an EOC marker.
|
||||
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
|
||||
|
||||
# Should error out, it does not.
|
||||
#with self.assertRaises(OSError):
|
||||
# j2k.read(rlevel=-1)
|
||||
|
||||
def test_jp2_brand_any_icc_profile(self):
|
||||
"""If 'jp2 ', then the method cannot be any icc profile."""
|
||||
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
|
||||
'jp2k-test', 'icc',
|
||||
'balloon_eciRGBv2_ps_adobeplugin.jpf')
|
||||
with self.assertWarns(UserWarning):
|
||||
Jp2k(jfile)
|
||||
|
||||
def test_jp2_brand_iccpr_mult_colr(self):
|
||||
"""Has colr box, one that conforms, one that does not."""
|
||||
|
||||
# Wrong 'brand' field; contains two versions of ICC profile: one
|
||||
# embedded using "Any ICC" method; other embedded using "Restricted
|
||||
# ICC" method, with description ("Modified eciRGB v2") and profileClass
|
||||
# ("Input Device") changed relative to original profile.
|
||||
jfile = join(FORMAT_CORPUS_DATA_ROOT, 'jp2k-test', 'icc',
|
||||
'balloon_eciRGBv2_ps_adobeplugin_jp2compatible.jpf')
|
||||
with self.assertWarns(UserWarning):
|
||||
Jp2k(jfile)
|
||||
|
||||
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Requires features introduced in 3.2 (assertWarns)")
|
||||
class TestSuiteOpj(unittest.TestCase):
|
||||
"""Test suite for files in openjpeg repository."""
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_jp2_brand_any_icc_profile(self):
|
||||
"""If 'jp2 ', then the method cannot be any icc profile."""
|
||||
filename = os.path.join(OPJ_DATA_ROOT,
|
||||
'input/nonregression/text_GBR.jp2')
|
||||
with self.assertWarns(UserWarning):
|
||||
Jp2k(filename)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -39,6 +39,7 @@ from glymur.jp2box import ColourSpecificationBox, ContiguousCodestreamBox
|
|||
from glymur.jp2box import FileTypeBox, ImageHeaderBox, JP2HeaderBox
|
||||
from glymur.jp2box import JPEG2000SignatureBox
|
||||
|
||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
class TestXML(unittest.TestCase):
|
||||
|
|
@ -93,6 +94,22 @@ class TestXML(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
os.unlink(self.xmlfile)
|
||||
|
||||
def test_invalid_utf8(self):
|
||||
"""Bad byte sequence that cannot be parsed."""
|
||||
filename = opj_data_file(os.path.join('input',
|
||||
'nonregression',
|
||||
'26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2'))
|
||||
if sys.hexversion < 0x03000000:
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
else:
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(filename)
|
||||
|
||||
self.assertIsNone(jp2.box[3].box[1].box[1].xml)
|
||||
|
||||
|
||||
def test_negative_file_and_xml(self):
|
||||
"""The XML should come from only one source."""
|
||||
xml_object = ET.parse(self.xmlfile)
|
||||
|
|
|
|||
|
|
@ -403,15 +403,9 @@ class TestJp2k(unittest.TestCase):
|
|||
# The file in question has multiple codestreams.
|
||||
jpx = Jp2k(self.jpxfile)
|
||||
data = jpx.read()
|
||||
if re.match(r"""1\.[0123]""", glymur.version.openjpeg_version):
|
||||
# openjpeg 1.3 doesn't apply the palette, so it's a 2D image here
|
||||
self.assertEqual(data.shape, (1024, 1024))
|
||||
else:
|
||||
self.assertEqual(data.shape, (1024, 1024, 3))
|
||||
self.assertEqual(data.shape, (1024, 1024, 3))
|
||||
|
||||
|
||||
@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version),
|
||||
"Requires at least version 1.5")
|
||||
class TestJp2k_write(unittest.TestCase):
|
||||
"""Write tests, can be run by versions 1.5+"""
|
||||
|
||||
|
|
|
|||
|
|
@ -381,11 +381,7 @@ class TestSuite(unittest.TestCase):
|
|||
jfile = opj_data_file('input/conformance/file9.jp2')
|
||||
jp2k = Jp2k(jfile)
|
||||
jpdata = jp2k.read()
|
||||
if re.match(r"""1\.3""", glymur.version.openjpeg_version):
|
||||
# Version 1.3 reads the indexed image as indices, not as RGB.
|
||||
self.assertEqual(jpdata.shape, (512, 768))
|
||||
else:
|
||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||
self.assertEqual(jpdata.shape, (512, 768, 3))
|
||||
|
||||
def test_NR_DEC_Bretagne2_j2k_1_decode(self):
|
||||
jfile = opj_data_file('input/nonregression/Bretagne2.j2k')
|
||||
|
|
@ -6307,11 +6303,16 @@ class TestSuiteDump(unittest.TestCase):
|
|||
[8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10])
|
||||
|
||||
def test_NR_text_GBR_dump(self):
|
||||
# brand is 'jp2 ', but has any icc profile.
|
||||
# Verify the warning on python3, but ignore it otherwise.
|
||||
jfile = opj_data_file('input/nonregression/text_GBR.jp2')
|
||||
with warnings.catch_warnings():
|
||||
# brand is 'jp2 ', but has any icc profile.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(jfile)
|
||||
if sys.hexversion > 0x03030000:
|
||||
with self.assertWarns(UserWarning):
|
||||
jp2 = Jp2k(jfile)
|
||||
else:
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(jfile)
|
||||
|
||||
ids = [box.box_id for box in jp2.box]
|
||||
lst = ['jP ', 'ftyp', 'rreq', 'jp2h',
|
||||
|
|
|
|||
|
|
@ -23,33 +23,6 @@ from glymur import Jp2k
|
|||
import glymur
|
||||
|
||||
|
||||
@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version),
|
||||
"Functionality not implemented for 1.3, 1.4")
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
||||
class TestSuiteNegative2pointzero(unittest.TestCase):
|
||||
"""Feature set not supported for versions less than 2.0"""
|
||||
|
||||
def setUp(self):
|
||||
self.jp2file = glymur.data.nemo()
|
||||
self.j2kfile = glymur.data.goodstuff()
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
def test_cinema_mode(self):
|
||||
"""Cinema mode not supported for less than 2.0.1."""
|
||||
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
|
||||
data = read_image(infile)
|
||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||
j = Jp2k(tfile.name, 'wb')
|
||||
with self.assertRaises(IOError):
|
||||
j.write(data, psnr=[30, 35, 40], cratios=[2, 3, 4])
|
||||
|
||||
|
||||
@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version),
|
||||
"Functionality not implemented for 1.3, 1.4")
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_OPJ_DATA_ROOT environment variable not set")
|
||||
class TestSuiteNegative(unittest.TestCase):
|
||||
|
|
|
|||
|
|
@ -249,9 +249,6 @@ class TestSuiteNegative2pointzero(unittest.TestCase):
|
|||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "no write support on windows, period")
|
||||
@unittest.skipIf(re.match(r"""1\.[01234]\.\d""",
|
||||
glymur.version.openjpeg_version) is not None,
|
||||
"Writing only supported with openjpeg version 1.5+.")
|
||||
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
|
||||
@unittest.skipIf(OPJ_DATA_ROOT is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
|
|
|
|||
|
|
@ -905,6 +905,33 @@ class TestPrinting(unittest.TestCase):
|
|||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_issue182(self):
|
||||
"""Should not show the format string in output."""
|
||||
# The cmap box is wildly broken, but printing was still wrong.
|
||||
# Format strings like %d were showing up in the output.
|
||||
filename = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2')
|
||||
|
||||
with warnings.catch_warnings():
|
||||
# Ignore warning about bad pclr box.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2.box[3].box[3])
|
||||
actual = fake_out.getvalue().strip()
|
||||
self.assertEqual(actual, fixtures.issue_182_cmap)
|
||||
|
||||
def test_issue183(self):
|
||||
filename = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||
|
||||
with warnings.catch_warnings():
|
||||
# Ignore warning about bad pclr box.
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(filename)
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(jp2.box[2].box[1])
|
||||
actual = fake_out.getvalue().strip()
|
||||
self.assertEqual(actual, fixtures.issue_183_colr)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03000000,
|
||||
"Ordered dicts not printing well in 2.7")
|
||||
def test_exif_uuid(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue