Merge branch 'devel' of github.com:quintusdias/glymur into devel

This commit is contained in:
John Evans 2013-11-13 17:44:13 -05:00
commit 52914d1411
13 changed files with 581 additions and 372 deletions

View file

@ -1,3 +1,12 @@
Oct 29, 2013 - Palette box now a 2D numpy array instead of a list of
1D arrays. Super box constructors now take optional box list argument.
Removed ssiz attribute from SIZsegment class.
Oct 29, 2013 - v0.5.9 Fixed bad library load on linux as a result of 0.5.8
Oct 29, 2013 - v0.5.8 Fixed unnecessary warnings when default locations for
openjpeg libraries on mac do not specify the actual library.
Oct 28, 2013 - v0.5.7 Fixed bad import error message when libopenjpeg library Oct 28, 2013 - v0.5.7 Fixed bad import error message when libopenjpeg library
not installed on mac. not installed on mac.

View file

@ -78,7 +78,7 @@ copyright = u'2013, John Evans'
# The short X.Y version. # The short X.Y version.
version = '0.5' version = '0.5'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.5.7' release = '0.5.9'
# 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

@ -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. 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* 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 instead of *openjpeg*) from the developmental source that you can retrieve
via subversion. As of this time of writing, svn revision 2347 works. via subversion. As of this time of writing, svn revision r2354 works.
You should also download the test data for the purpose of configuring You should also download the test data for the purpose of configuring
and running OpenJPEG's test suite, check their instructions for all this. and running OpenJPEG's test suite, check their instructions for all this.
You should set the **OPJ_DATA_ROOT** environment variable for the purpose You should set the **OPJ_DATA_ROOT** environment variable for the purpose

View file

@ -4,7 +4,7 @@ How do I...?
... read the lowest resolution thumbnail? ... read the lowest resolution thumbnail?
===================================== =========================================
Printing the Jp2k object should reveal the number of resolutions (look in the Printing the Jp2k object should reveal the number of resolutions (look in the
COD segment section), but you can take a shortcut by supplying -1 as the COD segment section), but you can take a shortcut by supplying -1 as the
resolution level. :: resolution level. ::
@ -15,7 +15,7 @@ resolution level. ::
>>> thumbnail = j.read(rlevel=-1) >>> thumbnail = j.read(rlevel=-1)
... display metadata? ... display metadata?
================= =====================
There are two ways. From the unix command line, the script *jp2dump* is There are two ways. From the unix command line, the script *jp2dump* is
available. :: available. ::
@ -35,7 +35,7 @@ codestream box, only the main header is printed. It is possible to print
>>> print(j.get_codestream()) >>> print(j.get_codestream())
... add XML metadata? ... add XML metadata?
================= =====================
You can append any number of XML boxes to a JP2 file (not to a raw codestream). You can append any number of XML boxes to a JP2 file (not to a raw codestream).
Consider the following XML file `data.xml` : :: Consider the following XML file `data.xml` : ::
@ -67,7 +67,7 @@ The **append** method can add an XML box as shown below::
>>> print(jp2) >>> print(jp2)
... add metadata in a more general fashion? ... add metadata in a more general fashion?
======================================= ===========================================
An existing raw codestream (or JP2 file) can be wrapped (re-wrapped) in a An existing raw codestream (or JP2 file) can be wrapped (re-wrapped) in a
user-defined set of JP2 boxes. To get just a minimal JP2 jacket on the user-defined set of JP2 boxes. To get just a minimal JP2 jacket on the
codestream provided by `goodstuff.j2k` (a file consisting of a raw codestream), codestream provided by `goodstuff.j2k` (a file consisting of a raw codestream),
@ -158,7 +158,7 @@ while **append** modifies an existing file and is currently limited to XML
boxes. boxes.
... create an image with an alpha layer? ... create an image with an alpha layer?
==================================== ========================================
OpenJPEG can create JP2 files with more than 3 components (requires OpenJPEG can create JP2 files with more than 3 components (requires
the development version of OpenJPEG), but by default, any extra components are the development version of OpenJPEG), but by default, any extra components are

View file

@ -646,16 +646,50 @@ class Codestream(object):
length, = struct.unpack('>H', read_buffer) length, = struct.unpack('>H', read_buffer)
xy_buffer = fptr.read(36) xy_buffer = fptr.read(36)
data = struct.unpack('>HIIIIIIIIH', xy_buffer)
num_components, = struct.unpack('>H', xy_buffer[-2:]) rsiz = data[0]
xysiz = (data[1], data[2])
xyosiz = (data[3], data[4])
xytsiz = (data[5], data[6])
xytosiz = (data[7], data[8])
component_buffer = fptr.read(num_components * 3) # Csiz is the number of components
Csiz = data[9]
segment = SIZsegment(xy_buffer, component_buffer, length, offset) component_buffer = fptr.read(Csiz * 3)
data = struct.unpack('>' + 'B' * len(component_buffer),
component_buffer)
bitdepth = tuple(((x & 0x7f) + 1) for x in data[0::3])
signed = tuple(((x & 0xb0) > 0) for x in data[0::3])
xrsiz = data[1::3]
yrsiz = data[2::3]
for j, subsampling in enumerate(zip(xrsiz, yrsiz)):
if 0 in subsampling:
msg = "Invalid subsampling value for component {0}: "
msg += "dx={1}, dy={2}."
msg = msg.format(j, subsampling[0], subsampling[1])
warnings.warn(msg)
kwargs = {'rsiz': rsiz,
'xysiz': xysiz,
'xyosiz': xyosiz,
'xytsiz': xytsiz,
'xytosiz': xytosiz,
'Csiz': Csiz,
'bitdepth': bitdepth,
'signed': signed,
'xyrsiz': (xrsiz, yrsiz),
'length': length,
'offset': offset}
segment = SIZsegment(**kwargs)
# Need to keep track of the number of components from SIZ for # Need to keep track of the number of components from SIZ for
# other markers # other markers.
self._csiz = len(segment.ssiz) self._csiz = Csiz
return segment return segment
@ -1441,8 +1475,8 @@ class SIZsegment(Segment):
Width and height of reference tile with respect to the reference grid. Width and height of reference tile with respect to the reference grid.
xtosiz, ytosiz : int xtosiz, ytosiz : int
Horizontal and vertical offsets of tile from origin of reference grid. Horizontal and vertical offsets of tile from origin of reference grid.
ssiz : iterable bytes Csiz : int
Encoded precision (depth) in bits and sign of each component. Number of components in image.
bitdepth : iterable bytes bitdepth : iterable bytes
Precision (depth) in bits of each component. Precision (depth) in bits of each component.
signed : iterable bool signed : iterable bool
@ -1457,21 +1491,20 @@ class SIZsegment(Segment):
15444-1:2004 - Information technology -- JPEG 2000 image coding system: 15444-1:2004 - Information technology -- JPEG 2000 image coding system:
Core coding system Core coding system
""" """
def __init__(self, xy_buffer, component_buffer, length, offset): def __init__(self, rsiz=-1, xysiz=None, xyosiz=-1, xytsiz=-1, xytosiz=-1,
Segment.__init__(self, marker_id='SIZ') Csiz=-1, bitdepth=None, signed=None, xyrsiz=-1, length=-1,
offset=-1):
Segment.__init__(self, marker_id='SIZ', length=length, offset=offset)
data = struct.unpack('>HIIIIIIIIH', xy_buffer) self.rsiz = rsiz
self.xsiz, self.ysiz = xysiz
self.rsiz = data[0] self.xosiz, self.yosiz = xyosiz
self.xsiz = data[1] self.xtsiz, self.ytsiz = xytsiz
self.ysiz = data[2] self.xtosiz, self.ytosiz = xytosiz
self.xosiz = data[3] self.Csiz = Csiz
self.yosiz = data[4] self.bitdepth = bitdepth
self.xtsiz = data[5] self.signed = signed
self.ytsiz = data[6] self.xrsiz, self.yrsiz = xyrsiz
self.xtosiz = data[7]
self.ytosiz = data[8]
# disregarding the last element in data
num_tiles_x = (self.xsiz - self.xosiz) / (self.xtsiz - self.xtosiz) num_tiles_x = (self.xsiz - self.xosiz) / (self.xtsiz - self.xtosiz)
num_tiles_y = (self.ysiz - self.yosiz) / (self.ytsiz - self.ytosiz) num_tiles_y = (self.ysiz - self.yosiz) / (self.ytsiz - self.ytosiz)
@ -1480,25 +1513,22 @@ class SIZsegment(Segment):
msg = "Invalid number of tiles ({0}).".format(numtiles) msg = "Invalid number of tiles ({0}).".format(numtiles)
warnings.warn(msg) warnings.warn(msg)
data = struct.unpack('>' + 'B' * len(component_buffer),
component_buffer)
self.ssiz = data[0::3] def __repr__(self):
msg = "glymur.codestream.SIZsegment(rsiz={rsiz}, xysiz={xysiz}, "
for j, subsampling in enumerate(list(zip(data[1::3], data[2::3]))): msg += "xyosiz={xyosiz}, xytsiz={xytsiz}, xytosiz={xytosiz}, "
if 0 in subsampling: msg += "Csiz={Csiz}, bitdepth={bitdepth}, signed={signed}, "
msg = "Invalid subsampling value for component {0}: " msg += "xyrsiz={xyrsiz})"
msg += "dx={1}, dy={2}." msg = msg.format(rsiz=self.rsiz,
msg = msg.format(j, subsampling[0], subsampling[1]) xysiz=(self.xsiz, self.ysiz),
warnings.warn(msg) xyosiz=(self.xosiz, self.yosiz),
self.xrsiz = data[1::3] xytsiz=(self.xtsiz, self.ytsiz),
self.yrsiz = data[2::3] xytosiz=(self.xtosiz, self.ytosiz),
Csiz=self.Csiz,
self.bitdepth = tuple(((x & 0x7f) + 1) for x in self.ssiz) bitdepth=self.bitdepth,
self.signed = tuple(((x & 0xb0) > 0) for x in self.ssiz) signed=self.signed,
xyrsiz=(self.xrsiz, self.yrsiz))
self.length = length return msg
self.offset = offset
def __str__(self): def __str__(self):
msg = Segment.__str__(self) msg = Segment.__str__(self)
@ -1549,6 +1579,9 @@ class SOCsegment(Segment):
Segment.__init__(self, marker_id='SOC') Segment.__init__(self, marker_id='SOC')
self.__dict__.update(**kwargs) self.__dict__.update(**kwargs)
def __repr__(self):
msg = "glymur.codestream.SOCsegment()"
return msg
class SODsegment(Segment): class SODsegment(Segment):
"""Container for Start of Data (SOD) segment information. """Container for Start of Data (SOD) segment information.

View file

@ -75,6 +75,12 @@ class Jp2kBox(object):
self.offset = offset self.offset = offset
self.longname = longname self.longname = longname
def __repr__(self):
msg = "glymur.jp2box.Jp2kBox(box_id='{0}', offset={1}, length={2}, "
msg += "longname='{3}')"
msg = msg.format(self.box_id, self.offset, self.length, self.longname)
return msg
def __str__(self): def __str__(self):
msg = "{0} Box ({1})".format(self.longname, self.box_id) msg = "{0} Box ({1})".format(self.longname, self.box_id)
msg += " @ ({0}, {1})".format(self.offset, self.length) msg += " @ ({0}, {1})".format(self.offset, self.length)
@ -206,6 +212,17 @@ class ColourSpecificationBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.ColourSpecificationBox("
msg += "method={0}, precedence={1}, approximation={2}, colorspace={3}, "
msg += "icc_profile={4})"
msg = msg.format(self.method,
self.precedence,
self.approximation,
self.colorspace,
self.icc_profile)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
@ -426,12 +443,12 @@ class ChannelDefinitionBox(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.
index : int index : list
number of the channel. Defaults to monotonically increasing sequence, number of the channel. Defaults to monotonically increasing sequence,
i.e. [0, 1, 2, ...] i.e. [0, 1, 2, ...]
channel_type : int channel_type : list
type of the channel type of the channel
association : int association : list
index of the associated color index of the associated color
""" """
def __init__(self, index=None, channel_type=None, association=None, def __init__(self, index=None, channel_type=None, association=None,
@ -458,9 +475,9 @@ class ChannelDefinitionBox(Jp2kBox):
msg += " 65535 - unspecified" msg += " 65535 - unspecified"
raise IOError(msg) raise IOError(msg)
self.index = index self.index = tuple(index)
self.channel_type = channel_type self.channel_type = tuple(channel_type)
self.association = association self.association = tuple(association)
self.__dict__.update(**kwargs) self.__dict__.update(**kwargs)
def __str__(self): def __str__(self):
@ -475,6 +492,12 @@ class ChannelDefinitionBox(Jp2kBox):
msg = msg.format(self.index[j], color_type_string, assn) msg = msg.format(self.index[j], color_type_string, assn)
return msg return msg
def __repr__(self):
msg = "glymur.jp2box.ChannelDefinitionBox("
msg += "index={0}, channel_type={1}, association={2})"
msg = msg.format(self.index, self.channel_type, self.association)
return msg
def write(self, fptr): def write(self, fptr):
"""Write a channel definition box to file. """Write a channel definition box to file.
""" """
@ -537,11 +560,15 @@ class CodestreamHeaderBox(Jp2kBox):
box : list box : list
List of boxes contained in this superbox. List of boxes contained in this superbox.
""" """
def __init__(self, length=0, offset=-1): def __init__(self, box=[], length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jpch', longname='Codestream Header') Jp2kBox.__init__(self, box_id='jpch', longname='Codestream Header')
self.length = length self.length = length
self.offset = offset self.offset = offset
self.box = [] self.box = box
def __repr__(self):
msg = "glymur.jp2box.CodestreamHeaderBox(box={0})".format(self.box)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
@ -595,13 +622,18 @@ class CompositingLayerHeaderBox(Jp2kBox):
box : list box : list
List of boxes contained in this superbox. List of boxes contained in this superbox.
""" """
def __init__(self, length=0, offset=-1): def __init__(self, box=[], length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jplh', Jp2kBox.__init__(self, box_id='jplh',
longname='Compositing Layer Header') longname='Compositing Layer Header')
self.length = length self.length = length
self.offset = offset self.offset = offset
self.box = [] self.box = []
def __repr__(self):
msg = "glymur.jp2box.CompositingLayerHeaderBox(box={0})"
msg = msg.format(self.box)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
for box in self.box: for box in self.box:
@ -650,11 +682,11 @@ class ComponentMappingBox(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
Verbose description of the box. Verbose description of the box.
component_index : int component_index : tuple
Index of component in codestream that is mapped to this channel. Index of component in codestream that is mapped to this channel.
mapping_type : int mapping_type : tuple
mapping type, either direct use (0) or palette (1) mapping type, either direct use (0) or palette (1)
palette_index : int palette_index : tuple
Index component from palette Index component from palette
""" """
def __init__(self, component_index, mapping_type, palette_index, def __init__(self, component_index, mapping_type, palette_index,
@ -666,6 +698,14 @@ class ComponentMappingBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.ComponentMappingBox("
msg += "component_index={0}, mapping_type={1}, palette_index={2})"
msg = msg.format(self.component_index,
self.mapping_type,
self.palette_index)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
@ -733,6 +773,10 @@ class ContiguousCodestreamBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.ContiguousCodeStreamBox(main_header={0})"
return msg.format(repr(self.main_header))
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
msg += '\n Main header:' msg += '\n Main header:'
@ -801,6 +845,13 @@ class FileTypeBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.FileTypeBox(brand='{0}', minor_version={1}, "
msg += "compatibility_list={2})"
msg = msg.format(self.brand, self.minor_version,
self.compatibility_list)
return msg
def __str__(self): def __str__(self):
lst = [Jp2kBox.__str__(self), lst = [Jp2kBox.__str__(self),
' Brand: {0}', ' Brand: {0}',
@ -914,8 +965,23 @@ class ImageHeaderBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.ImageHeaderBox("
msg += "{height}, {width}, num_components={num_components}, "
msg += "signed={signed}, bits_per_component={bits_per_component}, "
msg += "compression={compression}, "
msg += "colorspace_unknown={colorspace_unknown}, "
msg += "ip_provided={ip_provided})"
msg = msg.format(height=self.height, width=self.width,
num_components=self.num_components,
signed=self.signed,
bits_per_component=self.bits_per_component,
compression=self.compression,
colorspace_unknown=self.colorspace_unknown,
ip_provided=self.ip_provided)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self)
msg = "{0}" msg = "{0}"
msg += '\n Size: [{1} {2} {3}]' msg += '\n Size: [{1} {2} {3}]'
msg += '\n Bitdepth: {4}' msg += '\n Bitdepth: {4}'
@ -1004,11 +1070,15 @@ class AssociationBox(Jp2kBox):
box : list box : list
List of boxes contained in this superbox. List of boxes contained in this superbox.
""" """
def __init__(self, length=0, offset=-1): def __init__(self, box=[], length=0, offset=-1):
Jp2kBox.__init__(self, box_id='asoc', longname='Association') Jp2kBox.__init__(self, box_id='asoc', longname='Association')
self.length = length self.length = length
self.offset = offset self.offset = offset
self.box = [] self.box = box
def __repr__(self):
msg = "glymur.jp2box.AssociationBox(box={0})".format(self.box)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
@ -1062,11 +1132,15 @@ class JP2HeaderBox(Jp2kBox):
box : list box : list
List of boxes contained in this superbox. List of boxes contained in this superbox.
""" """
def __init__(self, length=0, offset=-1): def __init__(self, box=[], length=0, offset=-1):
Jp2kBox.__init__(self, box_id='jp2h', longname='JP2 Header') Jp2kBox.__init__(self, box_id='jp2h', longname='JP2 Header')
self.length = length self.length = length
self.offset = offset self.offset = offset
self.box = [] self.box = box
def __repr__(self):
msg = "glymur.jp2box.JP2HeaderBox(box={0})".format(self.box)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
@ -1141,6 +1215,9 @@ class JPEG2000SignatureBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
return 'glymur.jp2box.JPEG2000SignatureBox()'
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
msg += '\n Signature: {0:02x}{1:02x}{2:02x}{3:02x}' msg += '\n Signature: {0:02x}{1:02x}{2:02x}{3:02x}'
@ -1205,6 +1282,12 @@ class PaletteBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.PaletteBox({0}, bits_per_component={1}, "
msg += "signed={2})"
msg = msg.format(self.palette, self.bits_per_component, self.signed)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
msg += '\n Size: ({0} x {1})'.format(*self.palette.shape) msg += '\n Size: ({0} x {1})'.format(*self.palette.shape)
@ -1386,6 +1469,18 @@ class ReaderRequirementsBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.ReaderRequirementsBox(fuam={fuam}, dcm={dcm}, "
msg += "standard_flag={standard_flag}, standard_mask={standard_mask}, "
msg += "vendor_feature={vendor_feature}, vendor_mask={vendor_mask})"
msg = msg.format(fuam=self.fuam,
dcm=self.dcm,
standard_flag=self.standard_flag,
standard_mask=self.standard_mask,
vendor_feature=self.vendor_feature,
vendor_mask=self.vendor_mask)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
@ -1523,11 +1618,16 @@ class ResolutionBox(Jp2kBox):
box : list box : list
List of boxes contained in this superbox. List of boxes contained in this superbox.
""" """
def __init__(self, length=0, offset=-1): def __init__(self, box=[], length=0, offset=-1):
Jp2kBox.__init__(self, box_id='res ', longname='Resolution') Jp2kBox.__init__(self, box_id='res ', longname='Resolution')
self.length = length self.length = length
self.offset = offset self.offset = offset
self.box = [] self.box = box
def __repr__(self):
msg = "glymur.jp2box.ResolutionBox(box={0})"
msg = msg.format(self.box)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
@ -1589,6 +1689,11 @@ class CaptureResolutionBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.CaptureResolutionBox({0}, {1})"
msg = msg.format(self.vertical_resolution, self.horizontal_resolution)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
msg += '\n VCR: {0}'.format(self.vertical_resolution) msg += '\n VCR: {0}'.format(self.vertical_resolution)
@ -1646,6 +1751,11 @@ class DisplayResolutionBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.DisplayResolutionBox({0}, {1})"
msg = msg.format(self.vertical_resolution, self.horizontal_resolution)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
msg += '\n VDR: {0}'.format(self.vertical_resolution) msg += '\n VDR: {0}'.format(self.vertical_resolution)
@ -1707,6 +1817,10 @@ class LabelBox(Jp2kBox):
msg += '\n Label: {0}'.format(self.label) msg += '\n Label: {0}'.format(self.label)
return msg return msg
def __repr__(self):
msg = 'glymur.jp2box.LabelBox("{0}")'.format(self.label)
return msg
@staticmethod @staticmethod
def parse(fptr, offset, length): def parse(fptr, offset, length):
"""Parse Label box. """Parse Label box.
@ -1768,6 +1882,9 @@ class XMLBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
return "glymur.jp2box.XMLBox(xml={0})".format(self.xml)
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
xml = self.xml xml = self.xml
@ -1826,7 +1943,6 @@ class XMLBox(Jp2kBox):
msg = msg.format(offset, ude.reason) msg = msg.format(offset, ude.reason)
warnings.warn(msg, UserWarning) warnings.warn(msg, UserWarning)
# Strip out any trailing nulls, as they can foul up XML parsing. # Strip out any trailing nulls, as they can foul up XML parsing.
text = text.rstrip(chr(0)) text = text.rstrip(chr(0))
@ -1866,6 +1982,10 @@ class UUIDListBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.UUIDListBox({0})".format(self.ulst)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
for j, uuid_item in enumerate(self.ulst): for j, uuid_item in enumerate(self.ulst):
@ -1917,11 +2037,15 @@ class UUIDInfoBox(Jp2kBox):
box : list box : list
List of boxes contained in this superbox. List of boxes contained in this superbox.
""" """
def __init__(self, length=0, offset=-1): def __init__(self, box=[], length=0, offset=-1):
Jp2kBox.__init__(self, box_id='uinf', longname='UUIDInfo') Jp2kBox.__init__(self, box_id='uinf', longname='UUIDInfo')
self.length = length self.length = length
self.offset = offset self.offset = offset
self.box = [] self.box = box
def __repr__(self):
msg = "glymur.jp2box.UUIDInfoBox(box={0})".format(self.box)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
@ -1990,6 +2114,11 @@ class DataEntryURLBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.DataEntryURLBox({0}, {1}, '{2}')"
msg = msg.format(self.version, self.flag, self.url)
return msg
def __str__(self): def __str__(self):
msg = Jp2kBox.__str__(self) msg = Jp2kBox.__str__(self)
msg += '\n ' msg += '\n '
@ -2072,6 +2201,7 @@ class UUIDBox(Jp2kBox):
""" """
Jp2kBox.__init__(self, box_id='uuid', longname='UUID') Jp2kBox.__init__(self, box_id='uuid', longname='UUID')
self.uuid = the_uuid self.uuid = the_uuid
self.raw_data = raw_data
if the_uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): if the_uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
# XMP data. Parse as XML. Seems to be a difference between # XMP data. Parse as XML. Seems to be a difference between
@ -2096,6 +2226,12 @@ class UUIDBox(Jp2kBox):
self.length = length self.length = length
self.offset = offset self.offset = offset
def __repr__(self):
msg = "glymur.jp2box.UUIDBox(the_uuid={0}, "
msg += "raw_data=<byte array {1} elements>)"
return msg.format(repr(self.uuid), len(self.raw_data))
def __str__(self): def __str__(self):
msg = '{0}\n' msg = '{0}\n'
msg += ' UUID: {1}{2}\n' msg += ' UUID: {1}{2}\n'

View file

@ -72,6 +72,10 @@ class Jp2k(Jp2kBox):
if mode == 'rb': if mode == 'rb':
self.parse() self.parse()
def __repr__(self):
msg = "glymur.Jp2k('{0}')".format(self.filename)
return msg
def __str__(self): def __str__(self):
metadata = ['File: ' + os.path.basename(self.filename)] metadata = ['File: ' + os.path.basename(self.filename)]
if len(self.box) > 0: if len(self.box) > 0:

View file

@ -45,6 +45,12 @@ def glymurrc_fname():
def load_openjpeg(path): def load_openjpeg(path):
"""Load the openjpeg library, falling back on defaults if necessary. """Load the openjpeg library, falling back on defaults if necessary.
Parameters
----------
path : str
Path to openjpeg 1.5 library as specified by configuration file. Will
be None if no configuration file specified.
""" """
if path is None: if path is None:
# Let ctypes try to find it. # Let ctypes try to find it.
@ -53,6 +59,7 @@ def load_openjpeg(path):
# If we could not find it, then look in some likely locations on mac # If we could not find it, then look in some likely locations on mac
# and win. # and win.
if path is None: if path is None:
# Could not find a library via ctypes
if platform.system() == 'Darwin': if platform.system() == 'Darwin':
# MacPorts # MacPorts
path = '/opt/local/lib/libopenjpeg.dylib' path = '/opt/local/lib/libopenjpeg.dylib'
@ -60,6 +67,10 @@ def load_openjpeg(path):
path = os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5', path = os.path.join('C:\\', 'Program files', 'OpenJPEG 1.5',
'bin', 'openjpeg.dll') 'bin', 'openjpeg.dll')
if path is not None and not os.path.exists(path):
# the mac/win default location does not exist.
return None
return load_library_handle(path) return load_library_handle(path)
@ -67,10 +78,11 @@ def load_openjp2(path):
"""Load the openjp2 library, falling back on defaults if necessary. """Load the openjp2 library, falling back on defaults if necessary.
""" """
if path is None: if path is None:
# No help from the config file, try to find it ourselves. # No help from the config file, try to find it via ctypes.
path = find_library('openjp2') path = find_library('openjp2')
if path is None: if path is None:
# Could not find a library via ctypes
if platform.system() == 'Darwin': if platform.system() == 'Darwin':
# MacPorts # MacPorts
path = '/opt/local/lib/libopenjp2.dylib' path = '/opt/local/lib/libopenjp2.dylib'
@ -78,6 +90,10 @@ def load_openjp2(path):
path = os.path.join('C:\\', 'Program files', 'OpenJPEG 2.0', path = os.path.join('C:\\', 'Program files', 'OpenJPEG 2.0',
'bin', 'openjp2.dll') 'bin', 'openjp2.dll')
if path is not None and not os.path.exists(path):
# the mac/win default location does not exist.
return None
return load_library_handle(path) return load_library_handle(path)
@ -85,6 +101,9 @@ def load_library_handle(path):
"""Load the library, return the ctypes handle.""" """Load the library, return the ctypes handle."""
if path is None: if path is None:
# Either could not find a library via ctypes or user-configuration-file,
# or we could not find it in any of the default locations.
# This is probably a very old linux.
return None return None
try: try:
@ -93,10 +112,10 @@ def load_library_handle(path):
else: else:
opj_lib = ctypes.CDLL(path) opj_lib = ctypes.CDLL(path)
except (TypeError, OSError): except (TypeError, OSError):
msg = '"Library {0}" could not be loaded. Operating in degraded mode.' msg = '"Library {0}" could not be loaded. Operating in degraded mode.'
msg = msg.format(path) msg = msg.format(path)
warnings.warn(msg, UserWarning) warnings.warn(msg, UserWarning)
opj_lib = None opj_lib = None
return opj_lib return opj_lib

View file

@ -116,5 +116,49 @@ class TestCodestream(unittest.TestCase):
# codestream, so the last one is EOC. # codestream, so the last one is EOC.
self.assertEqual(codestream.segment[-1].marker_id, 'EOC') self.assertEqual(codestream.segment[-1].marker_id, 'EOC')
class TestCodestreamRepr(unittest.TestCase):
def setUp(self):
self.jp2file = glymur.data.nemo()
def tearDown(self):
pass
def test_soc(self):
"""Test SOC segment repr"""
segment = glymur.codestream.SOCsegment()
newseg = eval(repr(segment))
self.assertEqual(newseg.marker_id, 'SOC')
def test_siz(self):
"""Test SIZ segment repr"""
kwargs = {'rsiz': 0,
'xysiz': (2592, 1456),
'xyosiz': (0, 0),
'xytsiz': (2592, 1456),
'xytosiz': (0, 0),
'Csiz': 3,
'bitdepth': (8, 8, 8),
'signed': (False, False, False),
'xyrsiz': ((1, 1, 1), (1, 1, 1))}
segment = glymur.codestream.SIZsegment(**kwargs)
newseg = eval(repr(segment))
self.assertEqual(newseg.marker_id, 'SIZ')
self.assertEqual(newseg.xsiz, 2592)
self.assertEqual(newseg.ysiz, 1456)
self.assertEqual(newseg.xosiz, 0)
self.assertEqual(newseg.yosiz, 0)
self.assertEqual(newseg.xtsiz, 2592)
self.assertEqual(newseg.ytsiz, 1456)
self.assertEqual(newseg.xtosiz, 0)
self.assertEqual(newseg.ytosiz, 0)
self.assertEqual(newseg.xrsiz, (1, 1, 1))
self.assertEqual(newseg.yrsiz, (1, 1, 1))
self.assertEqual(newseg.bitdepth, (8, 8, 8))
self.assertEqual(newseg.signed, (False, False, False))
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View file

@ -18,11 +18,13 @@ Test suite specifically targeting JP2 box layout.
import doctest import doctest
import os import os
import re
import shutil import shutil
import struct import struct
import sys import sys
import tempfile import tempfile
import uuid import uuid
from uuid import UUID
import xml.etree.cElementTree as ET import xml.etree.cElementTree as ET
if sys.hexversion < 0x02070000: if sys.hexversion < 0x02070000:
@ -40,7 +42,7 @@ from glymur.jp2box import JPEG2000SignatureBox
from glymur.core import COLOR, OPACITY from glymur.core import COLOR, OPACITY
from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE
from .fixtures import OPENJP2_IS_V2_OFFICIAL from .fixtures import OPENJP2_IS_V2_OFFICIAL, opj_data_file
try: try:
FORMAT_CORPUS_DATA_ROOT = os.environ['FORMAT_CORPUS_DATA_ROOT'] FORMAT_CORPUS_DATA_ROOT = os.environ['FORMAT_CORPUS_DATA_ROOT']
@ -413,7 +415,7 @@ class TestAppend(unittest.TestCase):
jp2 = Jp2k(tfile.name) jp2 = Jp2k(tfile.name)
the_xml = ET.fromstring('<?xml version="1.0"?><data>0</data>') the_xml = ET.fromstring('<?xml version="1.0"?><data>0</data>')
xmlbox = glymur.jp2box.XMLBox(xml=the_xml) xmlbox = glymur.jp2box.XMLBox(xml=ET.ElementTree(the_xml))
jp2.append(xmlbox) jp2.append(xmlbox)
# The sequence of box IDs should be the same as before, but with an # The sequence of box IDs should be the same as before, but with an
@ -709,6 +711,250 @@ class TestJp2Boxes(unittest.TestCase):
self.assertIsNone(box.main_header) self.assertIsNone(box.main_header)
class TestRepr(unittest.TestCase):
"""Tests for __repr__ methods."""
def test_default_jp2k(self):
"""Should be able to eval a JPEG2000SignatureBox"""
jp2k = glymur.jp2box.JPEG2000SignatureBox()
# Test the representation instantiation.
newbox = eval(repr(jp2k))
self.assertTrue(isinstance(newbox, glymur.jp2box.JPEG2000SignatureBox))
self.assertEqual(newbox.signature, (13, 10, 135, 10))
def test_default_ftyp(self):
"""Should be able to instantiate a FileTypeBox"""
ftyp = glymur.jp2box.FileTypeBox()
# Test the representation instantiation.
newbox = eval(repr(ftyp))
self.assertTrue(isinstance(newbox, glymur.jp2box.FileTypeBox))
self.assertEqual(newbox.brand, 'jp2 ')
self.assertEqual(newbox.minor_version, 0)
self.assertEqual(newbox.compatibility_list, ['jp2 '])
def test_colourspecification_box(self):
"""Verify __repr__ method on colr box."""
# TODO: add icc_profile
box = ColourSpecificationBox(colorspace=glymur.core.SRGB)
newbox = eval(repr(box))
self.assertEqual(newbox.method, glymur.core.ENUMERATED_COLORSPACE)
self.assertEqual(newbox.precedence, 0)
self.assertEqual(newbox.approximation, 0)
self.assertEqual(newbox.colorspace, glymur.core.SRGB)
self.assertIsNone(newbox.icc_profile)
def test_channeldefinition_box(self):
"""Verify __repr__ method on cdef box."""
channel_type = [COLOR, COLOR, COLOR]
association = [RED, GREEN, BLUE]
cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2],
channel_type=channel_type,
association=association)
newbox = eval(repr(cdef))
self.assertEqual(newbox.index, (0, 1, 2))
self.assertEqual(newbox.channel_type, (COLOR, COLOR, COLOR))
self.assertEqual(newbox.association, (RED, GREEN, BLUE))
def test_jp2header_box(self):
"""Verify __repr__ method on ihdr box."""
ihdr = ImageHeaderBox(100, 200, num_components=3)
colr = ColourSpecificationBox(colorspace=glymur.core.SRGB)
jp2h = JP2HeaderBox(box=[ihdr, colr])
newbox = eval(repr(jp2h))
self.assertEqual(newbox.box_id, 'jp2h')
self.assertEqual(newbox.box[0].box_id, 'ihdr')
self.assertEqual(newbox.box[1].box_id, 'colr')
def test_imageheader_box(self):
"""Verify __repr__ method on jhdr box."""
ihdr = ImageHeaderBox(100, 200, num_components=3)
newbox = eval(repr(ihdr))
self.assertEqual(newbox.height, 100)
self.assertEqual(newbox.width, 200)
self.assertEqual(newbox.num_components, 3)
self.assertFalse(newbox.signed)
self.assertEqual(newbox.bits_per_component, 8)
self.assertEqual(newbox.compression, 7)
self.assertFalse(newbox.colorspace_unknown)
self.assertFalse(newbox.ip_provided)
def test_association_box(self):
"""Verify __repr__ method on asoc box."""
asoc = glymur.jp2box.AssociationBox()
newbox = eval(repr(asoc))
self.assertEqual(newbox.box_id, 'asoc')
self.assertEqual(len(newbox.box), 0)
def test_codestreamheader_box(self):
"""Verify __repr__ method on jpch box."""
jpch = glymur.jp2box.CodestreamHeaderBox()
newbox = eval(repr(jpch))
self.assertEqual(newbox.box_id, 'jpch')
self.assertEqual(len(newbox.box), 0)
def test_compositinglayerheader_box(self):
"""Verify __repr__ method on jplh box."""
jplh = glymur.jp2box.CompositingLayerHeaderBox()
newbox = eval(repr(jplh))
self.assertEqual(newbox.box_id, 'jplh')
self.assertEqual(len(newbox.box), 0)
def test_componentmapping_box(self):
"""Verify __repr__ method on cmap box."""
cmap = glymur.jp2box.ComponentMappingBox(component_index=(0, 0, 0),
mapping_type=(1, 1, 1),
palette_index=(0, 1, 2))
newbox = eval(repr(cmap))
self.assertEqual(newbox.box_id, 'cmap')
self.assertEqual(newbox.component_index, (0, 0, 0))
self.assertEqual(newbox.mapping_type, (1, 1, 1))
self.assertEqual(newbox.palette_index, (0, 1, 2))
def test_resolution_boxes(self):
"""Verify __repr__ method on resolution boxes."""
resc = glymur.jp2box.CaptureResolutionBox(0.5, 2.5)
resd = glymur.jp2box.DisplayResolutionBox(2.5, 0.5)
res_super_box = glymur.jp2box.ResolutionBox(box=[resc, resd])
newbox = eval(repr(res_super_box))
self.assertEqual(newbox.box_id, 'res ')
self.assertEqual(newbox.box[0].box_id, 'resc')
self.assertEqual(newbox.box[0].vertical_resolution, 0.5)
self.assertEqual(newbox.box[0].horizontal_resolution, 2.5)
self.assertEqual(newbox.box[1].box_id, 'resd')
self.assertEqual(newbox.box[1].vertical_resolution, 2.5)
self.assertEqual(newbox.box[1].horizontal_resolution, 0.5)
def test_label_box(self):
"""Verify __repr__ method on label box."""
lbl = glymur.jp2box.LabelBox("this is a test")
newbox = eval(repr(lbl))
self.assertEqual(newbox.box_id, 'lbl ')
self.assertEqual(newbox.label, "this is a test")
def test_data_entry_url_box(self):
"""Verify __repr__ method on data entry url box."""
version = 0
flag = (0, 0, 0)
url = "http://readthedocs.glymur.org"
box = glymur.jp2box.DataEntryURLBox(version, flag, url)
newbox = eval(repr(box))
self.assertEqual(newbox.box_id, 'url ')
self.assertEqual(newbox.version, version)
self.assertEqual(newbox.flag, flag)
self.assertEqual(newbox.url, url)
def test_uuidinfo_box(self):
"""Verify __repr__ method on uinf box."""
uinf = glymur.jp2box.UUIDInfoBox()
newbox = eval(repr(uinf))
self.assertEqual(newbox.box_id, 'uinf')
self.assertEqual(len(newbox.box), 0)
def test_uuidlist_box(self):
"""Verify __repr__ method on ulst box."""
uuid1 = uuid.UUID('00000000-0000-0000-0000-000000000001')
uuid2 = uuid.UUID('00000000-0000-0000-0000-000000000002')
uuids = [uuid1, uuid2]
ulst = glymur.jp2box.UUIDListBox(ulst=uuids)
newbox = eval(repr(ulst))
self.assertEqual(newbox.box_id, 'ulst')
self.assertEqual(newbox.ulst[0], uuid1)
self.assertEqual(newbox.ulst[1], uuid2)
def test_jp2k_box(self):
"""Verify Superclass repr."""
box = glymur.jp2box.Jp2kBox(box_id='one', offset=2, length=3,
longname='four')
newbox = eval(repr(box))
self.assertEqual(newbox.box_id, 'one')
self.assertEqual(newbox.offset, 2)
self.assertEqual(newbox.length, 3)
self.assertEqual(newbox.longname, 'four')
def test_palette_box(self):
"""Verify Palette box repr."""
palette = np.array([[255, 0, 1000], [0, 255, 0]], dtype=np.int32)
bps = (8, 8, 16)
signed = (True, False, True)
box = glymur.jp2box.PaletteBox(palette=palette, bits_per_component=bps,
signed=(True, False, True))
# The palette can't be reinstantiated thru eval/repr.
s = repr(box)
self.assertTrue(True)
@unittest.skipIf(sys.hexversion < 0x02070000, "Requires 2.7+")
def test_xml_box(self):
"""Verify xml box repr."""
elt = ET.fromstring('<?xml version="1.0"?><data>0</data>')
tree = ET.ElementTree(elt)
box = glymur.jp2box.XMLBox(xml=tree)
regexp = "glymur.jp2box.XMLBox"
regexp += "\(xml=<(xml.etree.ElementTree.){0,1}ElementTree object "
regexp += "at 0x([a-f0-9]*)>\)"
if sys.hexversion < 0x03000000:
self.assertRegexpMatches(repr(box), regexp)
else:
self.assertRegex(repr(box), regexp)
def test_readerrequirements_box(self):
"""Verify rreq repr method."""
box = glymur.jp2box.ReaderRequirementsBox(fuam=160, dcm=192,
standard_flag=(5, 61, 43),
standard_mask=(128, 96, 64),
vendor_feature=[],
vendor_mask=[])
newbox = eval(repr(box))
self.assertEqual(box.fuam, newbox.fuam)
self.assertEqual(box.dcm, newbox.dcm)
self.assertEqual(box.standard_flag, newbox.standard_flag)
self.assertEqual(box.standard_mask, newbox.standard_mask)
self.assertEqual(box.vendor_feature, newbox.vendor_feature)
self.assertEqual(box.vendor_mask, newbox.vendor_mask)
@unittest.skipIf(sys.hexversion < 0x02070000, "Requires 2.7+")
def test_uuid_box(self):
"""Verify uuid repr method."""
uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000')
data = b'0123456789'
box = glymur.jp2box.UUIDBox(the_uuid=uuid_instance, raw_data=data)
# Since the raw_data parameter is a sequence of bytes which could be
# quite long, don't bother trying to make it conform to eval(repr()).
regexp = "glymur.jp2box.UUIDBox\("
regexp += "the_uuid=UUID\('00000000-0000-0000-0000-000000000000'\),\s"
regexp += "raw_data=<byte\sarray\s10\selements>\)"
if sys.hexversion < 0x03000000:
self.assertRegexpMatches(repr(box), regexp)
else:
self.assertRegex(repr(box), regexp)
@unittest.skipIf(sys.hexversion < 0x02070000, "Requires 2.7+")
def test_contiguous_codestream_box(self):
"""Verify contiguous codestream box repr method."""
jp2file = glymur.data.nemo()
jp2 = Jp2k(jp2file)
box = jp2.box[-1]
# Difficult to eval(repr()) this, so just match the general pattern.
regexp = "glymur.jp2box.ContiguousCodeStreamBox"
regexp += "\(main_header=<glymur.codestream.Codestream\sobject\s"
regexp += "at\s0x([a-f0-9]*)>\)"
if sys.hexversion < 0x03000000:
self.assertRegexpMatches(repr(box), regexp)
else:
self.assertRegex(repr(box), regexp)
class TestJpxBoxes(unittest.TestCase): class TestJpxBoxes(unittest.TestCase):
"""Tests for JPX boxes.""" """Tests for JPX boxes."""

View file

@ -67,6 +67,15 @@ class TestJp2k(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def test_repr(self):
"""Verify that results of __repr__ are eval-able."""
j = Jp2k(self.j2kfile)
newjp2 = eval(repr(j))
self.assertEqual(newjp2.filename, self.j2kfile)
self.assertEqual(newjp2.mode, 'rb')
self.assertEqual(len(newjp2.box), 0)
def test_rlevel_max(self): def test_rlevel_max(self):
"""Verify that rlevel=-1 gets us the lowest resolution image""" """Verify that rlevel=-1 gets us the lowest resolution image"""
j = Jp2k(self.j2kfile) j = Jp2k(self.j2kfile)

View file

@ -62,266 +62,6 @@ class TestSuite(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def test_ETS_C0P0_p0_01_j2k(self):
jfile = opj_data_file('input/conformance/p0_01.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p0_01.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
def test_ETS_C0P0_p0_02_j2k(self):
jfile = opj_data_file('input/conformance/p0_02.j2k')
jp2k = Jp2k(jfile)
with warnings.catch_warnings():
# Invalid marker ID.
warnings.simplefilter("ignore")
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p0_02.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
@unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_03_j2k(self):
jfile = opj_data_file('input/conformance/p0_03.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p0_03r0.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
def test_ETS_C0P0_p0_03_j2k_r1(self):
jfile = opj_data_file('input/conformance/p0_03.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=1)
pgxfile = opj_data_file('baseline/conformance/c0p0_03r1.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
@unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_04_j2k(self):
jfile = opj_data_file('input/conformance/p0_04.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=3)
pgxfile = opj_data_file('baseline/conformance/c0p0_04.pgx')
pgxdata = read_pgx(pgxfile)
self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 33)
self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 55.8)
@unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_07_j2k(self):
jfile = opj_data_file('input/conformance/p0_07.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read()
pgxfile = opj_data_file('baseline/conformance/c0p0_07.pgx')
pgxdata = read_pgx(pgxfile)
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 10)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.34)
@unittest.skip("8-bit pgx data vs 12-bit j2k data")
def test_ETS_C0P0_p0_08_j2k(self):
jfile = opj_data_file('input/conformance/p0_08.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=5)
pgxfile = opj_data_file('baseline/conformance/c0p0_08.pgx')
pgxdata = read_pgx(pgxfile)
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 7)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 6.72)
def test_ETS_C0P0_p0_09_j2k(self):
jfile = opj_data_file('input/conformance/p0_09.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=2)
pgxfile = opj_data_file('baseline/conformance/c0p0_09.pgx')
pgxdata = read_pgx(pgxfile)
self.assertTrue(peak_tolerance(jpdata, pgxdata) < 4)
self.assertTrue(mse(jpdata, pgxdata) < 1.47)
@unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_10_j2k(self):
jfile = opj_data_file('input/conformance/p0_10.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p0_10.pgx')
pgxdata = read_pgx(pgxfile)
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 10)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 2.84)
def test_ETS_C0P0_p0_11_j2k(self):
jfile = opj_data_file('input/conformance/p0_11.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p0_11.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
@unittest.skip("fprintf stderr output in r2343.")
def test_ETS_C0P0_p0_12_j2k(self):
jfile = opj_data_file('input/conformance/p0_12.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p0_12.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
@unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_13_j2k(self):
jfile = opj_data_file('input/conformance/p0_13.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p0_13.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata)
@unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_14_j2k(self):
jfile = opj_data_file('input/conformance/p0_14.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=2)
pgxfile = opj_data_file('baseline/conformance/c0p0_14.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata)
@unittest.skip("Known failure in OPENJPEG test suite.")
def test_ETS_C0P0_p0_15_j2k(self):
jfile = opj_data_file('input/conformance/p0_15.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p0_15r0.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
def test_ETS_C0P0_p0_15_j2k_r1(self):
jfile = opj_data_file('input/conformance/p0_15.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=1)
pgxfile = opj_data_file('baseline/conformance/c0p0_15r1.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
def test_ETS_C0P0_p0_16_j2k(self):
jfile = opj_data_file('input/conformance/p0_16.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p0_16.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
def test_ETS_C0P1_p1_01_j2k(self):
jfile = opj_data_file('input/conformance/p1_01.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p1_01.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata, pgxdata)
@unittest.skip("Known failure in OPENJPEG test suite operation.")
def test_ETS_C0P1_p1_02_j2k(self):
jfile = opj_data_file('input/conformance/p1_02.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=3)
pgxfile = opj_data_file('baseline/conformance/c0p1_02.pgx')
pgxdata = read_pgx(pgxfile)
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 35)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 74)
@unittest.skip("Known failure in OPENJPEG test suite operation.")
def test_ETS_C0P1_p1_04_j2k(self):
jfile = opj_data_file('input/conformance/p1_04.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p1_04r0.pgx')
pgxdata = read_pgx(pgxfile)
print(peak_tolerance(jpdata, pgxdata))
self.assertTrue(peak_tolerance(jpdata, pgxdata) < 2)
self.assertTrue(mse(jpdata, pgxdata) < 0.55)
@unittest.skip("Known failure in OPENJPEG test suite, precision issue.")
def test_ETS_C0P1_p1_04_j2k_r3(self):
jfile = opj_data_file('input/conformance/p1_04.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=3)
pgxfile = opj_data_file('baseline/conformance/c0p1_04r3.pgx')
pgxdata = read_pgx(pgxfile)
print(peak_tolerance(jpdata, pgxdata))
self.assertTrue(peak_tolerance(jpdata, pgxdata) < 2)
self.assertTrue(mse(jpdata, pgxdata) < 0.55)
@unittest.skip("Known failure in OPENJPEG test suite operation.")
def test_ETS_C0P1_p1_05_j2k(self):
jfile = opj_data_file('input/conformance/p1_05.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=4)
pgxfile = opj_data_file('baseline/conformance/c0p1_05.pgx')
pgxdata = read_pgx(pgxfile)
print(peak_tolerance(jpdata[:, :, 0], pgxdata))
print(peak_tolerance(jpdata[:, :, 1], pgxdata))
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 128)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 16384)
@unittest.skip("Known failure in OPENJPEG test suite operation.")
def test_ETS_C0P1_p1_06_j2k(self):
jfile = opj_data_file('input/conformance/p1_06.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=1)
pgxfile = opj_data_file('baseline/conformance/c0p1_06.pgx')
pgxdata = read_pgx(pgxfile)
print(peak_tolerance(jpdata[:, :, 0], pgxdata))
print(peak_tolerance(jpdata[:, :, 1], pgxdata))
self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 128)
self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 16384)
@unittest.skip("fprintf stderr output in r2345.")
def test_ETS_C0P1_p1_07_j2k(self):
jfile = opj_data_file('input/conformance/p1_07.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read_bands(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c0p1_07.pgx')
pgxdata = read_pgx(pgxfile)
np.testing.assert_array_equal(jpdata[0], pgxdata)
def test_ETS_C1P0_p0_01_j2k(self): def test_ETS_C1P0_p0_01_j2k(self):
jfile = opj_data_file('input/conformance/p0_01.j2k') jfile = opj_data_file('input/conformance/p0_01.j2k')
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
@ -332,10 +72,13 @@ class TestSuite(unittest.TestCase):
np.testing.assert_array_equal(jpdata, pgxdata) np.testing.assert_array_equal(jpdata, pgxdata)
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_ETS_C1P0_p0_02_j2k(self): def test_ETS_C1P0_p0_02_j2k(self):
jfile = opj_data_file('input/conformance/p0_02.j2k') jfile = opj_data_file('input/conformance/p0_02.j2k')
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)
jpdata = jp2k.read(rlevel=0) with self.assertWarns(UserWarning):
jpdata = jp2k.read(rlevel=0)
pgxfile = opj_data_file('baseline/conformance/c1p0_02_0.pgx') pgxfile = opj_data_file('baseline/conformance/c1p0_02_0.pgx')
pgxdata = read_pgx(pgxfile) pgxdata = read_pgx(pgxfile)
@ -6728,40 +6471,6 @@ class TestSuite_bands(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def test_ETS_C0P0_p0_05_j2k(self):
jfile = opj_data_file('input/conformance/p0_05.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read_bands(rlevel=3)
pgxfile = opj_data_file('baseline/conformance/c0p0_05.pgx')
pgxdata = read_pgx(pgxfile)
self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 54)
self.assertTrue(mse(jpdata[0], pgxdata) < 68)
@unittest.skip("8-bit pgx data vs 12-bit j2k data")
def test_ETS_C0P0_p0_06_j2k(self):
jfile = opj_data_file('input/conformance/p0_06.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read_bands(rlevel=3)
pgxfile = opj_data_file('baseline/conformance/c0p0_06.pgx')
pgxdata = read_pgx(pgxfile)
tol = peak_tolerance(jpdata[0], pgxdata)
self.assertTrue(tol < 109)
m = mse(jpdata[0], pgxdata)
self.assertTrue(m < 743)
def test_ETS_C0P1_p1_03_j2k(self):
jfile = opj_data_file('input/conformance/p1_03.j2k')
jp2k = Jp2k(jfile)
jpdata = jp2k.read_bands(rlevel=3)
pgxfile = opj_data_file('baseline/conformance/c0p1_03.pgx')
pgxdata = read_pgx(pgxfile)
self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 28)
self.assertTrue(mse(jpdata[0], pgxdata) < 18.8)
def test_ETS_C1P1_p1_03_j2k(self): def test_ETS_C1P1_p1_03_j2k(self):
jfile = opj_data_file('input/conformance/p1_03.j2k') jfile = opj_data_file('input/conformance/p1_03.j2k')
jp2k = Jp2k(jfile) jp2k = Jp2k(jfile)

View file

@ -15,7 +15,7 @@ from .lib import openjp2 as opj2
# Do not change the format of this next line! Doing so risks breaking # Do not change the format of this next line! Doing so risks breaking
# setup.py # setup.py
version = "0.5.7" version = "0.5.9"
_sv = LooseVersion(version) _sv = LooseVersion(version)
version_tuple = _sv.version version_tuple = _sv.version