Merge branch 'devel' into issue40
This commit is contained in:
commit
596d502f15
11 changed files with 305 additions and 47 deletions
|
|
@ -1,4 +1,5 @@
|
|||
Jun 11, 2013 - Added reduce=-1 option to get lowest resolution thumbnail
|
||||
Jun 11, 2013 - v0.1.8 Added reduce=-1 option to get lowest resolution
|
||||
thumbnail.
|
||||
|
||||
Jun 07, 2013 - v0.1.7 Changed Exif dictionary names from ['Exif', 'Photo',
|
||||
'Iop', 'GPSInfo'] to ['Image', 'Photo', 'Iop', 'GPSInfo'].
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
include *.txt *.md
|
||||
recursive-include *.txt *.py
|
||||
prune build
|
||||
exclude readthedocs-pip-requirements.txt
|
||||
|
|
|
|||
|
|
@ -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.1.7'
|
||||
release = '0.1.8'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Read the lowest resolution thumbnail?
|
|||
=====================================
|
||||
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 reduce
|
||||
level.
|
||||
level. ::
|
||||
|
||||
>>> import pkg_resources
|
||||
>>> import glymur
|
||||
|
|
@ -38,7 +38,7 @@ codestream box, only the main header is printed. It is possible to print
|
|||
|
||||
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. ::
|
||||
|
||||
>>> import pkg_resources
|
||||
>>> from glymur import Jp2k
|
||||
|
|
|
|||
169
glymur/jp2box.py
169
glymur/jp2box.py
|
|
@ -12,6 +12,7 @@ References
|
|||
"""
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
import math
|
||||
import os
|
||||
import pprint
|
||||
|
|
@ -153,9 +154,9 @@ class ColourSpecificationBox(Jp2kBox):
|
|||
colorspace : int or None
|
||||
Enumerated colorspace, corresponds to one of 'sRGB', 'greyscale', or
|
||||
'YCC'. If not None, then icc_profile must be None.
|
||||
icc_profile : byte array or None
|
||||
ICC profile according to ICC profile specification. If not None, then
|
||||
color_space must be None.
|
||||
icc_profile : _ICCProfile or None
|
||||
ICC profile header according to ICC profile specification. If not
|
||||
None, then color_space must be None.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
Jp2kBox.__init__(self, id='', longname='Colour Specification')
|
||||
|
|
@ -174,8 +175,7 @@ class ColourSpecificationBox(Jp2kBox):
|
|||
x = _colorspace_map_display[self.colorspace]
|
||||
msg += '\n Colorspace: {0}'.format(x)
|
||||
else:
|
||||
x = len(self.icc_profile)
|
||||
msg += '\n ICC Profile: {0} bytes'.format(x)
|
||||
msg += '\n ICC Profile: {0}'.format(self.icc_profile.__str__())
|
||||
|
||||
return msg
|
||||
|
||||
|
|
@ -221,12 +221,169 @@ class ColourSpecificationBox(Jp2kBox):
|
|||
# ICC profile
|
||||
kwargs['colorspace'] = None
|
||||
n = offset + length - f.tell()
|
||||
kwargs['icc_profile'] = f.read(n)
|
||||
if n < 128:
|
||||
msg = "ICC profile header is corrupt, length is "
|
||||
msg += "only {0} instead of 128."
|
||||
warnings.warn(msg.format(n), UserWarning)
|
||||
kwargs['icc_profile'] = None
|
||||
else:
|
||||
icc_profile = _ICCProfile(f.read(n))
|
||||
kwargs['icc_profile'] = icc_profile
|
||||
|
||||
box = ColourSpecificationBox(**kwargs)
|
||||
return box
|
||||
|
||||
|
||||
class _ICCProfile:
|
||||
"""
|
||||
"""
|
||||
profile_class = {b'scnr': 'input device profile',
|
||||
b'mntr': 'display device profile',
|
||||
b'prtr': 'output device profile',
|
||||
b'link': 'devicelink profile',
|
||||
b'spac': 'colorspace conversion profile',
|
||||
b'abst': 'abstract profile',
|
||||
b'nmcl': 'name colour profile'}
|
||||
|
||||
colour_space_dict = {b'XYZ ': 'XYZ',
|
||||
b'Lab ': 'Lab',
|
||||
b'Luv ': 'Luv',
|
||||
b'YCbr': 'YCbCr',
|
||||
b'Yxy ': 'Yxy',
|
||||
b'RGB ': 'RGB',
|
||||
b'GRAY': 'gray',
|
||||
b'HSV ': 'hsv',
|
||||
b'HLS ': 'hls',
|
||||
b'CMYK': 'CMYK',
|
||||
b'CMY ': 'cmy',
|
||||
b'2CLR': '2colour',
|
||||
b'3CLR': '3colour',
|
||||
b'4CLR': '4colour',
|
||||
b'5CLR': '5colour',
|
||||
b'6CLR': '6colour',
|
||||
b'7CLR': '7colour',
|
||||
b'8CLR': '8colour',
|
||||
b'9CLR': '9colour',
|
||||
b'ACLR': '10colour',
|
||||
b'BCLR': '11colour',
|
||||
b'CCLR': '12colour',
|
||||
b'DCLR': '13colour',
|
||||
b'ECLR': '14colour',
|
||||
b'FCLR': '15colour'}
|
||||
|
||||
rendering_intent_dict = {0: 'perceptual',
|
||||
1: 'media-relative colorimetric',
|
||||
2: 'saturation',
|
||||
3: 'ICC-absolute colorimetric'}
|
||||
|
||||
def __init__(self, buffer):
|
||||
self._raw_buffer = buffer
|
||||
|
||||
self.size, = struct.unpack('>I', self._raw_buffer[0:4])
|
||||
self.preferred_cmm_type, = struct.unpack('>I', self._raw_buffer[4:8])
|
||||
|
||||
data = struct.unpack('>BB', self._raw_buffer[8:10])
|
||||
major = data[0]
|
||||
minor = (data[1] & 0xf0) >> 4
|
||||
bugfix = (data[1] & 0x0f)
|
||||
self.version = '{0}.{1}.{2}'.format(major, minor, bugfix)
|
||||
|
||||
self.device_class = self.profile_class[self._raw_buffer[12:16]]
|
||||
self.colour_space = self.colour_space_dict[self._raw_buffer[16:20]]
|
||||
self.connection_space = self.colour_space_dict[self._raw_buffer[20:24]]
|
||||
|
||||
data = struct.unpack('>HHHHHH', self._raw_buffer[24:36])
|
||||
self.datetime = datetime.datetime(*data)
|
||||
self.file_signature = buffer[36:40].decode('utf-8')
|
||||
if buffer[40:44] == b'\x00\x00\x00\x00':
|
||||
self.platform = 'unrecognized'
|
||||
else:
|
||||
self.platform = buffer[40:44].decode('utf-8')
|
||||
|
||||
self.flags, = struct.unpack('>I', buffer[44:48])
|
||||
|
||||
self.device_manufacturer = buffer[48:52].decode('utf-8')
|
||||
if buffer[52:56] == b'\x00\x00\x00\x00':
|
||||
self.device_model = ''
|
||||
else:
|
||||
self.device_model = buffer[52:56].decode('utf-8')
|
||||
self.device_attributes, = struct.unpack('>Q', buffer[56:64])
|
||||
self.rendering_intent, = struct.unpack('>I', buffer[64:68])
|
||||
|
||||
data = struct.unpack('>iii', buffer[68:80])
|
||||
self.illuminant = np.array(data, dtype=np.float64) / 65536
|
||||
|
||||
if buffer[80:84] == b'\x00\x00\x00\x00':
|
||||
self.creator = 'unrecognized'
|
||||
else:
|
||||
self.creator = buffer[80:84].decode('utf-8')
|
||||
|
||||
self.profile_id = buffer[84:100]
|
||||
self.reserved = buffer[100:127]
|
||||
|
||||
def __str__(self):
|
||||
msg = "\n Size: {0}"
|
||||
msg += "\n Preferred CMM type: {1:x}"
|
||||
msg += "\n Version: {2}"
|
||||
msg += "\n Device class signature: {3}"
|
||||
msg += "\n Color space: {4}"
|
||||
msg += "\n Connection space: {5}"
|
||||
msg += "\n Creation time: {6}"
|
||||
msg += "\n File signature: {7}"
|
||||
msg += "\n Platform: {8}"
|
||||
msg += "\n Flags: {9}"
|
||||
msg += "\n Device manufacturer: {10}"
|
||||
msg += "\n Device model: {11}"
|
||||
msg += "\n Device attributes: {12}"
|
||||
msg += "\n Rendering intent: {13}"
|
||||
msg += "\n Illuminant: {14}"
|
||||
msg += "\n Creator signature: {15}"
|
||||
|
||||
if self.flags & 0x01:
|
||||
flag_string = 'embedded, '
|
||||
else:
|
||||
flag_string = 'not embedded, '
|
||||
if self.flags & 0x02:
|
||||
flag_string += 'cannot be used independently'
|
||||
else:
|
||||
flag_string += 'can be used independently'
|
||||
|
||||
if self.device_attributes & 0x01:
|
||||
attr_string = 'transparency, '
|
||||
else:
|
||||
attr_string = 'reflective, '
|
||||
if self.device_attributes & 0x02:
|
||||
attr_string += 'matte, '
|
||||
else:
|
||||
attr_string += 'glossy, '
|
||||
if self.device_attributes & 0x04:
|
||||
attr_string += 'negative media polarity, '
|
||||
else:
|
||||
attr_string += 'positive media polarity, '
|
||||
if self.device_attributes & 0x08:
|
||||
attr_string += 'black and white media'
|
||||
else:
|
||||
attr_string += 'color media'
|
||||
|
||||
msg = msg.format(self.size,
|
||||
self.preferred_cmm_type,
|
||||
self.version,
|
||||
self.device_class,
|
||||
self.colour_space,
|
||||
self.connection_space,
|
||||
self.datetime,
|
||||
self.file_signature,
|
||||
self.platform,
|
||||
flag_string,
|
||||
self.device_manufacturer,
|
||||
self.device_model,
|
||||
attr_string,
|
||||
self.rendering_intent_dict[self.rendering_intent],
|
||||
self.illuminant,
|
||||
self.creator)
|
||||
return(msg)
|
||||
|
||||
|
||||
class ComponentDefinitionBox(Jp2kBox):
|
||||
"""Container for component definition box information.
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ class Jp2k(Jp2kBox):
|
|||
f.seek(0)
|
||||
self.box = self._parse_superbox(f)
|
||||
|
||||
def write(self, data, cratios=None, eph=False, psnr=None, numres=None,
|
||||
def write(self, img_array, cratios=None, eph=False, psnr=None, numres=None,
|
||||
cbsize=None, psizes=None, grid_offset=None, sop=False,
|
||||
subsam=None, tilesize=None, prog=None, modesw=None,
|
||||
colorspace=None, verbose=False):
|
||||
|
|
@ -150,7 +150,7 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
data : array
|
||||
img_array : ndarray
|
||||
Image data to be written to file.
|
||||
callbacks : bool, optional
|
||||
If true, enable default info handler such that INFO messages
|
||||
|
|
@ -307,19 +307,19 @@ class Jp2k(Jp2kBox):
|
|||
msg = "Cannot specify cratios and psnr together."
|
||||
raise RuntimeError(msg)
|
||||
|
||||
if data.ndim == 2:
|
||||
numrows, numcols = data.shape
|
||||
data = data.reshape(numrows, numcols, 1)
|
||||
elif data.ndim == 3:
|
||||
if img_array.ndim == 2:
|
||||
numrows, numcols = img_array.shape
|
||||
img_array = img_array.reshape(numrows, numcols, 1)
|
||||
elif img_array.ndim == 3:
|
||||
pass
|
||||
else:
|
||||
msg = "{0}D imagery is not allowed.".format(data.ndim)
|
||||
msg = "{0}D imagery is not allowed.".format(img_array.ndim)
|
||||
raise IOError(msg)
|
||||
|
||||
numrows, numcols, num_comps = data.shape
|
||||
numrows, numcols, num_comps = img_array.shape
|
||||
|
||||
if colorspace is None:
|
||||
if data.shape[2] == 1 or data.shape[2] == 2:
|
||||
if img_array.shape[2] == 1 or img_array.shape[2] == 2:
|
||||
colorspace = opj2._CLRSPC_GRAY
|
||||
else:
|
||||
# No YCC unless specifically told to do so.
|
||||
|
|
@ -331,15 +331,15 @@ class Jp2k(Jp2kBox):
|
|||
if colorspace not in ('rgb', 'grey', 'gray'):
|
||||
msg = 'Invalid colorspace "{0}"'.format(colorspace)
|
||||
raise IOError(msg)
|
||||
elif colorspace == 'rgb' and data.shape[2] < 3:
|
||||
elif colorspace == 'rgb' and img_array.shape[2] < 3:
|
||||
msg = 'RGB colorspace requires at least 3 components.'
|
||||
raise IOError(msg)
|
||||
else:
|
||||
colorspace = _cspace_map[colorspace]
|
||||
|
||||
if data.dtype == np.uint8:
|
||||
if img_array.dtype == np.uint8:
|
||||
comp_prec = 8
|
||||
elif data.dtype == np.uint16:
|
||||
elif img_array.dtype == np.uint16:
|
||||
comp_prec = 16
|
||||
else:
|
||||
raise RuntimeError("unhandled datatype")
|
||||
|
|
@ -368,7 +368,7 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
# Stage the image data to the openjpeg data structure.
|
||||
for k in range(0, num_comps):
|
||||
layer = np.ascontiguousarray(data[:, :, k], dtype=np.int32)
|
||||
layer = np.ascontiguousarray(img_array[:, :, k], dtype=np.int32)
|
||||
dest = image.contents.comps[k].data
|
||||
src = layer.ctypes.data
|
||||
ctypes.memmove(dest, src, layer.nbytes)
|
||||
|
|
@ -419,7 +419,7 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
Returns
|
||||
-------
|
||||
result : array
|
||||
img_array : ndarray
|
||||
The image data.
|
||||
|
||||
Raises
|
||||
|
|
@ -451,18 +451,18 @@ class Jp2k(Jp2kBox):
|
|||
msg = "Components must all have the same subsampling factors."
|
||||
raise IOError(msg)
|
||||
|
||||
data = self._read_common(reduce=reduce,
|
||||
layer=layer,
|
||||
area=area,
|
||||
tile=tile,
|
||||
verbose=verbose,
|
||||
as_bands=False)
|
||||
img_array = self._read_common(reduce=reduce,
|
||||
layer=layer,
|
||||
area=area,
|
||||
tile=tile,
|
||||
verbose=verbose,
|
||||
as_bands=False)
|
||||
|
||||
if data.shape[2] == 1:
|
||||
data = data.view()
|
||||
data.shape = data.shape[0:2]
|
||||
if img_array.shape[2] == 1:
|
||||
img_array = img_array.view()
|
||||
img_array.shape = img_array.shape[0:2]
|
||||
|
||||
return data
|
||||
return img_array
|
||||
|
||||
def _read_common(self, reduce=0, layer=0, area=None, tile=None,
|
||||
verbose=False, as_bands=False):
|
||||
|
|
@ -486,7 +486,7 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
Returns
|
||||
-------
|
||||
data : list or array
|
||||
img_array : ndarray
|
||||
The individual image components or a single array.
|
||||
"""
|
||||
dparam = opj2._set_default_decoder_parameters()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from .test_callbacks import TestCallbacks as callbacks
|
||||
from .test_codestream import TestCodestream as codestream
|
||||
from .test_jp2k import TestJp2k as jp2k
|
||||
from .test_icc import TestICC as icc
|
||||
from .test_printing import TestPrinting as printing
|
||||
from .test_opj_suite import TestSuite as suite
|
||||
from .test_opj_suite_write import TestSuiteWrite as suitew
|
||||
|
|
|
|||
74
glymur/test/test_icc.py
Normal file
74
glymur/test/test_icc.py
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import datetime
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import warnings
|
||||
from xml.etree import cElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
import pkg_resources
|
||||
|
||||
from glymur import Jp2k
|
||||
import glymur
|
||||
|
||||
try:
|
||||
data_root = os.environ['OPJ_DATA_ROOT']
|
||||
except KeyError:
|
||||
data_root = None
|
||||
except:
|
||||
raise
|
||||
|
||||
|
||||
@unittest.skipIf(data_root is None,
|
||||
"OPJ_DATA_ROOT environment variable not set")
|
||||
class TestICC(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_file5(self):
|
||||
filename = os.path.join(data_root, 'input/conformance/file5.jp2')
|
||||
j = Jp2k(filename)
|
||||
profile = j.box[3].box[1].icc_profile
|
||||
self.assertEqual(profile.size, 546)
|
||||
self.assertEqual(profile.preferred_cmm_type, 0)
|
||||
self.assertEqual(profile.version, '2.2.0')
|
||||
self.assertEqual(profile.device_class, 'input device profile')
|
||||
self.assertEqual(profile.colour_space, 'RGB')
|
||||
self.assertEqual(profile.datetime,
|
||||
datetime.datetime(2001, 8, 30, 13, 32, 37))
|
||||
self.assertEqual(profile.file_signature, 'acsp')
|
||||
self.assertEqual(profile.platform, 'unrecognized')
|
||||
self.assertTrue(profile.flags & 0x01) # embedded
|
||||
self.assertFalse(profile.flags & 0x02) # use anywhere
|
||||
|
||||
self.assertEqual(profile.device_manufacturer, 'KODA')
|
||||
self.assertEqual(profile.device_model, 'ROMM')
|
||||
|
||||
self.assertFalse(profile.device_attributes & 0x01) # reflective
|
||||
self.assertFalse(profile.device_attributes & 0x02) # glossy
|
||||
self.assertFalse(profile.device_attributes & 0x04) # positive
|
||||
self.assertFalse(profile.device_attributes & 0x08) # colour
|
||||
self.assertEqual(profile.rendering_intent & 0x00ff, 0) # perceptual
|
||||
|
||||
np.testing.assert_almost_equal(profile.illuminant,
|
||||
(0.964203, 1.000000, 0.824905),
|
||||
decimal=6)
|
||||
|
||||
self.assertEqual(profile.creator, 'JPEG')
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
"Uses features introduced in 3.2.")
|
||||
def test_invalid_profile_header(self):
|
||||
jfile = os.path.join(data_root,
|
||||
'input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||
with self.assertWarns(UserWarning) as cw:
|
||||
data = Jp2k(jfile).read()
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -3579,7 +3579,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].method, 2) # enumerated
|
||||
self.assertEqual(jp2.box[3].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(len(jp2.box[3].box[1].icc_profile), 546)
|
||||
self.assertEqual(jp2.box[3].box[1].icc_profile.size, 546)
|
||||
self.assertIsNone(jp2.box[3].box[1].colorspace)
|
||||
|
||||
# Jp2 Header
|
||||
|
|
@ -3674,7 +3674,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].method, 2)
|
||||
self.assertEqual(jp2.box[3].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(len(jp2.box[3].box[1].icc_profile), 13332)
|
||||
self.assertEqual(jp2.box[3].box[1].icc_profile.size, 13332)
|
||||
self.assertIsNone(jp2.box[3].box[1].colorspace)
|
||||
|
||||
# Jp2 Header
|
||||
|
|
@ -3723,7 +3723,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 2) # enumerated
|
||||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(len(jp2.box[2].box[1].icc_profile), 414)
|
||||
self.assertEqual(jp2.box[2].box[1].icc_profile.size, 414)
|
||||
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
||||
|
||||
# XML box
|
||||
|
|
@ -6394,7 +6394,10 @@ class TestSuite(unittest.TestCase):
|
|||
def test_NR_orb_blue10_lin_jp2_dump(self):
|
||||
jfile = os.path.join(data_root,
|
||||
'input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||
jp2 = Jp2k(jfile)
|
||||
with warnings.catch_warnings():
|
||||
# This file has an invalid ICC profile
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(jfile)
|
||||
|
||||
ids = [box.id for box in jp2.box]
|
||||
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
||||
|
|
@ -6426,7 +6429,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 2) # res icc
|
||||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 0) # JP2
|
||||
self.assertEqual(len(jp2.box[2].box[1].icc_profile), 1)
|
||||
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
||||
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
|
@ -6490,7 +6493,10 @@ class TestSuite(unittest.TestCase):
|
|||
def test_NR_orb_blue10_win_jp2_dump(self):
|
||||
jfile = os.path.join(data_root,
|
||||
'input/nonregression/orb-blue10-win-jp2.jp2')
|
||||
jp2 = Jp2k(jfile)
|
||||
with warnings.catch_warnings():
|
||||
# This file has an invalid ICC profile
|
||||
warnings.simplefilter("ignore")
|
||||
jp2 = Jp2k(jfile)
|
||||
|
||||
ids = [box.id for box in jp2.box]
|
||||
self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
|
||||
|
|
@ -6522,7 +6528,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[2].box[1].method, 2) # restricted icc
|
||||
self.assertEqual(jp2.box[2].box[1].precedence, 0)
|
||||
self.assertEqual(jp2.box[2].box[1].approximation, 0) # JP2
|
||||
self.assertEqual(len(jp2.box[2].box[1].icc_profile), 1)
|
||||
self.assertIsNone(jp2.box[2].box[1].icc_profile)
|
||||
self.assertIsNone(jp2.box[2].box[1].colorspace)
|
||||
|
||||
c = jp2.box[3].main_header
|
||||
|
|
@ -6624,7 +6630,7 @@ class TestSuite(unittest.TestCase):
|
|||
self.assertEqual(jp2.box[3].box[1].method, 3) # any icc
|
||||
self.assertEqual(jp2.box[3].box[1].precedence, 2)
|
||||
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact
|
||||
self.assertEqual(len(jp2.box[3].box[1].icc_profile), 1328)
|
||||
self.assertEqual(jp2.box[3].box[1].icc_profile.size, 1328)
|
||||
self.assertIsNone(jp2.box[3].box[1].colorspace)
|
||||
|
||||
# UUID boxes. All mentioned in the RREQ box.
|
||||
|
|
@ -6859,7 +6865,10 @@ class TestSuite(unittest.TestCase):
|
|||
def test_NR_DEC_orb_blue_lin_jp2_25_decode(self):
|
||||
jfile = os.path.join(data_root,
|
||||
'input/nonregression/orb-blue10-lin-jp2.jp2')
|
||||
data = Jp2k(jfile).read()
|
||||
with warnings.catch_warnings():
|
||||
# This file has an invalid ICC profile
|
||||
warnings.simplefilter("ignore")
|
||||
data = Jp2k(jfile).read()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_NR_DEC_orb_blue_win_jp2_26_decode(self):
|
||||
|
|
|
|||
|
|
@ -790,7 +790,24 @@ class TestPrinting(unittest.TestCase):
|
|||
' Precedence: 2',
|
||||
' Approximation: accurately represents '
|
||||
+ 'correct colorspace definition',
|
||||
' ICC Profile: 1328 bytes']
|
||||
' ICC Profile: ',
|
||||
' Size: 1328',
|
||||
' Preferred CMM type: 6170706c',
|
||||
' Version: 2.2.0',
|
||||
' Device class signature: display device profile',
|
||||
' Color space: RGB',
|
||||
' Connection space: XYZ',
|
||||
' Creation time: 2009-02-25 11:26:11',
|
||||
' File signature: acsp',
|
||||
' Platform: APPL',
|
||||
' Flags: not embedded, can be used independently',
|
||||
' Device manufacturer: appl',
|
||||
' Device model: ',
|
||||
' Device attributes: '
|
||||
+ 'reflective, glossy, positive media polarity, color media',
|
||||
' Rendering intent: perceptual',
|
||||
' Illuminant: [ 0.96420288 1. 0.8249054 ]',
|
||||
' Creator signature: appl']
|
||||
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -1,7 +1,7 @@
|
|||
from distutils.core import setup
|
||||
|
||||
kwargs = {'name': 'Glymur',
|
||||
'version': '0.1.7',
|
||||
'version': '0.1.8',
|
||||
'description': 'Tools for accessing JPEG2000 files',
|
||||
'long_description': open('README.md').read(),
|
||||
'author': 'John Evans',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue