Merge branch 'release-0.2.4'

This commit is contained in:
jevans 2013-07-21 12:32:05 -04:00
commit 8c3e6b69ae
13 changed files with 115 additions and 68 deletions

View file

@ -1,3 +1,7 @@
Jul 21, 2013 - v0.2.4 Fixed markdown bug for Fedora 17 information, fixed
out-of-date windows information (issue79). Fixed incorrect
interpretation of Psot parameter (issue78).
Jul 18, 2013 - v0.2.3 Support for Python 2.6, OpenJPEG 1.4. Incompatible
change to ChannelDefinitionBox constructor. Added RGBA example.

View file

@ -1,9 +1,9 @@
glymur: a Python interface for JPEG 2000
=========================================
**glymur** contains a Python interface to the OpenJPEG library
which allows linux and mac users to read and write JPEG 2000 files.
**glymur** works on Python 2.6, 2.7 and 3.3. Python 3.3 is strongly
**glymur** contains a Python interface to the OpenJPEG library which
allows one to read and write JPEG 2000 files. **glymur** works on
Python 2.6, 2.7 and 3.3. Python 3.3 is strongly
recommended.
Please read the docs, https://glymur.readthedocs.org/en/latest/

View file

@ -78,7 +78,7 @@ copyright = u'2013, John Evans'
# The short X.Y version.
version = '0.1'
# The full version, including alpha/beta/rc tags.
release = '0.2.3'
release = '0.2.4'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View file

@ -115,7 +115,7 @@ following RPMs installed.
* numpy
* matplotlib (optional)
In addition, you must install contextlib2 and Pillow via pip.
In addition, you must install contextlib2 and Pillow via pip. ::
$ yum install python-devel # pip needs this in order to compile Pillow
$ pip-python install Pillow --user
@ -126,8 +126,11 @@ Windows
-------
The only configuration I've tested is Python(xy), which uses Python 2.7.
Python(xy) already comes with numpy, but you will have to install pip and then
contextlib2 and mock as well. Both 1.5.1 and the svn development versions of
openjpeg work.
contextlib2 and mock as well. Glymur seems to work with both 1.5.1 and the
svn development versions of openjpeg.
Glymur has been tested **far less** extensively on Windows than on the other
platforms.
'''''''

View file

@ -6,7 +6,7 @@ from .jp2k import Jp2k
from .jp2dump import jp2dump
from . import data
#from . import test
from . import test
def runtests():

View file

@ -57,7 +57,12 @@ class Codestream(object):
Attributes
----------
segment : list of marker segments
segment : iterable
list of marker segments
offset : int
Offset of the codestream from start of the file in bytes.
length : int
Length of the codestream in bytes.
Raises
------
@ -70,17 +75,22 @@ class Codestream(object):
15444-1:2004 - Information technology -- JPEG 2000 image coding system:
Core coding system
"""
def __init__(self, fptr, header_only=True):
def __init__(self, fptr, length, header_only=True):
"""
Parameters
----------
fptr : file
Open file object.
length : int
Length of the codestream in bytes.
header_only : bool, optional
If True, only marker segments in the main header are parsed.
Supplying False may impose a large performance penalty.
"""
self.offset = fptr.tell()
self.length = length
# Number of components. Must be kept track of for the processing of
# many segments.
self._csiz = -1
@ -111,9 +121,9 @@ class Codestream(object):
try:
segment = self._process_marker_segment(fptr, marker_id)
except InconsistentStartOfTileError as isote:
except Exception as error:
# Treat this as a warning.
msg = str(isote)
msg = str(error)
warnings.warn(msg)
break
@ -199,7 +209,11 @@ class Codestream(object):
segment = _parse_sot_segment(fptr)
if segment.offset not in self._tile_offset:
self._tile_offset.append(segment.offset)
self._tile_length.append(segment.psot)
if segment.psot == 0:
tile_part_length = self.offset + self.length - segment.offset - 2
else:
tile_part_length = segment.psot
self._tile_length.append(tile_part_length)
else:
msg = "Inconsistent start-of-tile (SOT) marker segment "
msg += "encountered in tile with index {0}. "

View file

@ -644,7 +644,7 @@ class ContiguousCodestreamBox(Jp2kBox):
-------
ContiguousCodestreamBox instance
"""
main_header = Codestream(fptr, header_only=True)
main_header = Codestream(fptr, length, header_only=True)
box = ContiguousCodestreamBox(main_header, length=length,
offset=offset)
return box

View file

@ -1033,7 +1033,8 @@ class Jp2k(Jp2kBox):
"""
with open(self.filename, 'rb') as fptr:
if self._codec_format == _opj2.CODEC_J2K:
codestream = Codestream(fptr, header_only=header_only)
codestream = Codestream(fptr, self.length,
header_only=header_only)
else:
box = [x for x in self.box if x.box_id == 'jp2c']
if len(box) != 1:
@ -1042,9 +1043,15 @@ class Jp2k(Jp2kBox):
fptr.seek(box[0].offset)
read_buffer = fptr.read(8)
(box_length, _) = struct.unpack('>I4s', read_buffer)
if box_length == 1:
if box_length == 0:
# The length of the box is presumed to last until the end
# of the file. Compute the effective length of the box.
box_length = os.path.getsize(fptr.name) - fptr.tell() + 8
elif box_length == 1:
# Seek past the XL field.
read_buffer = fptr.read(8)
codestream = Codestream(fptr, header_only=header_only)
box_length, = struct.unpack('>Q', read_buffer)
codestream = Codestream(fptr, box_length - 8,
header_only=header_only)
return codestream

View file

@ -28,8 +28,7 @@ except:
class TestCodestream(unittest.TestCase):
def setUp(self):
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
"data/nemo.jp2")
self.jp2file = glymur.data.nemo()
def tearDown(self):
pass
@ -95,5 +94,16 @@ class TestCodestream(unittest.TestCase):
self.assertEqual(c.segment[2].length, 3)
self.assertEqual(c.segment[2]._data, b'\x00')
def test_psot_is_zero(self):
# Psot=0 in SOT is perfectly legal. Issue #78.
filename = os.path.join(data_root,
'input/nonregression/123.j2c')
j = Jp2k(filename)
c = j.get_codestream(header_only=False)
# The codestream is valid, so we should be able to get the entire
# codestream, so the last one is EOC.
self.assertEqual(c.segment[-1].marker_id, 'EOC')
if __name__ == "__main__":
unittest.main()

View file

@ -823,12 +823,16 @@ class TestSuite(unittest.TestCase):
self.assertTrue(True)
def test_NR_DEC_broken2_jp2_5_decode(self):
jfile = os.path.join(data_root,
'input/nonregression/broken2.jp2')
# Null pointer access
jfile = os.path.join(data_root, 'input/nonregression/broken2.jp2')
with self.assertRaises(IOError):
data = Jp2k(jfile).read()
with warnings.catch_warnings():
# Library warning, invalid number of subbands.
warnings.simplefilter("ignore")
data = Jp2k(jfile).read()
self.assertTrue(True)
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_NR_DEC_broken3_jp2_6_decode(self):
@ -845,7 +849,10 @@ class TestSuite(unittest.TestCase):
jfile = os.path.join(data_root,
'input/nonregression/broken4.jp2')
with self.assertRaises(IOError):
data = Jp2k(jfile).read()
with warnings.catch_warnings():
# Library warning, invalid number of subbands.
warnings.simplefilter("ignore")
data = Jp2k(jfile).read()
self.assertTrue(True)
@unittest.skip("fprintf stderr output in r2343.")
@ -6003,13 +6010,16 @@ class TestSuiteDump(unittest.TestCase):
self.assertEqual(c.segment[6]._exponent,
[8] + [9, 9, 10] * 5)
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2, 'assertWarns'.")
def test_NR_broken2_jp2_dump(self):
# Invalid marker ID on codestream.
jfile = os.path.join(data_root,
'input/nonregression/broken2.jp2')
with self.assertRaises(IOError):
jfile = os.path.join(data_root, 'input/nonregression/broken2.jp2')
with self.assertWarns(UserWarning):
jp2 = Jp2k(jfile)
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_NR_broken3_jp2_dump(self):
@ -6137,12 +6147,16 @@ class TestSuiteDump(unittest.TestCase):
self.assertEqual(c.segment[6]._exponent,
[8] + [9, 9, 10] * 5)
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2, 'assertWarns'")
def test_NR_broken4_jp2_dump(self):
jfile = os.path.join(data_root,
'input/nonregression/broken4.jp2')
with self.assertRaises(IOError):
# Has an invalid marker in the main header
jfile = os.path.join(data_root, 'input/nonregression/broken4.jp2')
with self.assertWarns(UserWarning):
jp2 = Jp2k(jfile)
self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC')
def test_NR_file409752(self):
jfile = os.path.join(data_root,
'input/nonregression/file409752.jp2')
@ -7799,18 +7813,22 @@ class TestSuite15(unittest.TestCase):
data = jp2.read()
self.assertTrue(True)
@unittest.skipIf(int(glymur.lib.openjpeg.version().split('.')[1]) < 5,
"Segfaults openjpeg 1.4 and earlier.")
def test_NR_DEC_broken2_jp2_5_decode(self):
jfile = os.path.join(data_root,
'input/nonregression/broken2.jp2')
with self.assertRaises(IOError):
data = Jp2k(jfile).read()
# Null pointer access
jfile = os.path.join(data_root, 'input/nonregression/broken2.jp2')
with self.assertRaises(ValueError):
with warnings.catch_warnings():
# Library warning, invalid number of subbands.
warnings.simplefilter("ignore")
data = Jp2k(jfile).read()
self.assertTrue(True)
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_NR_DEC_broken3_jp2_6_decode(self):
jfile = os.path.join(data_root,
'input/nonregression/broken3.jp2')
jfile = os.path.join(data_root, 'input/nonregression/broken3.jp2')
with self.assertWarns(UserWarning) as cw:
# colr box has bad length.
j = Jp2k(jfile)
@ -7818,11 +7836,16 @@ class TestSuite15(unittest.TestCase):
with self.assertRaises(ValueError) as ce:
d = j.read()
@unittest.skipIf(int(glymur.lib.openjpeg.version().split('.')[1]) < 5,
"Segfaults openjpeg 1.4 and earlier.")
def test_NR_DEC_broken4_jp2_7_decode(self):
jfile = os.path.join(data_root,
'input/nonregression/broken4.jp2')
with self.assertRaises(IOError):
data = Jp2k(jfile).read()
# Null pointer access
jfile = os.path.join(data_root, 'input/nonregression/broken4.jp2')
with self.assertRaises(ValueError):
with warnings.catch_warnings():
# Library warning, invalid number of subbands.
warnings.simplefilter("ignore")
data = Jp2k(jfile).read()
self.assertTrue(True)
@unittest.skip("fprintf stderr output in r2343.")

View file

@ -73,25 +73,16 @@ class TestSuiteNegative(unittest.TestCase):
with self.assertRaises(RuntimeError):
j.write(data, psnr=[30, 35, 40], cratios=[2, 3, 4])
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_NR_MarkerIsNotCompliant_j2k_dump(self):
# SOT marker gives bad offset.
relpath = 'input/nonregression/MarkerIsNotCompliant.j2k'
jfile = os.path.join(data_root, relpath)
jp2k = Jp2k(jfile)
with self.assertWarns(UserWarning) as cw:
c = jp2k.get_codestream(header_only=False)
# Verify that the last segment returned in the codestream is SOD,
# not EOC. Codestream parsing should stop when we try to jump to
# the end of SOT.
self.assertEqual(c.segment[-1].marker_id, 'SOD')
c = jp2k.get_codestream(header_only=False)
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_NR_illegalcolortransform_dump(self):
# SOT marker gives bad offset.
# EOC marker is bad
relpath = 'input/nonregression/illegalcolortransform.j2k'
jfile = os.path.join(data_root, relpath)
jp2k = Jp2k(jfile)
@ -103,20 +94,11 @@ class TestSuiteNegative(unittest.TestCase):
# the end of SOT.
self.assertEqual(c.segment[-1].marker_id, 'SOD')
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_NR_Cannotreaddatawithnosizeknown_j2k(self):
# SOT marker gives bad offset.
relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k'
jfile = os.path.join(data_root, relpath)
jp2k = Jp2k(jfile)
with self.assertWarns(UserWarning) as cw:
c = jp2k.get_codestream(header_only=False)
# Verify that the last segment returned in the codestream is SOD,
# not EOC. Codestream parsing should stop when we try to jump to
# the end of SOT.
self.assertEqual(c.segment[-1].marker_id, 'SOD')
c = jp2k.get_codestream(header_only=False)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_code_block_dimensions(self):

View file

@ -6,34 +6,38 @@
| | | | | pass. |
+-----------+--------+--------+--------+--------------------------------------+
| Mac | X | | | MacPorts with both OpenJPEG 1.5.1 |
| 10.6.8 | | | | and OpenJPEG svn. 353 of 449 tests |
| 10.6.8 | | | | and OpenJPEG svn. 352 of 450 tests |
| | | | | should pass. |
+-----------+--------+--------+--------+--------------------------------------+
| Mac | | X | | MacPorts with both OpenJPEG 1.5.1 |
| 10.6.8 | | | | and OpenJPEG svn. 376 of 454 tests |
| 10.6.8 | | | | and OpenJPEG svn. 377 of 455 tests |
| | | | | should pass. |
+-----------+--------+--------+--------+--------------------------------------+
| Mac | | | X | MacPorts with both OpenJPEG 1.5.1 |
| 10.6.8 | | | | and OpenJPEG svn. 401 of 454 |
| 10.6.8 | | | | and OpenJPEG svn. 402 of 455 |
| | | | | tests should pass. |
+-----------+--------+--------+-----------------------------------------------+
| Fedora 19 | | | X | Ships with 1.5.1, openjp2 built too. |
| | | | | 401 of 454 tests should pass. |
| | | | | 402 of 455 tests should pass. |
+-----------+--------+--------+--------+--------------------------------------+
| Fedora 18 | | | X | Ships with 1.5.1. 169 of 449 tests |
| | | | | should pass. |
+-----------+--------+--------+--------+--------------------------------------+
| Fedora 17 | | X | | Ships with 1.4.0. 169 of 449 tests |
| Fedora 17 | | X | | Ships with 1.4.0. 166 of 450 tests |
| | | | | should pass. |
+-----------+--------+--------+--------+--------------------------------------+
| CentOS | X | | | Ships with 1.3.0. 167 of 449 tests |
| CentOS | X | | | Ships with 1.3.0. 164 of 450 tests |
| 6.3 | | | | should pass. |
+-----------+--------+--------+--------+--------------------------------------+
| Raspberry | | X | | Ships with 1.3.0. 169 of 449 tests |
| Raspberry | | X | | Ships with 1.3.0. 166 of 450 tests |
| Pi | | | | should pass. |
| Debian 7 | | | | |
+-----------+--------+--------+--------+--------------------------------------+
Make release branch, qualify on all platforms.
Pylint on entire package should exceed 0.95.
pep8 should be pass cleanly.
Coverage should exceed 95%.
Make release candidate, push to Pypi, qualify in virtual environment.
Merge release branch to master, tag, push to master, push to Pypi.

View file

@ -2,7 +2,7 @@ from setuptools import setup, find_packages
import sys
kwargs = {'name': 'Glymur',
'version': '0.2.3',
'version': '0.2.4',
'description': 'Tools for accessing JPEG2000 files',
'long_description': open('README.md').read(),
'author': 'John Evans',