Merge branch 'release-0.2.5'

This commit is contained in:
jevans 2013-07-22 18:07:45 -04:00
commit 729f42b5c9
9 changed files with 32 additions and 52 deletions

View file

@ -1,3 +1,6 @@
Jul 23, 2013 - v0.2.5 Fixed inconsistency in XML handling, now all instances
are always ElementTree objects (issue82).
Jul 21, 2013 - v0.2.4 Fixed markdown bug for Fedora 17 information, fixed Jul 21, 2013 - v0.2.4 Fixed markdown bug for Fedora 17 information, fixed
out-of-date windows information (issue79). Fixed incorrect out-of-date windows information (issue79). Fixed incorrect
interpretation of Psot parameter (issue78). interpretation of Psot parameter (issue78).

View file

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

View file

@ -185,9 +185,8 @@ Work with XMP UUIDs?
==================== ====================
The example JP2 file shipped with glymur has an XMP UUID. :: The example JP2 file shipped with glymur has an XMP UUID. ::
>>> from glymur import Jp2k >>> import glymur
>>> file = glymur.data.nemo() >>> j = glymur.Jp2k(glymur.data.nemo())
>>> j = Jp2k(file)
>>> print(j.box[4]) >>> print(j.box[4])
UUID Box (uuid) @ (715, 2412) UUID Box (uuid) @ (715, 2412)
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP) UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
@ -198,7 +197,7 @@ The example JP2 file shipped with glymur has an XMP UUID. ::
</rdf:RDF> </rdf:RDF>
</ns0:xmpmeta> </ns0:xmpmeta>
Since the UUID data in this case is returned as an ElementTree Element, one can Since the UUID data in this case is returned as an ElementTree instance, one can
use ElementTree to access the data. For example, to extract the use ElementTree to access the data. For example, to extract the
**CreatorTool** attribute value, the following would work:: **CreatorTool** attribute value, the following would work::

View file

@ -6,7 +6,6 @@ Here's an incomplete list of what I'd like to focus on in the near future.
* continue to monitor upstream changes in the openjp2 library * continue to monitor upstream changes in the openjp2 library
* investigate using CFFI or cython instead of ctypes to wrap openjp2 * investigate using CFFI or cython instead of ctypes to wrap openjp2
* investigate swapping out ElementTree for LXML
* eventually expose the openjp2 API * eventually expose the openjp2 API
* investigate JPIP * investigate JPIP

View file

@ -42,16 +42,6 @@ for _marker in range(0xff90, 0xff94):
_VALID_MARKERS.append(_marker) _VALID_MARKERS.append(_marker)
class InconsistentStartOfTileError(IOError):
"""To be raised if bad SOT segment encountered.
SOT segment offsets are recorded as encountered. The offsets should all be
different.
"""
def __init__(self, msg):
IOError.__init__(self, msg)
class Codestream(object): class Codestream(object):
"""Container for codestream information. """Container for codestream information.
@ -115,8 +105,8 @@ class Codestream(object):
marker_id, = struct.unpack('>H', read_buffer) marker_id, = struct.unpack('>H', read_buffer)
if marker_id == 0xff90 and header_only: if marker_id == 0xff90 and header_only:
# start-of-tile (SOT) means we are out of the main header. # Start-of-tile (SOT) means that we are out of the main header
# No need to go any further. # and there is no need to go further.
break break
try: try:
@ -135,7 +125,7 @@ class Codestream(object):
if marker_id == 0xff93: if marker_id == 0xff93:
# If SOD, then we need to seek past the tile part bit stream. # If SOD, then we need to seek past the tile part bit stream.
if self._parse_tpart_flag: if self._parse_tpart_flag and not header_only:
# But first parse the tile part bit stream for SOP and # But first parse the tile part bit stream for SOP and
# EPH segments. # EPH segments.
self._parse_tile_part_bit_stream(fptr, segment, self._parse_tile_part_bit_stream(fptr, segment,
@ -143,6 +133,7 @@ class Codestream(object):
fptr.seek(self._tile_offset[-1] + self._tile_length[-1]) fptr.seek(self._tile_offset[-1] + self._tile_length[-1])
def _process_marker_segment(self, fptr, marker_id): def _process_marker_segment(self, fptr, marker_id):
"""Process and return a segment from the codestream. """Process and return a segment from the codestream.
""" """
@ -207,19 +198,12 @@ class Codestream(object):
# we encounter start-of-data marker segments. # we encounter start-of-data marker segments.
segment = _parse_sot_segment(fptr) segment = _parse_sot_segment(fptr)
if segment.offset not in self._tile_offset: self._tile_offset.append(segment.offset)
self._tile_offset.append(segment.offset) if segment.psot == 0:
if segment.psot == 0: tile_part_length = self.offset + self.length - segment.offset - 2
tile_part_length = self.offset + self.length - segment.offset - 2
else:
tile_part_length = segment.psot
self._tile_length.append(tile_part_length)
else: else:
msg = "Inconsistent start-of-tile (SOT) marker segment " tile_part_length = segment.psot
msg += "encountered in tile with index {0}. " self._tile_length.append(tile_part_length)
msg += "Codestream parsing terminated."
msg = msg.format(segment.isot)
raise InconsistentStartOfTileError(msg)
elif marker_id == 0xff93: elif marker_id == 0xff93:
# start of data. Need to seek past the current tile part. # start of data. Need to seek past the current tile part.

View file

@ -1608,7 +1608,7 @@ class XMLBox(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.
xml : ElementTree.Element xml : ElementTree object
XML section. XML section.
""" """
def __init__(self, xml=None, filename=None, length=0, offset=-1): def __init__(self, xml=None, filename=None, length=0, offset=-1):
@ -1636,10 +1636,7 @@ class XMLBox(Jp2kBox):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
xml = self.xml xml = self.xml
if self.xml is not None: if self.xml is not None:
try: msg += _pretty_print_xml(self.xml)
msg += _pretty_print_xml(self.xml)
except TypeError:
msg += _pretty_print_xml(self.xml.getroot())
else: else:
msg += '\n {0}'.format(xml) msg += '\n {0}'.format(xml)
return msg return msg
@ -1682,7 +1679,8 @@ class XMLBox(Jp2kBox):
text = text.rstrip('\0') text = text.rstrip('\0')
try: try:
xml = ET.fromstring(text) elt = ET.fromstring(text)
xml = ET.ElementTree(elt)
except ParseError as parse_error: except ParseError as parse_error:
msg = 'A problem was encountered while parsing an XML box: "{0}"' msg = 'A problem was encountered while parsing an XML box: "{0}"'
msg = msg.format(str(parse_error)) msg = msg.format(str(parse_error))
@ -1926,13 +1924,11 @@ class UUIDBox(Jp2kBox):
# XMP data. Parse as XML. Seems to be a difference between # XMP data. Parse as XML. Seems to be a difference between
# ElementTree in version 2.7 and 3.3. # ElementTree in version 2.7 and 3.3.
if sys.hexversion < 0x03000000: if sys.hexversion < 0x03000000:
#parser = ET.XMLParser(encoding='utf-8') elt = ET.fromstring(raw_data)
#import pdb; pdb.set_trace()
#self.data = ET.fromstringlist(raw_data, parser=parser)
self.data = ET.fromstring(raw_data)
else: else:
text = raw_data.decode('utf-8') text = raw_data.decode('utf-8')
self.data = ET.fromstring(text) elt = ET.fromstring(text)
self.data = ET.ElementTree(elt)
elif the_uuid.bytes == b'JpgTiffExif->JP2': elif the_uuid.bytes == b'JpgTiffExif->JP2':
exif_obj = Exif(raw_data) exif_obj = Exif(raw_data)
ifds = OrderedDict() ifds = OrderedDict()
@ -2555,8 +2551,8 @@ def _pretty_print_xml(xml, level=0):
"""Pretty print XML data. """Pretty print XML data.
""" """
xml = copy.deepcopy(xml) xml = copy.deepcopy(xml)
_indent(xml, level=level) _indent(xml.getroot(), level=level)
xmltext = ET.tostring(xml).decode('utf-8') xmltext = ET.tostring(xml.getroot()).decode('utf-8')
# Indent it a bit. # Indent it a bit.
lst = [(' ' + x) for x in xmltext.split('\n')] lst = [(' ' + x) for x in xmltext.split('\n')]

View file

@ -365,7 +365,7 @@ class TestXML(unittest.TestCase):
j2k.wrap(tfile.name, boxes=boxes) j2k.wrap(tfile.name, boxes=boxes)
jp2 = Jp2k(tfile.name) jp2 = Jp2k(tfile.name)
self.assertEqual(jp2.box[3].box_id, 'xml ') self.assertEqual(jp2.box[3].box_id, 'xml ')
self.assertEqual(ET.tostring(jp2.box[3].xml), self.assertEqual(ET.tostring(jp2.box[3].xml.getroot()),
b'<data>0</data>') b'<data>0</data>')
@unittest.skipIf(os.name == "nt", @unittest.skipIf(os.name == "nt",

View file

@ -4021,7 +4021,7 @@ class TestSuiteDump(unittest.TestCase):
self.assertEqual(jp2.box[1].compatibility_list[1], 'jp2 ') self.assertEqual(jp2.box[1].compatibility_list[1], 'jp2 ')
# XML box # XML box
tags = [x.tag for x in jp2.box[2].xml] tags = [x.tag for x in jp2.box[2].xml.getroot()]
self.assertEqual(tags, self.assertEqual(tags,
['{http://www.jpeg.org/jpx/1.0/xml}' ['{http://www.jpeg.org/jpx/1.0/xml}'
+ 'GENERAL_CREATION_INFO']) + 'GENERAL_CREATION_INFO'])
@ -4046,7 +4046,7 @@ class TestSuiteDump(unittest.TestCase):
self.assertEqual(jp2.box[3].box[1].colorspace, glymur.core.SRGB) self.assertEqual(jp2.box[3].box[1].colorspace, glymur.core.SRGB)
# XML box # XML box
tags = [x.tag for x in jp2.box[4].xml] tags = [x.tag for x in jp2.box[4].xml.getroot()]
self.assertEqual(tags, ['{http://www.jpeg.org/jpx/1.0/xml}CAPTION', self.assertEqual(tags, ['{http://www.jpeg.org/jpx/1.0/xml}CAPTION',
'{http://www.jpeg.org/jpx/1.0/xml}LOCATION', '{http://www.jpeg.org/jpx/1.0/xml}LOCATION',
'{http://www.jpeg.org/jpx/1.0/xml}EVENT']) '{http://www.jpeg.org/jpx/1.0/xml}EVENT'])
@ -4376,13 +4376,13 @@ class TestSuiteDump(unittest.TestCase):
self.assertIsNone(jp2.box[2].box[1].colorspace) self.assertIsNone(jp2.box[2].box[1].colorspace)
# XML box # XML box
tags = [x.tag for x in jp2.box[3].xml] tags = [x.tag for x in jp2.box[3].xml.getroot()]
self.assertEqual(tags, self.assertEqual(tags,
['{http://www.jpeg.org/jpx/1.0/xml}' ['{http://www.jpeg.org/jpx/1.0/xml}'
+ 'GENERAL_CREATION_INFO']) + 'GENERAL_CREATION_INFO'])
# XML box # XML box
tags = [x.tag for x in jp2.box[5].xml] tags = [x.tag for x in jp2.box[5].xml.getroot()]
self.assertEqual(tags, self.assertEqual(tags,
['{http://www.jpeg.org/jpx/1.0/xml}CAPTION', ['{http://www.jpeg.org/jpx/1.0/xml}CAPTION',
'{http://www.jpeg.org/jpx/1.0/xml}LOCATION', '{http://www.jpeg.org/jpx/1.0/xml}LOCATION',
@ -6954,8 +6954,7 @@ class TestSuiteDump(unittest.TestCase):
self.assertEqual(c.segment[3]._exponent, [4] + [5, 5, 6] * 5) self.assertEqual(c.segment[3]._exponent, [4] + [5, 5, 6] * 5)
def test_NR_merged_dump(self): def test_NR_merged_dump(self):
jfile = os.path.join(data_root, jfile = os.path.join(data_root, 'input/nonregression/merged.jp2')
'input/nonregression/merged.jp2')
jp2 = Jp2k(jfile) jp2 = Jp2k(jfile)
ids = [box.box_id for box in jp2.box] ids = [box.box_id for box in jp2.box]

View file

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