Merge branch 'issue246' of https://github.com/quintusdias/glymur into issue246
This commit is contained in:
commit
c61bf0babe
3 changed files with 134 additions and 102 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
|||
*.pyc
|
||||
*.swp
|
||||
|
|
|
|||
|
|
@ -759,49 +759,51 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
return boxes
|
||||
|
||||
def __getitem__(self, *pargs):
|
||||
def __getitem__(self, pargs):
|
||||
"""
|
||||
Slicing protocol.
|
||||
"""
|
||||
if isinstance(pargs[0], slice):
|
||||
if isinstance(pargs, slice):
|
||||
# Case of jp2[:]
|
||||
#
|
||||
# Should have a slice object where start = stop = step = None
|
||||
slc = pargs[0]
|
||||
slc = pargs
|
||||
if slc.start is None and slc.stop is None and slc.step is None:
|
||||
return self.read()
|
||||
else:
|
||||
raise IndexError("Illegal syntax.")
|
||||
|
||||
if isinstance(pargs[0], tuple):
|
||||
ridx = pargs[0][0]
|
||||
cidx = pargs[0][1]
|
||||
# Assuming pargs is a tuple from now on.
|
||||
rows = pargs[0]
|
||||
cols = pargs[1]
|
||||
if len(pargs) == 2:
|
||||
bands = slice(None, None, None)
|
||||
else:
|
||||
bands = pargs[2]
|
||||
|
||||
if ((ridx.start is not None) or
|
||||
(ridx.stop is not None) or
|
||||
(cidx.start is not None) or
|
||||
(cidx.stop is not None)):
|
||||
msg = "Only strides are supported when slicing a Jp2k object."
|
||||
raise IndexError(msg)
|
||||
if ((rows.step is None) and (cols.step is None)):
|
||||
# Slicing with full resolution.
|
||||
# This can be improved to take advantage of tiling.
|
||||
return self.read()[rows, cols, bands]
|
||||
|
||||
if ridx.step is None and cidx.step is None:
|
||||
step = 1
|
||||
elif ridx.step != cidx.step:
|
||||
msg = "Row and column strides must be the same."
|
||||
raise IndexError(msg)
|
||||
else:
|
||||
step = ridx.step
|
||||
|
||||
if np.log2(step) != np.floor(np.log2(step)):
|
||||
msg = "Row and column strides must be powers of 2."
|
||||
raise IndexError(msg)
|
||||
if rows.step != cols.step:
|
||||
msg = "Row and column strides must be the same."
|
||||
raise IndexError(msg)
|
||||
|
||||
data = self.read(rlevel=np.int(np.log2(step)))
|
||||
if len(pargs[0]) == 2:
|
||||
return data
|
||||
# Ok, reduce layer step is the same in both xy directions, so just take
|
||||
# one of them.
|
||||
step = rows.step
|
||||
|
||||
if np.log2(step) != np.floor(np.log2(step)):
|
||||
msg = "Row and column strides must be powers of 2."
|
||||
raise IndexError(msg)
|
||||
|
||||
# Ok, 3 arguments in pargs.
|
||||
if isinstance(pargs[0][2], slice):
|
||||
return data[:,:,pargs[0][2]]
|
||||
elif isinstance(pargs[0][2], int):
|
||||
return data[:,:,pargs[0][2]]
|
||||
data = self.read(rlevel=np.int(np.log2(step)))
|
||||
if len(pargs) == 2:
|
||||
return data
|
||||
|
||||
# Ok, 3 arguments in pargs.
|
||||
return data[:, :, bands]
|
||||
|
||||
|
||||
def read(self, **kwargs):
|
||||
|
|
|
|||
|
|
@ -52,6 +52,106 @@ def load_tests(loader, tests, ignore):
|
|||
return tests
|
||||
|
||||
|
||||
class TestSliceProtocol(unittest.TestCase):
|
||||
"""
|
||||
Test slice protocol, i.e. when using [ ] to read image data.
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
|
||||
self.jp2 = Jp2k(glymur.data.nemo())
|
||||
self.jp2_data = self.jp2.read()
|
||||
|
||||
self.j2k = Jp2k(glymur.data.goodstuff())
|
||||
self.j2k_data = self.j2k.read()
|
||||
|
||||
def test_resolution_strides_cannot_differ(self):
|
||||
with self.assertRaises(IndexError):
|
||||
# Strides in x/y directions cannot differ.
|
||||
self.j2k[::2, ::3]
|
||||
|
||||
def test_resolution_strides_must_be_powers_of_two(self):
|
||||
with self.assertRaises(IndexError):
|
||||
self.j2k[::3, ::3]
|
||||
|
||||
def test_integer_index_in_3d(self):
|
||||
|
||||
for j in [0, 1, 2]:
|
||||
band = self.j2k[:, :, j]
|
||||
np.testing.assert_array_equal(self.j2k_data[:, :, j], band)
|
||||
|
||||
def test_slice_in_third_dimension(self):
|
||||
actual = self.j2k[:,:,1:3]
|
||||
expected = self.j2k_data[:,:,1:3]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_reduce_resolution_and_slice_in_third_dimension(self):
|
||||
d = self.j2k[::2, ::2, 1:3]
|
||||
all = self.j2k.read(rlevel=1)
|
||||
np.testing.assert_array_equal(all[:,:,1:3], d)
|
||||
|
||||
def test_full_resolution_slicing_by_quarters_upper_left(self):
|
||||
actual = self.jp2[:728, :1296]
|
||||
expected = self.jp2_data[:728, :1296]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_full_resolution_slicing_by_quarters_lower_left(self):
|
||||
actual = self.jp2[728:, :1296]
|
||||
expected = self.jp2_data[728:, :1296]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_full_resolution_slicing_by_quarters_upper_right(self):
|
||||
actual = self.jp2[:728, 1296:]
|
||||
expected = self.jp2_data[:728, 1296:]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_full_resolution_slicing_by_quarters_lower_right(self):
|
||||
actual = self.jp2[728:, 1296:]
|
||||
expected = self.jp2_data[728:, 1296:]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_full_resolution_slicing_by_halves_left(self):
|
||||
actual = self.jp2[:, :1296]
|
||||
expected = self.jp2_data[:, :1296]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_full_resolution_slicing_by_right_half(self):
|
||||
actual = self.jp2[:, 1296:]
|
||||
expected = self.jp2_data[:, 1296:]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_full_resolution_slicing_by_top_half(self):
|
||||
actual = self.jp2[:728, :]
|
||||
expected = self.jp2_data[:728, :]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_full_resolution_slicing_by_bottom_half(self):
|
||||
actual = self.jp2[728:, :]
|
||||
expected = self.jp2_data[728:, :]
|
||||
np.testing.assert_array_equal(actual, expected)
|
||||
|
||||
def test_slice_protocol_2d_reduce_resolution(self):
|
||||
d = self.j2k[:]
|
||||
self.assertEqual(d.shape, (800, 480, 3))
|
||||
|
||||
d = self.j2k[::1, ::1]
|
||||
self.assertEqual(d.shape, (800, 480, 3))
|
||||
|
||||
d = self.j2k[::2, ::2]
|
||||
self.assertEqual(d.shape, (400, 240, 3))
|
||||
|
||||
d = self.j2k[::4, ::4]
|
||||
self.assertEqual(d.shape, (200, 120, 3))
|
||||
|
||||
d = self.j2k[::8, ::8]
|
||||
self.assertEqual(d.shape, (100, 60, 3))
|
||||
|
||||
d = self.j2k[::16, ::16]
|
||||
self.assertEqual(d.shape, (50, 30, 3))
|
||||
|
||||
d = self.j2k[::32, ::32]
|
||||
self.assertEqual(d.shape, (25, 15, 3))
|
||||
|
||||
class TestJp2k(unittest.TestCase):
|
||||
"""These tests should be run by just about all configuration."""
|
||||
|
||||
|
|
@ -63,77 +163,6 @@ class TestJp2k(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_slice_protocol_negative(self):
|
||||
"""
|
||||
"""
|
||||
j = Jp2k(self.j2kfile)
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
# Strides in x/y directions cannot differ.
|
||||
d = j[::2, ::3]
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
# Strides in x/y direction must be powers of 2.
|
||||
d = j[::3, ::3]
|
||||
|
||||
# start and stop are not supported when slicing on Jp2k object
|
||||
with self.assertRaises(IndexError):
|
||||
d = j[2::2, 2::2]
|
||||
with self.assertRaises(IndexError):
|
||||
d = j[:8:2, :8:2]
|
||||
with self.assertRaises(IndexError):
|
||||
d = j[2:8:2, 2:8:2]
|
||||
|
||||
def test_slice_protocol_3d(self):
|
||||
"""
|
||||
"""
|
||||
j = Jp2k(self.j2kfile)
|
||||
all = j.read()
|
||||
|
||||
d = j[:,:,0]
|
||||
np.testing.assert_array_equal(all[:,:,0], d)
|
||||
|
||||
d = j[:,:,1]
|
||||
np.testing.assert_array_equal(all[:,:,1], d)
|
||||
|
||||
d = j[:,:,2]
|
||||
np.testing.assert_array_equal(all[:,:,2], d)
|
||||
|
||||
d = j[:,:,1:3]
|
||||
np.testing.assert_array_equal(all[:,:,1:3], d)
|
||||
|
||||
d = j[::2, ::2, 1:3]
|
||||
all = j.read(rlevel=1)
|
||||
np.testing.assert_array_equal(all[:,:,1:3], d)
|
||||
|
||||
def test_slice_protocol_2d(self):
|
||||
"""
|
||||
|
||||
"""
|
||||
j = Jp2k(self.j2kfile)
|
||||
|
||||
d = j[:]
|
||||
self.assertEqual(d.shape, (800, 480, 3))
|
||||
|
||||
# Stride of one.
|
||||
d = j[::1, ::1]
|
||||
self.assertEqual(d.shape, (800, 480, 3))
|
||||
|
||||
# Stride of 2.
|
||||
d = j[::2, ::2]
|
||||
self.assertEqual(d.shape, (400, 240, 3))
|
||||
|
||||
d = j[::4, ::4]
|
||||
self.assertEqual(d.shape, (200, 120, 3))
|
||||
|
||||
d = j[::8, ::8]
|
||||
self.assertEqual(d.shape, (100, 60, 3))
|
||||
|
||||
d = j[::16, ::16]
|
||||
self.assertEqual(d.shape, (50, 30, 3))
|
||||
|
||||
d = j[::32, ::32]
|
||||
self.assertEqual(d.shape, (25, 15, 3))
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Unexplained failure on windows")
|
||||
def test_irreversible(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue