Merge branch 'devel'

This commit is contained in:
John Evans 2013-05-31 08:30:46 -04:00
commit f2e67007a3
13 changed files with 213 additions and 121 deletions

View file

@ -1,7 +1,8 @@
May 28, 2013 - Added jp2 boxes to rst docs, XMLBox.indent method made private.
May 30, 2013 - v0.1.2. Added XMP UUID read support. Added jp2 boxes to rst
docs, XMLBox.indent method made into a private module method. Precinct
sizes restricted to be multiples of two.
May 27, 2013 - v0.1.1, Changed write example to not rely on matplotlib. Fixed
May 27, 2013 - v0.1.1. Changed write example to not rely on matplotlib. Fixed
readthedocs.org setup to build documentation automatically. Can import
glymur without libopenjp2 actually being present.
May 27, 2013 - Changed write example to not rely on matplotlib.
glymur without libopenjp2 actually being present. Changed write example
to not rely on matplotlib.

View file

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

View file

@ -7,9 +7,9 @@ which allows linux and mac users to read and write JPEG 2000 files. For more
information about OpenJPEG, please consult http://www.openjpeg.org. glymur
should be considered to be alpha-quality software.
glymur tries to support reading (including all metadata) and writing of
JP2 and J2C files. Writing J2C/JP2 files is currently limited to images that
can fit in memory, however.
glymur tries to support reading and writing of JP2 and J2C files. Writing
J2C/JP2 files is currently limited to images that can fit in memory, however.
Of particular focus is metadata retrieval, such as XMP packets.
There is some very limited support for reading JPX
metadata. For instance, **asoc** and **labl** boxes are recognized, so GMLJP2

View file

@ -16,24 +16,15 @@ def _glymurrc_fname():
if os.path.exists(fname):
return fname
# environ var GLYMURCONFIGDIR
if 'GLYMURCONFIGDIR' in os.environ:
path = os.environ['GLYMURCONFIGDIR']
if os.path.exists(path):
fname = os.path.join(path, 'glymurrc')
if os.path.exists(fname):
return fname
else:
msg = "glymurrc file hinted at by GLYMURCONFIGDIR does not "
msg += "exist."
warnings.warn(msg, UserWarning)
# HOME/.glymur/glymurrc
# Either GLYMURCONFIGDIR/glymurrc or $HOME/.glymur/glymurrc
confdir = _get_configdir()
if confdir is not None:
fname = os.path.join(_get_configdir(), 'glymurrc')
fname = os.path.join(confdir, 'glymurrc')
if os.path.exists(fname):
return fname
else:
msg = "Configuration file '{0}' does not exist.".format(confdir)
warnings.warn(msg, UserWarning)
# didn't find a configuration file.
return None

View file

@ -472,8 +472,6 @@ class Codestream:
SPcod = f.read(n)
kwargs['SPcod'] = np.frombuffer(SPcod, dtype=np.uint8)
# 0:
# 1: layers
params = struct.unpack('>BHBBBBBB', SPcod[0:9])
kwargs['_layers'] = params[1]
kwargs['_numresolutions'] = params[3]

Binary file not shown.

View file

@ -1288,37 +1288,11 @@ class XMLBox(Jp2kBox):
Jp2kBox.__init__(self, id='', longname='XML')
self.__dict__.update(**kwargs)
def _indent(self, elem, level=0):
"""recipe for pretty printing XML. Please see
http://effbot.org/zone/element-lib.htm#prettyprint
"""
i = "\n" + level * " "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
self._indent(elem, level + 1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
def __str__(self):
msg = Jp2kBox.__str__(self)
xml = self.xml
if self.xml is not None:
xml = copy.deepcopy(self.xml)
self._indent(xml)
xmltext = ET.tostring(xml).decode('utf-8')
# Indent it a bit.
lst = [(' ' + x) for x in xmltext.split('\n')]
xml = '\n'.join(lst)
msg += '\n{0}'.format(xml)
msg += _pretty_print_xml(self.xml)
else:
msg += '\n {0}'.format(xml)
return msg
@ -1581,17 +1555,30 @@ class UUIDBox(Jp2kBox):
more verbose description of the box.
uuid : uuid.UUID
16-byte UUID
data : bytes
Vendor-specific UUID data.
data : bytes or ElementTree.Element
Vendor-specific UUID data. XMP UUIDs are interpreted as standard XML.
"""
def __init__(self, **kwargs):
Jp2kBox.__init__(self, id='', longname='UUID')
self.__dict__.update(**kwargs)
def __str__(self):
msg = Jp2kBox.__str__(self)
msg += '\n UUID: {0}'.format(self.uuid)
msg += '\n UUID Data: {0} bytes'.format(len(self.data))
msg = '{0}\n'
msg += ' UUID: {1}{2}\n'
msg += ' UUID Data: {3}'
if self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
uuid_type = ' (XMP)'
uuid_data = _pretty_print_xml(self.data)
else:
uuid_type = ''
uuid_data = '{0} bytes'.format(len(self.data))
msg = msg.format(Jp2kBox.__str__(self),
self.uuid,
uuid_type,
uuid_data)
return msg
@staticmethod
@ -1622,7 +1609,17 @@ class UUIDBox(Jp2kBox):
n = offset + length - f.tell()
buffer = f.read(n)
kwargs['data'] = buffer
if kwargs['uuid'] == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
# XMP data. Parse as XML. Seems to be a difference between
# ElementTree in version 2.7 and 3.3.
if sys.hexversion < 0x03000000:
parser = ET.XMLParser(encoding='utf-8')
kwargs['data'] = ET.fromstringlist(buffer, parser=parser)
else:
text = buffer.decode('utf-8')
kwargs['data'] = ET.fromstring(text)
else:
kwargs['data'] = buffer
box = UUIDBox(**kwargs)
return box
@ -1649,3 +1646,34 @@ _box_with_id = {
'url ': DataEntryURLBox,
'uuid': UUIDBox,
'xml ': XMLBox}
def _indent(elem, level=0):
"""Recipe for pretty printing XML. Please see
http://effbot.org/zone/element-lib.htm#prettyprint
"""
i = "\n" + level * " "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
_indent(elem, level + 1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
def _pretty_print_xml(xml, level=0):
"""Pretty print XML data.
"""
xml = copy.deepcopy(xml)
_indent(xml, level=level)
xmltext = ET.tostring(xml).decode('utf-8')
# Indent it a bit.
lst = [(' ' + x) for x in xmltext.split('\n')]
xml = '\n'.join(lst)
return '\n{0}'.format(xml)

View file

@ -8,6 +8,7 @@ if sys.hexversion >= 0x03030000:
else:
from contextlib2 import ExitStack
import ctypes
import math
import os
import struct
import warnings
@ -152,7 +153,7 @@ class Jp2k(Jp2kBox):
data : array
Image data to be written to file.
callbacks : bool, optional
If true, enable default info handler such that INFO messages
If true, enable default info handler such that INFO messages
produced by the OpenJPEG library are output to the console. By
default, OpenJPEG warning and error messages are captured by
Python's own warning and error mechanisms.
@ -181,7 +182,8 @@ class Jp2k(Jp2kBox):
psnr : list, optional
Different PSNR for successive layers.
psizes : list, optional
List of precinct sizes.
List of precinct sizes. Each precinct size tuple is defined in
(height x width).
sop : bool, optional
If true, write SOP marker before each packet.
subsam : tuple, optional
@ -266,9 +268,15 @@ class Jp2k(Jp2kBox):
cparams.cp_fixed_quality = 1
if psizes is not None:
for j, precinct in enumerate(psizes):
cparams.prcw_init[j] = precinct[0]
cparams.prch_init[j] = precinct[1]
for j, (prch, prcw) in enumerate(psizes):
if ((math.log(prch, 2) != math.floor(math.log(prch, 2)) or
math.log(prcw, 2) != math.floor(math.log(prcw, 2)))):
msg = "Bad precinct size ({0}, {1}), "
msg += "must be multiple of 2."
raise IOError(msg.format(prch, prcw))
cparams.prcw_init[j] = prcw
cparams.prch_init[j] = prch
cparams.csty |= 0x01
cparams.res_spec = len(psizes)
@ -634,7 +642,7 @@ class Jp2k(Jp2kBox):
>>> jp = glymur.Jp2k(jfile)
>>> codestream = jp.get_codestream()
>>> print(codestream.segment[1])
SIZ marker segment @ (87, 47)
SIZ marker segment @ (3137, 47)
Profile: 2
Reference Grid Height, Width: (1456 x 2592)
Vertical, Horizontal Reference Grid Offset: (0 x 0)

View file

@ -53,7 +53,7 @@ class TestCallbacks(unittest.TestCase):
d = j.read(reduce=3, verbose=True, area=(0, 0, 512, 1024))
actual = sys.stdout.getvalue().strip()
lines = ['[INFO] Start to read j2k main header (85).',
lines = ['[INFO] Start to read j2k main header (3135).',
'[INFO] Main header has been correctly decoded.',
'[INFO] Setting decoding area to 0,0,1024,512',
'[INFO] Header of tile 0 / 17 has been read.',

View file

@ -50,19 +50,13 @@ def chdir(dirname=None):
class TestJp2k(unittest.TestCase):
def setUp(self):
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
"data/nemo.jp2")
def tearDown(self):
pass
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_invalid_xml_box(self):
# Should be able to recover from xml box with bad xml.
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
with open(self.jp2file, 'rb') as ifile:
@classmethod
def setUpClass(cls):
jp2file = pkg_resources.resource_filename(glymur.__name__,
"data/nemo.jp2")
with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile:
cls._bad_xml_file = tfile.name
with open(jp2file, 'rb') as ifile:
# Everything up until the jp2c box.
buffer = ifile.read(77)
tfile.write(buffer)
@ -81,13 +75,35 @@ class TestJp2k(unittest.TestCase):
tfile.write(buffer)
tfile.flush()
with self.assertWarns(UserWarning) as cw:
jp2k = Jp2k(tfile.name)
@classmethod
def tearDownClass(cls):
os.unlink(cls._bad_xml_file)
self.assertEqual(jp2k.box[3].id, 'xml ')
self.assertEqual(jp2k.box[3].offset, 77)
self.assertEqual(jp2k.box[3].length, 28)
self.assertIsNone(jp2k.box[3].xml)
def setUp(self):
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
"data/nemo.jp2")
def tearDown(self):
pass
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_invalid_xml_box_warning(self):
# Should be able to recover from xml box with bad xml.
# Just verify that a warning is issued on 3.2+
with self.assertWarns(UserWarning) as cw:
jp2k = Jp2k(self._bad_xml_file)
def test_invalid_xml_box(self):
# Should be able to recover from xml box with bad xml.
with warnings.catch_warnings():
warnings.simplefilter("ignore")
jp2k = Jp2k(self._bad_xml_file)
self.assertEqual(jp2k.box[3].id, 'xml ')
self.assertEqual(jp2k.box[3].offset, 77)
self.assertEqual(jp2k.box[3].length, 28)
self.assertIsNone(jp2k.box[3].xml)
def test_bad_area_parameter(self):
# Verify that we error out appropriately if given a bad area parameter.
@ -139,7 +155,7 @@ class TestJp2k(unittest.TestCase):
jp2k = Jp2k(self.jp2file)
# top-level boxes
self.assertEqual(len(jp2k.box), 4)
self.assertEqual(len(jp2k.box), 6)
self.assertEqual(jp2k.box[0].id, 'jP ')
self.assertEqual(jp2k.box[0].offset, 0)
@ -156,9 +172,17 @@ class TestJp2k(unittest.TestCase):
self.assertEqual(jp2k.box[2].length, 45)
self.assertEqual(jp2k.box[2].longname, 'JP2 Header')
self.assertEqual(jp2k.box[3].id, 'jp2c')
self.assertEqual(jp2k.box[3].id, 'uuid')
self.assertEqual(jp2k.box[3].offset, 77)
self.assertEqual(jp2k.box[3].length, 1133427)
self.assertEqual(jp2k.box[3].length, 638)
self.assertEqual(jp2k.box[4].id, 'uuid')
self.assertEqual(jp2k.box[4].offset, 715)
self.assertEqual(jp2k.box[4].length, 2412)
self.assertEqual(jp2k.box[5].id, 'jp2c')
self.assertEqual(jp2k.box[5].offset, 3127)
self.assertEqual(jp2k.box[5].length, 1133427)
# jp2h super box
self.assertEqual(len(jp2k.box[2].box), 2)
@ -200,7 +224,7 @@ class TestJp2k(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
with open(self.jp2file, 'rb') as ifile:
# Everything up until the jp2c box.
buffer = ifile.read(77)
buffer = ifile.read(3127)
tfile.write(buffer)
# The L field must be 1 in order to signal the presence of the
@ -221,9 +245,9 @@ class TestJp2k(unittest.TestCase):
jp2k = Jp2k(tfile.name)
self.assertEqual(jp2k.box[3].id, 'jp2c')
self.assertEqual(jp2k.box[3].offset, 77)
self.assertEqual(jp2k.box[3].length, 1133427 + 8)
self.assertEqual(jp2k.box[5].id, 'jp2c')
self.assertEqual(jp2k.box[5].offset, 3127)
self.assertEqual(jp2k.box[5].length, 1133427 + 8)
def test_L_is_zero(self):
# Verify that boxes with the L field as zero are correctly read.
@ -513,10 +537,9 @@ class TestJp2k(unittest.TestCase):
# Now append the codestream.
tfile2.write(codestream)
tfile2.flush()
with warnings.catch_warnings():
warnings.simplefilter("ignore")
jasoc = Jp2k(tfile2.name)
jasoc = Jp2k(tfile2.name)
self.assertEqual(jasoc.box[3].id, 'asoc')
self.assertEqual(jasoc.box[3].box[0].id, 'lbl ')
self.assertEqual(jasoc.box[3].box[0].label, 'label')
@ -528,17 +551,19 @@ class TestJp2k(unittest.TestCase):
with open(self.jp2file, 'rb') as fp:
data = fp.read()
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
tfile.write(data[0:129])
# Codestream starts at byte 3127. SIZ marker at 3137.
# COD marker at 3186. Subsampling at 3180.
tfile.write(data[0:3179])
# Make the DY bytes of the SIZ segment zero. That means that
# a subsampling factor is zero, which is illegal.
tfile.write(b'\x00')
tfile.write(data[130:132])
tfile.write(data[3180:3182])
tfile.write(b'\x00')
tfile.write(data[134:136])
tfile.write(data[3184:3186])
tfile.write(b'\x00')
tfile.write(data[136:])
tfile.write(data[3186:])
tfile.flush()
with warnings.catch_warnings():
warnings.simplefilter("ignore")
@ -597,6 +622,17 @@ class TestJp2k(unittest.TestCase):
with self.assertWarns(UserWarning) as cw:
imp.reload(glymur)
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_home_dir_missing_config_dir(self):
# Verify no exception is raised if $HOME is missing .glymur directory.
with tempfile.TemporaryDirectory() as tdir:
with patch.dict('os.environ', {'HOME': tdir}):
# Misconfigured new configuration file should
# be rejected.
with self.assertWarns(UserWarning) as cw:
imp.reload(glymur)
if __name__ == "__main__":
unittest.main()

View file

@ -9,6 +9,7 @@ import unittest
import warnings
import numpy as np
import pkg_resources
from ..lib import openjp2 as opj2
@ -62,7 +63,8 @@ def read_image(infile):
class TestSuiteNegative(unittest.TestCase):
def setUp(self):
pass
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
"data/nemo.jp2")
def tearDown(self):
pass
@ -150,5 +152,14 @@ class TestSuiteNegative(unittest.TestCase):
with self.assertWarns(UserWarning) as cw:
j = Jp2k(infile)
def test_precinct_size_not_multiple_of_two(self):
# Seems like precinct size should be a multiple of two.
ifile = Jp2k(self.jp2file)
data = ifile.read(reduce=3)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce:
ofile.write(data, psizes=[(13, 13)])
if __name__ == "__main__":
unittest.main()

View file

@ -47,10 +47,26 @@ class TestPrinting(unittest.TestCase):
' Method: enumerated colorspace',
' Precedence: 0',
' Colorspace: sRGB',
'Contiguous Codestream Box (jp2c) @ (77, 1133427)',
'UUID Box (uuid) @ (77, 638)',
' UUID: 4a706754-6966-6645-7869-662d3e4a5032',
' UUID Data: 614 bytes',
'UUID Box (uuid) @ (715, 2412)',
' UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)',
' UUID Data: ',
' <ns0:xmpmeta xmlns:ns0="adobe:ns:meta/" '
+ 'xmlns:ns2="http://ns.adobe.com/xap/1.0/" '
+ 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" '
+ 'ns0:xmptk="XMP Core 4.4.0-Exiv2">',
' <rdf:RDF>',
' <rdf:Description ns2:CreatorTool="glymur" '
+ 'rdf:about="" />',
' </rdf:RDF>',
' </ns0:xmpmeta>',
' ',
'Contiguous Codestream Box (jp2c) @ (3127, 1133427)',
' Main header:',
' SOC marker segment @ (85, 0)',
' SIZ marker segment @ (87, 47)',
' SOC marker segment @ (3135, 0)',
' SIZ marker segment @ (3137, 47)',
' Profile: 2',
' Reference Grid Height, Width: (1456 x 2592)',
' Vertical, Horizontal Reference Grid Offset: '
@ -62,7 +78,7 @@ class TestPrinting(unittest.TestCase):
' Signed: (False, False, False)',
' Vertical, Horizontal Subsampling: '
+ '((1, 1), (1, 1), (1, 1))',
' COD marker segment @ (136, 12)',
' COD marker segment @ (3186, 12)',
' Coding style:',
' Entropy coder, without partitions',
' SOP marker segments: False',
@ -86,7 +102,7 @@ class TestPrinting(unittest.TestCase):
+ 'False',
' Predictable termination: False',
' Segmentation symbols: False',
' QCD marker segment @ (150, 19)',
' QCD marker segment @ (3200, 19)',
' Quantization style: no quantization, '
+ '2 guard bits',
' Step size: [(0, 8), (0, 9), (0, 9), '
@ -98,10 +114,13 @@ class TestPrinting(unittest.TestCase):
def tearDown(self):
# Restore stdout.
sys.stdout = self.stdout
#import pdb; pdb.set_trace()
def test_jp2dump(self):
glymur.jp2dump(self.jp2file)
actual = sys.stdout.getvalue().strip()
self.actual = actual
self.expected = self.expectedNemo
self.assertEqual(actual, self.expectedNemo)
def test_COC_segment(self):
@ -110,7 +129,7 @@ class TestPrinting(unittest.TestCase):
print(codestream.segment[5])
actual = sys.stdout.getvalue().strip()
lines = ['COC marker segment @ (183, 9)',
lines = ['COC marker segment @ (3233, 9)',
' Associated component: 1',
' Coding style for this component: '
+ 'Entropy coder, PARTITION = 0',
@ -136,7 +155,7 @@ class TestPrinting(unittest.TestCase):
print(codestream.segment[2])
actual = sys.stdout.getvalue().strip()
lines = ['COD marker segment @ (136, 12)',
lines = ['COD marker segment @ (3186, 12)',
' Coding style:',
' Entropy coder, without partitions',
' SOP marker segments: False',
@ -226,7 +245,7 @@ class TestPrinting(unittest.TestCase):
print(codestream.segment[-1])
actual = sys.stdout.getvalue().strip()
lines = ['EOC marker segment @ (1133502, 0)']
lines = ['EOC marker segment @ (1136552, 0)']
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@ -313,7 +332,7 @@ class TestPrinting(unittest.TestCase):
print(codestream.segment[6])
actual = sys.stdout.getvalue().strip()
lines = ['QCC marker segment @ (194, 20)',
lines = ['QCC marker segment @ (3244, 20)',
' Associated Component: 1',
' Quantization style: no quantization, 2 guard bits',
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), '
@ -329,7 +348,7 @@ class TestPrinting(unittest.TestCase):
print(codestream.segment[3])
actual = sys.stdout.getvalue().strip()
lines = ['QCD marker segment @ (150, 19)',
lines = ['QCD marker segment @ (3200, 19)',
' Quantization style: no quantization, 2 guard bits',
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10), (0, 9), '
+ '(0, 9), (0, 10), (0, 9), (0, 9), (0, 10), (0, 9), '
@ -344,7 +363,7 @@ class TestPrinting(unittest.TestCase):
print(codestream.segment[1])
actual = sys.stdout.getvalue().strip()
lines = ['SIZ marker segment @ (87, 47)',
lines = ['SIZ marker segment @ (3137, 47)',
' Profile: 2',
' Reference Grid Height, Width: (1456 x 2592)',
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
@ -364,7 +383,7 @@ class TestPrinting(unittest.TestCase):
print(codestream.segment[0])
actual = sys.stdout.getvalue().strip()
lines = ['SOC marker segment @ (85, 0)']
lines = ['SOC marker segment @ (3135, 0)']
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@ -374,7 +393,7 @@ class TestPrinting(unittest.TestCase):
print(codestream.segment[9])
actual = sys.stdout.getvalue().strip()
lines = ['SOD marker segment @ (249, 0)']
lines = ['SOD marker segment @ (3299, 0)']
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@ -384,7 +403,7 @@ class TestPrinting(unittest.TestCase):
print(codestream.segment[4])
actual = sys.stdout.getvalue().strip()
lines = ['SOT marker segment @ (171, 10)',
lines = ['SOT marker segment @ (3221, 10)',
' Tile part index: 0',
' Tile part length: 78629',
' Tile part instance: 0',
@ -422,8 +441,8 @@ class TestPrinting(unittest.TestCase):
actual = sys.stdout.getvalue().strip()
lst = ['Codestream:',
' SOC marker segment @ (85, 0)',
' SIZ marker segment @ (87, 47)',
' SOC marker segment @ (3135, 0)',
' SIZ marker segment @ (3137, 47)',
' Profile: 2',
' Reference Grid Height, Width: (1456 x 2592)',
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
@ -433,7 +452,7 @@ class TestPrinting(unittest.TestCase):
' Signed: (False, False, False)',
' Vertical, Horizontal Subsampling: '
+ '((1, 1), (1, 1), (1, 1))',
' COD marker segment @ (136, 12)',
' COD marker segment @ (3186, 12)',
' Coding style:',
' Entropy coder, without partitions',
' SOP marker segments: False',
@ -455,7 +474,7 @@ class TestPrinting(unittest.TestCase):
' Vertically stripe causal context: False',
' Predictable termination: False',
' Segmentation symbols: False',
' QCD marker segment @ (150, 19)',
' QCD marker segment @ (3200, 19)',
' Quantization style: no quantization, '
+ '2 guard bits',
' Step size: [(0, 8), (0, 9), (0, 9), '

View file

@ -1,9 +1,9 @@
from distutils.core import setup
kwargs = {'name': 'glymur',
'version': '0.1.1',
'description': 'Tools for manipulating JPEG2000 files',
'long_description': open('README').read(),
kwargs = {'name': 'Glymur',
'version': '0.1.2',
'description': 'Tools for accessing JPEG2000 files',
'long_description': open('README.md').read(),
'author': 'John Evans',
'author_email': 'johnevans938 at gmail dot com',
'url': 'https://github.com/quintusdias/glymur',