starting on incompatible changes to writing
This commit is contained in:
parent
3c73415090
commit
6e1637e470
3 changed files with 128 additions and 90 deletions
112
glymur/jp2k.py
112
glymur/jp2k.py
|
|
@ -37,16 +37,6 @@ from .jp2box import (
|
||||||
)
|
)
|
||||||
from .lib import openjpeg as opj, openjp2 as opj2, c as libc
|
from .lib import openjpeg as opj, openjp2 as opj2, c as libc
|
||||||
|
|
||||||
JP2_IDS = ['colr', 'cdef', 'cmap', 'jp2c', 'ftyp', 'ihdr', 'jp2h', 'jP ',
|
|
||||||
'pclr', 'res ', 'resc', 'resd', 'xml ', 'ulst', 'uinf', 'url ',
|
|
||||||
'uuid']
|
|
||||||
JPX_IDS = ['asoc', 'nlst']
|
|
||||||
|
|
||||||
_COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB,
|
|
||||||
'gray': opj2.CLRSPC_GRAY,
|
|
||||||
'grey': opj2.CLRSPC_GRAY,
|
|
||||||
'ycc': opj2.CLRSPC_YCC}
|
|
||||||
|
|
||||||
class Jp2k(Jp2kBox):
|
class Jp2k(Jp2kBox):
|
||||||
"""JPEG 2000 file.
|
"""JPEG 2000 file.
|
||||||
|
|
||||||
|
|
@ -54,8 +44,6 @@ class Jp2k(Jp2kBox):
|
||||||
----------
|
----------
|
||||||
filename : str
|
filename : str
|
||||||
The path to the JPEG 2000 file.
|
The path to the JPEG 2000 file.
|
||||||
mode : str
|
|
||||||
The mode used to open the file.
|
|
||||||
box : sequence
|
box : sequence
|
||||||
List of top-level boxes in the file. Each box may in turn contain
|
List of top-level boxes in the file. Each box may in turn contain
|
||||||
its own list of boxes. Will be empty if the file consists only of a
|
its own list of boxes. Will be empty if the file consists only of a
|
||||||
|
|
@ -92,18 +80,16 @@ class Jp2k(Jp2kBox):
|
||||||
(728, 1296, 3)
|
(728, 1296, 3)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, filename, mode='rb'):
|
def __init__(self, filename, data=None, shape=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
filename : str or file
|
filename : str or file
|
||||||
The path to JPEG 2000 file.
|
The path to JPEG 2000 file.
|
||||||
mode : str, optional
|
|
||||||
The mode used to open the file.
|
|
||||||
"""
|
"""
|
||||||
Jp2kBox.__init__(self)
|
Jp2kBox.__init__(self)
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.mode = mode
|
|
||||||
self.box = []
|
self.box = []
|
||||||
self._codec_format = None
|
self._codec_format = None
|
||||||
self._colorspace = None
|
self._colorspace = None
|
||||||
|
|
@ -114,8 +100,10 @@ class Jp2k(Jp2kBox):
|
||||||
self._verbose = False
|
self._verbose = False
|
||||||
|
|
||||||
# Parse the file for JP2/JPX contents only if we are reading it.
|
# Parse the file for JP2/JPX contents only if we are reading it.
|
||||||
if mode == 'rb':
|
if data is None and shape is None:
|
||||||
self.parse()
|
self.parse()
|
||||||
|
else:
|
||||||
|
self._write(data, **kwargs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ignore_pclr_cmap_cdef(self):
|
def ignore_pclr_cmap_cdef(self):
|
||||||
|
|
@ -433,6 +421,77 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
self._cparams = cparams
|
self._cparams = cparams
|
||||||
|
|
||||||
|
def _write(self, img_array, verbose=False, **kwargs):
|
||||||
|
"""Write image data to a JP2/JPX/J2k file. Intended usage of the
|
||||||
|
various parameters follows that of OpenJPEG's opj_compress utility.
|
||||||
|
|
||||||
|
This method can only be used to create JPEG 2000 images that can fit
|
||||||
|
in memory.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
img_array : ndarray
|
||||||
|
Image data to be written to file.
|
||||||
|
cbsize : tuple, optional
|
||||||
|
Code block size (DY, DX).
|
||||||
|
cinema2k : int, optional
|
||||||
|
frames per second, either 24 or 48
|
||||||
|
cinema4k : bool, optional
|
||||||
|
Set to True to specify Cinema4K mode, defaults to false.
|
||||||
|
colorspace : str, optional
|
||||||
|
Either 'rgb' or 'gray'.
|
||||||
|
cratios : iterable
|
||||||
|
Compression ratios for successive layers.
|
||||||
|
eph : bool, optional
|
||||||
|
If true, write SOP marker after each header packet.
|
||||||
|
grid_offset : tuple, optional
|
||||||
|
Offset (DY, DX) of the origin of the image in the reference grid.
|
||||||
|
irreversible : bool, optional
|
||||||
|
If true, use the irreversible DWT 9-7 transform.
|
||||||
|
mct : bool, optional
|
||||||
|
Specifies usage of the multi component transform. If not
|
||||||
|
specified, defaults to True if the colorspace is RGB.
|
||||||
|
modesw : int, optional
|
||||||
|
Mode switch.
|
||||||
|
1 = BYPASS(LAZY)
|
||||||
|
2 = RESET
|
||||||
|
4 = RESTART(TERMALL)
|
||||||
|
8 = VSC
|
||||||
|
16 = ERTERM(SEGTERM)
|
||||||
|
32 = SEGMARK(SEGSYM)
|
||||||
|
numres : int, optional
|
||||||
|
Number of resolutions.
|
||||||
|
prog : str, optional
|
||||||
|
Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL".
|
||||||
|
psnr : iterable, optional
|
||||||
|
Different PSNR for successive layers.
|
||||||
|
psizes : list, optional
|
||||||
|
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
|
||||||
|
Subsampling factors (dy, dx).
|
||||||
|
tilesize : tuple, optional
|
||||||
|
Numeric tuple specifying tile size in terms of (numrows, numcols),
|
||||||
|
not (X, Y).
|
||||||
|
verbose : bool, optional
|
||||||
|
Print informational messages produced by the OpenJPEG library.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if re.match("1.[0-4]", version.openjpeg_version) is not None:
|
||||||
|
raise RuntimeError("You must have at least version 1.5 of OpenJPEG "
|
||||||
|
"in order to write images.")
|
||||||
|
|
||||||
|
self._shape = img_array.shape
|
||||||
|
self._determine_colorspace(**kwargs)
|
||||||
|
self._populate_cparams(img_array, **kwargs)
|
||||||
|
|
||||||
|
if opj2.OPENJP2 is not None:
|
||||||
|
self._write_openjp2(img_array, verbose=verbose)
|
||||||
|
else:
|
||||||
|
self._write_openjpeg(img_array, verbose=verbose)
|
||||||
|
|
||||||
def write(self, img_array, verbose=False, **kwargs):
|
def write(self, img_array, verbose=False, **kwargs):
|
||||||
"""Write image data to a JP2/JPX/J2k file. Intended usage of the
|
"""Write image data to a JP2/JPX/J2k file. Intended usage of the
|
||||||
various parameters follows that of OpenJPEG's opj_compress utility.
|
various parameters follows that of OpenJPEG's opj_compress utility.
|
||||||
|
|
@ -490,16 +549,6 @@ class Jp2k(Jp2kBox):
|
||||||
verbose : bool, optional
|
verbose : bool, optional
|
||||||
Print informational messages produced by the OpenJPEG library.
|
Print informational messages produced by the OpenJPEG library.
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
>>> import glymur
|
|
||||||
>>> jfile = glymur.data.nemo()
|
|
||||||
>>> jp2 = glymur.Jp2k(jfile)
|
|
||||||
>>> data = jp2.read(rlevel=1)
|
|
||||||
>>> from tempfile import NamedTemporaryFile
|
|
||||||
>>> tfile = NamedTemporaryFile(suffix='.jp2', delete=False)
|
|
||||||
>>> j = Jp2k(tfile.name, mode='wb')
|
|
||||||
>>> j.write(data.astype(np.uint8))
|
|
||||||
"""
|
"""
|
||||||
if re.match("1.[0-4]", version.openjpeg_version) is not None:
|
if re.match("1.[0-4]", version.openjpeg_version) is not None:
|
||||||
raise RuntimeError("You must have at least version 1.5 of OpenJPEG "
|
raise RuntimeError("You must have at least version 1.5 of OpenJPEG "
|
||||||
|
|
@ -679,7 +728,12 @@ class Jp2k(Jp2kBox):
|
||||||
|
|
||||||
# Turn the colorspace from a string to the enumerated value that
|
# Turn the colorspace from a string to the enumerated value that
|
||||||
# the library expects.
|
# the library expects.
|
||||||
self._colorspace = _COLORSPACE_MAP[colorspace.lower()]
|
COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB,
|
||||||
|
'gray': opj2.CLRSPC_GRAY,
|
||||||
|
'grey': opj2.CLRSPC_GRAY,
|
||||||
|
'ycc': opj2.CLRSPC_YCC}
|
||||||
|
|
||||||
|
self._colorspace = COLORSPACE_MAP[colorspace.lower()]
|
||||||
|
|
||||||
|
|
||||||
def _write_openjp2(self, img_array, verbose=False):
|
def _write_openjp2(self, img_array, verbose=False):
|
||||||
|
|
@ -1780,6 +1834,8 @@ def _validate_singletons(boxes):
|
||||||
if 'dtbl' in multiples:
|
if 'dtbl' in multiples:
|
||||||
raise IOError('There can only be one dtbl box in a file.')
|
raise IOError('There can only be one dtbl box in a file.')
|
||||||
|
|
||||||
|
JPX_IDS = ['asoc', 'nlst']
|
||||||
|
|
||||||
def _validate_jpx_brand(boxes, brand):
|
def _validate_jpx_brand(boxes, brand):
|
||||||
"""
|
"""
|
||||||
If there is a JPX box then the brand must be 'jpx '.
|
If there is a JPX box then the brand must be 'jpx '.
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ class SliceProtocolBase(unittest.TestCase):
|
||||||
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
||||||
class TestSliceProtocolBaseWrite(SliceProtocolBase):
|
class TestSliceProtocolBaseWrite(SliceProtocolBase):
|
||||||
|
|
||||||
|
@unittest.skip('requires shape implementation')
|
||||||
def test_write_ellipsis(self):
|
def test_write_ellipsis(self):
|
||||||
expected = self.j2k_data
|
expected = self.j2k_data
|
||||||
|
|
||||||
|
|
@ -95,12 +96,12 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase):
|
||||||
expected = self.j2k_data
|
expected = self.j2k_data
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=self.j2k_data)
|
||||||
j[:] = self.j2k_data
|
|
||||||
actual = j[:]
|
actual = j[:]
|
||||||
|
|
||||||
np.testing.assert_array_equal(actual, expected)
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
@unittest.skip('requires shape implementation')
|
||||||
def test_cannot_write_with_non_default_single_slice(self):
|
def test_cannot_write_with_non_default_single_slice(self):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, 'wb')
|
||||||
|
|
@ -113,30 +114,35 @@ class TestSliceProtocolBaseWrite(SliceProtocolBase):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
j[slice(0, 640)] = self.j2k_data
|
j[slice(0, 640)] = self.j2k_data
|
||||||
|
|
||||||
|
@unittest.skip('requires shape implementation')
|
||||||
def test_cannot_write_a_row(self):
|
def test_cannot_write_a_row(self):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, 'wb')
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
j[5] = self.j2k_data
|
j[5] = self.j2k_data
|
||||||
|
|
||||||
|
@unittest.skip('requires shape implementation')
|
||||||
def test_cannot_write_a_pixel(self):
|
def test_cannot_write_a_pixel(self):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, 'wb')
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
j[25, 35] = self.j2k_data[25, 35]
|
j[25, 35] = self.j2k_data[25, 35]
|
||||||
|
|
||||||
|
@unittest.skip('requires shape implementation')
|
||||||
def test_cannot_write_a_column(self):
|
def test_cannot_write_a_column(self):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, 'wb')
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
j[:, 25, :] = self.j2k_data[:, :25, :]
|
j[:, 25, :] = self.j2k_data[:, :25, :]
|
||||||
|
|
||||||
|
@unittest.skip('requires shape implementation')
|
||||||
def test_cannot_write_a_band(self):
|
def test_cannot_write_a_band(self):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, 'wb')
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
j[:, :, 0] = self.j2k_data[:, :, 0]
|
j[:, :, 0] = self.j2k_data[:, :, 0]
|
||||||
|
|
||||||
|
@unittest.skip('requires shape implementation')
|
||||||
def test_cannot_write_a_subarray(self):
|
def test_cannot_write_a_subarray(self):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, 'wb')
|
||||||
|
|
@ -297,8 +303,7 @@ class TestJp2k(unittest.TestCase):
|
||||||
j = Jp2k(self.jp2file)
|
j = Jp2k(self.jp2file)
|
||||||
expdata = j[:]
|
expdata = j[:]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j2 = Jp2k(tfile.name, 'wb')
|
j2 = Jp2k(tfile.name, data=expdata, irreversible=True)
|
||||||
j2.write(expdata, irreversible=True)
|
|
||||||
|
|
||||||
codestream = j2.get_codestream()
|
codestream = j2.get_codestream()
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
|
|
@ -337,7 +342,6 @@ class TestJp2k(unittest.TestCase):
|
||||||
newjp2 = eval(repr(j))
|
newjp2 = eval(repr(j))
|
||||||
|
|
||||||
self.assertEqual(newjp2.filename, self.j2kfile)
|
self.assertEqual(newjp2.filename, self.j2kfile)
|
||||||
self.assertEqual(newjp2.mode, 'rb')
|
|
||||||
self.assertEqual(len(newjp2.box), 0)
|
self.assertEqual(len(newjp2.box), 0)
|
||||||
|
|
||||||
@unittest.skip("see issue 302")
|
@unittest.skip("see issue 302")
|
||||||
|
|
@ -664,32 +668,30 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
data = np.zeros((640, 480), dtype=np.uint8)
|
data = np.zeros((640, 480), dtype=np.uint8)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data,
|
||||||
j.write(data, cbsize=(16, 16), psizes=[(16, 16)])
|
cbsize=(16, 16), psizes=[(16, 16)])
|
||||||
|
|
||||||
def test_precinct_size_not_power_of_two(self):
|
def test_precinct_size_not_power_of_two(self):
|
||||||
"""must be power of two"""
|
"""must be power of two"""
|
||||||
data = np.zeros((640, 480), dtype=np.uint8)
|
data = np.zeros((640, 480), dtype=np.uint8)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data,
|
||||||
j.write(data, cbsize=(16, 16), psizes=[(48, 48)])
|
cbsize=(16, 16), psizes=[(48, 48)])
|
||||||
|
|
||||||
def test_unsupported_int32(self):
|
def test_unsupported_int32(self):
|
||||||
"""Should raise a runtime error if trying to write int32"""
|
"""Should raise a runtime error if trying to write int32"""
|
||||||
data = np.zeros((128, 128), dtype=np.int32)
|
data = np.zeros((128, 128), dtype=np.int32)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
with self.assertRaises(RuntimeError):
|
with self.assertRaises(RuntimeError):
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data)
|
||||||
j.write(data)
|
|
||||||
|
|
||||||
def test_unsupported_uint32(self):
|
def test_unsupported_uint32(self):
|
||||||
"""Should raise a runtime error if trying to write uint32"""
|
"""Should raise a runtime error if trying to write uint32"""
|
||||||
data = np.zeros((128, 128), dtype=np.uint32)
|
data = np.zeros((128, 128), dtype=np.uint32)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
with self.assertRaises(RuntimeError):
|
with self.assertRaises(RuntimeError):
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data)
|
||||||
j.write(data)
|
|
||||||
|
|
||||||
def test_write_with_version_too_early(self):
|
def test_write_with_version_too_early(self):
|
||||||
"""Should raise a runtime error if trying to write with version 1.3"""
|
"""Should raise a runtime error if trying to write with version 1.3"""
|
||||||
|
|
@ -699,8 +701,7 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
with patch('glymur.version.openjpeg_version', new=version):
|
with patch('glymur.version.openjpeg_version', new=version):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
with self.assertRaises(RuntimeError):
|
with self.assertRaises(RuntimeError):
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data)
|
||||||
j.write(data)
|
|
||||||
|
|
||||||
def test_cblkh_different_than_width(self):
|
def test_cblkh_different_than_width(self):
|
||||||
"""Verify that we can set a code block size where height does not equal
|
"""Verify that we can set a code block size where height does not equal
|
||||||
|
|
@ -708,11 +709,8 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
data = np.zeros((128, 128), dtype=np.uint8)
|
data = np.zeros((128, 128), dtype=np.uint8)
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
|
|
||||||
# The code block dimensions are given as rows x columns.
|
# The code block dimensions are given as rows x columns.
|
||||||
j.write(data, cbsize=(16, 32))
|
j = Jp2k(tfile.name, data=data, cbsize=(16, 32))
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
|
|
||||||
# Code block size is reported as XY in the codestream.
|
# Code block size is reported as XY in the codestream.
|
||||||
|
|
@ -721,59 +719,55 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
def test_too_many_dimensions(self):
|
def test_too_many_dimensions(self):
|
||||||
"""OpenJP2 only allows 2D or 3D images."""
|
"""OpenJP2 only allows 2D or 3D images."""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
data = np.zeros((128, 128, 2, 2), dtype=np.uint8)
|
j = Jp2k(tfile.name,
|
||||||
j.write(data)
|
data=np.zeros((128, 128, 2, 2), dtype=np.uint8))
|
||||||
|
|
||||||
def test_2d_rgb(self):
|
def test_2d_rgb(self):
|
||||||
"""RGB must have at least 3 components."""
|
"""RGB must have at least 3 components."""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
data = np.zeros((128, 128, 2), dtype=np.uint8)
|
j = Jp2k(tfile.name,
|
||||||
j.write(data, colorspace='rgb')
|
data=np.zeros((128, 128, 2), dtype=np.uint8),
|
||||||
|
colorspace='rgb')
|
||||||
|
|
||||||
def test_colorspace_with_j2k(self):
|
def test_colorspace_with_j2k(self):
|
||||||
"""Specifying a colorspace with J2K does not make sense"""
|
"""Specifying a colorspace with J2K does not make sense"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
j = Jp2k(tfile.name,
|
||||||
j.write(data, colorspace='rgb')
|
data=np.zeros((128, 128, 3), dtype=np.uint8),
|
||||||
|
colorspace='rgb')
|
||||||
|
|
||||||
def test_specify_rgb(self):
|
def test_specify_rgb(self):
|
||||||
"""specify RGB explicitly"""
|
"""specify RGB explicitly"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name,
|
||||||
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
data=np.zeros((128, 128, 3), dtype=np.uint8),
|
||||||
j.write(data, colorspace='rgb')
|
colorspace='rgb')
|
||||||
self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB)
|
self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB)
|
||||||
|
|
||||||
def test_specify_gray(self):
|
def test_specify_gray(self):
|
||||||
"""test gray explicitly specified (that's GRAY, not GREY)"""
|
"""test gray explicitly specified (that's GRAY, not GREY)"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
data = np.zeros((128, 128), dtype=np.uint8)
|
data = np.zeros((128, 128), dtype=np.uint8)
|
||||||
j.write(data, colorspace='gray')
|
j = Jp2k(tfile.name, data=data, colorspace='gray')
|
||||||
self.assertEqual(j.box[2].box[1].colorspace,
|
self.assertEqual(j.box[2].box[1].colorspace,
|
||||||
glymur.core.GREYSCALE)
|
glymur.core.GREYSCALE)
|
||||||
|
|
||||||
def test_specify_grey(self):
|
def test_specify_grey(self):
|
||||||
"""test grey explicitly specified"""
|
"""test grey explicitly specified"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
data = np.zeros((128, 128), dtype=np.uint8)
|
data = np.zeros((128, 128), dtype=np.uint8)
|
||||||
j.write(data, colorspace='grey')
|
j = Jp2k(tfile.name, data=data, colorspace='grey')
|
||||||
self.assertEqual(j.box[2].box[1].colorspace,
|
self.assertEqual(j.box[2].box[1].colorspace,
|
||||||
glymur.core.GREYSCALE)
|
glymur.core.GREYSCALE)
|
||||||
|
|
||||||
def test_grey_with_two_extra_comps(self):
|
def test_grey_with_two_extra_comps(self):
|
||||||
"""should be able to write gray + two extra components"""
|
"""should be able to write gray + two extra components"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
||||||
j.write(data, colorspace='gray')
|
j = Jp2k(tfile.name, data=data, colorspace='gray')
|
||||||
self.assertEqual(j.box[2].box[0].height, 128)
|
self.assertEqual(j.box[2].box[0].height, 128)
|
||||||
self.assertEqual(j.box[2].box[0].width, 128)
|
self.assertEqual(j.box[2].box[0].width, 128)
|
||||||
self.assertEqual(j.box[2].box[0].num_components, 3)
|
self.assertEqual(j.box[2].box[0].num_components, 3)
|
||||||
|
|
@ -783,18 +777,16 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
def test_specify_ycc(self):
|
def test_specify_ycc(self):
|
||||||
"""Should reject YCC"""
|
"""Should reject YCC"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
||||||
j.write(data, colorspace='ycc')
|
j = Jp2k(tfile.name, data=data, colorspace='ycc')
|
||||||
|
|
||||||
def test_write_with_jp2_in_caps(self):
|
def test_write_with_jp2_in_caps(self):
|
||||||
"""should be able to write with JP2 suffix."""
|
"""should be able to write with JP2 suffix."""
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
expdata = j2k[:]
|
expdata = j2k[:]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.JP2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.JP2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
ofile = Jp2k(tfile.name, data=expdata)
|
||||||
ofile[:] = expdata
|
|
||||||
actdata = ofile[:]
|
actdata = ofile[:]
|
||||||
np.testing.assert_array_equal(actdata, expdata)
|
np.testing.assert_array_equal(actdata, expdata)
|
||||||
|
|
||||||
|
|
@ -803,8 +795,7 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
expdata = j2k[:]
|
expdata = j2k[:]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
ofile = Jp2k(tfile.name, data=expdata, mct=False)
|
||||||
ofile.write(expdata, mct=False)
|
|
||||||
actdata = ofile[:]
|
actdata = ofile[:]
|
||||||
np.testing.assert_array_equal(actdata, expdata)
|
np.testing.assert_array_equal(actdata, expdata)
|
||||||
|
|
||||||
|
|
@ -816,9 +807,8 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
j2k = Jp2k(self.j2kfile)
|
j2k = Jp2k(self.j2kfile)
|
||||||
expdata = j2k[:]
|
expdata = j2k[:]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
ofile.write(expdata[:, :, 0], mct=True)
|
ofile = Jp2k(tfile.name, data=expdata[:, :, 0], mct=True)
|
||||||
|
|
||||||
def test_write_cprl(self):
|
def test_write_cprl(self):
|
||||||
"""Must be able to write a CPRL progression order file"""
|
"""Must be able to write a CPRL progression order file"""
|
||||||
|
|
@ -826,8 +816,7 @@ class TestJp2k_write(unittest.TestCase):
|
||||||
j = Jp2k(self.jp2file)
|
j = Jp2k(self.jp2file)
|
||||||
expdata = j[::2, ::2]
|
expdata = j[::2, ::2]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
ofile = Jp2k(tfile.name, 'wb')
|
ofile = Jp2k(tfile.name, data=expdata, prog='CPRL')
|
||||||
ofile.write(expdata, prog='CPRL')
|
|
||||||
actdata = ofile[:]
|
actdata = ofile[:]
|
||||||
np.testing.assert_array_equal(actdata, expdata)
|
np.testing.assert_array_equal(actdata, expdata)
|
||||||
|
|
||||||
|
|
@ -873,10 +862,9 @@ class Test_2p0_official(unittest.TestCase):
|
||||||
"""Can only write 4 components on 2.0+, should error out otherwise."""
|
"""Can only write 4 components on 2.0+, should error out otherwise."""
|
||||||
with patch('glymur.version.openjpeg_version', new="2.0.0"):
|
with patch('glymur.version.openjpeg_version', new="2.0.0"):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
data = np.zeros((128, 128, 4), dtype=np.uint8)
|
data = np.zeros((128, 128, 4), dtype=np.uint8)
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j.write(data)
|
Jp2k(tfile.name, data=data)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2,
|
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2,
|
||||||
|
|
@ -908,10 +896,9 @@ class TestJp2k_2_0(unittest.TestCase):
|
||||||
def test_unrecognized_jp2_clrspace(self):
|
def test_unrecognized_jp2_clrspace(self):
|
||||||
"""We only allow RGB and GRAYSCALE. Should error out with others"""
|
"""We only allow RGB and GRAYSCALE. Should error out with others"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
data = np.zeros((128, 128, 3), dtype=np.uint8)
|
j = Jp2k(tfile.name, data=data, colorspace='cmyk')
|
||||||
j.write(data, colorspace='cmyk')
|
|
||||||
|
|
||||||
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
@unittest.skipIf(os.name == "nt", fixtures.WINDOWS_TMP_FILE_MSG)
|
||||||
def test_asoc_label_box(self):
|
def test_asoc_label_box(self):
|
||||||
|
|
@ -920,8 +907,7 @@ class TestJp2k_2_0(unittest.TestCase):
|
||||||
# OpenJPEG doesn't have such a file.
|
# OpenJPEG doesn't have such a file.
|
||||||
data = Jp2k(self.jp2file)[::2, ::2]
|
data = Jp2k(self.jp2file)[::2, ::2]
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=data)
|
||||||
j.write(data)
|
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2:
|
||||||
|
|
||||||
|
|
@ -979,9 +965,8 @@ class TestJp2k_2_1(unittest.TestCase):
|
||||||
def test_grey_with_extra_component(self):
|
def test_grey_with_extra_component(self):
|
||||||
"""version 2.0 cannot write gray + extra"""
|
"""version 2.0 cannot write gray + extra"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
data = np.zeros((128, 128, 2), dtype=np.uint8)
|
data = np.zeros((128, 128, 2), dtype=np.uint8)
|
||||||
j.write(data)
|
j = Jp2k(tfile.name, data=data)
|
||||||
self.assertEqual(j.box[2].box[0].height, 128)
|
self.assertEqual(j.box[2].box[0].height, 128)
|
||||||
self.assertEqual(j.box[2].box[0].width, 128)
|
self.assertEqual(j.box[2].box[0].width, 128)
|
||||||
self.assertEqual(j.box[2].box[0].num_components, 2)
|
self.assertEqual(j.box[2].box[0].num_components, 2)
|
||||||
|
|
@ -992,9 +977,8 @@ class TestJp2k_2_1(unittest.TestCase):
|
||||||
def test_rgb_with_extra_component(self):
|
def test_rgb_with_extra_component(self):
|
||||||
"""v2.0+ should be able to write extra components"""
|
"""v2.0+ should be able to write extra components"""
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
data = np.zeros((128, 128, 4), dtype=np.uint8)
|
data = np.zeros((128, 128, 4), dtype=np.uint8)
|
||||||
j.write(data)
|
j = Jp2k(tfile.name, data=data)
|
||||||
self.assertEqual(j.box[2].box[0].height, 128)
|
self.assertEqual(j.box[2].box[0].height, 128)
|
||||||
self.assertEqual(j.box[2].box[0].width, 128)
|
self.assertEqual(j.box[2].box[0].width, 128)
|
||||||
self.assertEqual(j.box[2].box[0].num_components, 4)
|
self.assertEqual(j.box[2].box[0].num_components, 4)
|
||||||
|
|
@ -1130,8 +1114,7 @@ class TestJp2kOpjDataRoot(unittest.TestCase):
|
||||||
expdata = np.fromfile(filename, dtype=np.uint16)
|
expdata = np.fromfile(filename, dtype=np.uint16)
|
||||||
expdata.resize((2816, 2048))
|
expdata.resize((2816, 2048))
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
j = Jp2k(tfile.name, data=expdata, irreversible=True)
|
||||||
j.write(expdata, irreversible=True)
|
|
||||||
|
|
||||||
codestream = j.get_codestream()
|
codestream = j.get_codestream()
|
||||||
self.assertEqual(codestream.segment[2].spcod[8],
|
self.assertEqual(codestream.segment[2].spcod[8],
|
||||||
|
|
|
||||||
|
|
@ -221,9 +221,8 @@ class TestNegative2pointzero(unittest.TestCase):
|
||||||
for version in versions:
|
for version in versions:
|
||||||
with patch('glymur.version.openjpeg_version', new=version):
|
with patch('glymur.version.openjpeg_version', new=version):
|
||||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||||
j = Jp2k(tfile.name, 'wb')
|
|
||||||
with self.assertRaises(IOError):
|
with self.assertRaises(IOError):
|
||||||
j.write(data, cinema2k=48)
|
j = Jp2k(tfile.name, data=data, cinema2k=48)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None,
|
@unittest.skipIf(re.match(r'''1.[0-4]''', openjpeg_version) is not None,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue