diff --git a/.gitignore b/.gitignore index 44f9c60..bbe1ac8 100644 --- a/.gitignore +++ b/.gitignore @@ -45,5 +45,9 @@ docs/_build docs/modules.rst docs/planetaryimage.rst +# Pycharm +.idea/ + # Sample Data tests/mission_data +.pytest_cache/ diff --git a/AUTHORS.rst b/AUTHORS.rst index 5d1d75b..5125b7c 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -13,4 +13,5 @@ Contributors * Trevor Olson * Nikhil Kalige * Austin Godber -* Bhavin Nayak \ No newline at end of file +* Bhavin Nayak +* Andrew Annex diff --git a/planetaryimage/decoders.py b/planetaryimage/decoders.py index 5f058b4..ca10304 100644 --- a/planetaryimage/decoders.py +++ b/planetaryimage/decoders.py @@ -3,6 +3,9 @@ class BandSequentialDecoder(object): + """ + BSQ + """ def __init__(self, dtype, shape, compression=None): self.dtype = dtype self.shape = shape @@ -21,6 +24,34 @@ def decode(self, stream): return data.reshape(self.shape) +class LineInterleavedDecoder(object): + """ + BIL + """ + def __init__(self, dtype, shape, compression=None): + self.dtype = dtype + self.shape = shape + self.sample_bytes = dtype.itemsize + self.compression = compression + + @property + def size(self): + return numpy.product(self.shape) + + def decode(self, stream): + bands, lines, samples = self.shape + bs = bands*samples + data = numpy.empty(self.shape, self.dtype) + for line in range(lines): + if self.compression: + chunk = numpy.fromstring(stream.read(bs * self.sample_bytes), self.dtype) + else: + chunk = numpy.fromfile(stream, self.dtype, bs) + data[:, line, :] = chunk.reshape((bands, samples)) + + return data + + class TileDecoder(object): def __init__(self, dtype, shape, tile_shape): self.dtype = dtype diff --git a/planetaryimage/image.py b/planetaryimage/image.py index dda0d91..9ffd4c2 100644 --- a/planetaryimage/image.py +++ b/planetaryimage/image.py @@ -142,9 +142,10 @@ def image(self): """ if self.bands == 1: return self.data.squeeze() - elif self.bands == 3: + elif self.bands > 1: return numpy.dstack(self.data) - # TODO: what about multiband images with 2, and 4+ bands? + else: + raise NotImplementedError('Have no impl for {} bands'.format(self.bands)) @property def bands(self): diff --git a/planetaryimage/pds3image.py b/planetaryimage/pds3image.py index fd93999..bb8ad69 100644 --- a/planetaryimage/pds3image.py +++ b/planetaryimage/pds3image.py @@ -6,7 +6,7 @@ import collections from .image import PlanetaryImage -from .decoders import BandSequentialDecoder +from . import decoders class Pointer(collections.namedtuple('Pointer', ['filename', 'bytes'])): @@ -311,6 +311,12 @@ def record_bytes(self): @property def _image_pointer(self): + # If we have a File object containing an Image within it + if '^IMAGE' not in self.label and 'FILE' in self.label: + new_label = self.label['FILE'] + if '^IMAGE' in new_label: + self.label = new_label + return Pointer.parse(new_label['^IMAGE'], self.record_bytes) return Pointer.parse(self.label['^IMAGE'], self.record_bytes) @property @@ -343,7 +349,12 @@ def dtype(self): @property def _decoder(self): if self.format == 'BAND_SEQUENTIAL': - return BandSequentialDecoder( + return decoders.BandSequentialDecoder( self.dtype, self.shape, self.compression ) + elif self.format == 'LINE_INTERLEAVED': + return decoders.LineInterleavedDecoder( + self.dtype, self.shape, self.compression + ) + raise ValueError('Unkown format (%s)' % self.format) diff --git a/tests/test_pds3file.py b/tests/test_pds3file.py index a30b4e5..d054c3d 100644 --- a/tests/test_pds3file.py +++ b/tests/test_pds3file.py @@ -14,7 +14,6 @@ gzipped_filename = os.path.join(DATA_DIR, 'pds3_1band.IMG.gz') bz2_filename = os.path.join(DATA_DIR, 'pds3_1band.IMG.bz2') - @pytest.fixture def expected(): return numpy.loadtxt(os.path.join(DATA_DIR, 'pds3_1band.txt')).reshape(