Skip to content

Commit 70d7bc5

Browse files
committed
Raise an exception for ENVI images with frame offsets.
ENVI image files with frame offsets are not supported. If an image with frame offsets were opened, image data would be read incorrectly so an exception is now thrown instead (this addresses issue #35). - io/envi.py: - (EnviFeatureNotSupported): New class - (_has_frame_offset): New function to determine if image has frame offsets. - (check_compatibility): New function to raise exception when an unsupported feature is indicated in an ENVI header. - (open): Check compatibility before opening image. - spectral.py (open): Check compatibility before opening image. - tests/envi.py: Added tests for ENVI feature compatibilty
1 parent b6592af commit 70d7bc5

File tree

3 files changed

+100
-1
lines changed

3 files changed

+100
-1
lines changed

spectral/io/envi.py

+44-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ def __init__(self, dtype):
7878
'data type names.'.format(np.dtype(dtype).name)
7979
super(EnviDataTypeError, self).__init__(msg)
8080

81+
class EnviFeatureNotSupported(NotImplementedError):
82+
'''A specified ENVI capability is not supported by the spectral module.'''
83+
pass
84+
8185
def _validate_dtype(dtype):
8286
'''Raises EnviDataTypeError if dtype can not be written to ENVI file.'''
8387
typename = np.dtype(dtype).name
@@ -170,6 +174,44 @@ class Params:
170174
p.filename = None
171175
return p
172176

177+
def _has_frame_offset(params):
178+
'''
179+
Returns True if header params indicate non-zero frame offsets.
180+
181+
Arguments:
182+
183+
`params` (dict):
184+
185+
Dictionary of header parameters assocaited with hdr file.
186+
187+
Returns:
188+
189+
bool
190+
191+
This function returns True when either "major frame offsets" or
192+
"minor frame offsets" is specified and contains a non-zero value.
193+
'''
194+
for param in ['major frame offsets', 'minor frame offsets']:
195+
if param in params:
196+
val = params[param]
197+
if np.iterable(val):
198+
offsets = [int(x) for x in val]
199+
else:
200+
offsets = [int(val)] * 2
201+
if not np.all(np.equal(offsets, 0)):
202+
return True
203+
return False
204+
205+
def check_compatibility(header):
206+
'''
207+
Verifies that all features of an ENVI header are supported.
208+
'''
209+
from .spyfile import find_file_path
210+
if type(header) in [str, unicode]:
211+
header = read_envi_header(find_file_path(header))
212+
if _has_frame_offset(header):
213+
raise EnviFeatureNotSupported(
214+
'ENVI image frame offsets are not supported.')
173215

174216
def open(file, image=None):
175217
'''
@@ -210,7 +252,7 @@ def open(file, image=None):
210252

211253
headerPath = find_file_path(file)
212254
h = read_envi_header(headerPath)
213-
255+
check_compatibility(h)
214256
p = gen_params(h)
215257

216258
inter = h["interleave"]
@@ -594,6 +636,7 @@ def _write_image(hdr_file, data, header, **kwargs):
594636
'''
595637
Write `data` as an ENVI file using the metadata in `header`.
596638
'''
639+
check_compatibility(header)
597640
force = kwargs.get('force', False)
598641
img_ext = kwargs.get('ext', '.img')
599642

spectral/spectral.py

+2
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ def open_image(file):
471471
# Try to open it as an ENVI header file.
472472
try:
473473
return envi.open(pathname)
474+
except envi.EnviFeatureNotSupported:
475+
raise
474476
except:
475477
pass
476478

spectral/tests/envi.py

+54
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,60 @@ def test_save_load_classes(self):
175175
gt2 = spy.open_image(fname).read_band(0)
176176
assert(np.all(gt == gt2))
177177

178+
def test_open_nonzero_frame_offset_fails(self):
179+
'''Opening files with nonzero frame offsets should fail.'''
180+
import os
181+
import spectral as spy
182+
img = spy.open_image('92AV3C.lan')
183+
fname = os.path.join(testdir, 'test_open_nonzero_frame_offset_fails.hdr')
184+
spy.envi.save_image(fname, img)
185+
fout = open(fname, 'a')
186+
fout.write('major frame offsets = 128\n')
187+
fout.close()
188+
try:
189+
img2 = spy.envi.open(fname)
190+
except spy.envi.EnviFeatureNotSupported:
191+
pass
192+
else:
193+
raise Exception('File erroneously opened.')
194+
195+
def test_open_zero_frame_offset_passes(self):
196+
'''Files with frame offsets set to zero should open.'''
197+
import os
198+
import spectral as spy
199+
img = spy.open_image('92AV3C.lan')
200+
fname = os.path.join(testdir, 'test_open_zero_frame_offset_passes.hdr')
201+
spy.envi.save_image(fname, img)
202+
fout = open(fname, 'a')
203+
fout.write('major frame offsets = 0\n')
204+
fout.write('minor frame offsets = {0, 0}\n')
205+
fout.close()
206+
img2 = spy.envi.open(fname)
207+
208+
def test_save_nonzero_frame_offset_fails(self):
209+
'''Opening files with nonzero frame offsets should fail.'''
210+
import os
211+
import spectral as spy
212+
img = spy.open_image('92AV3C.lan')
213+
fname = os.path.join(testdir, 'test_save_nonzero_frame_offset_fails.hdr')
214+
meta = {'major frame offsets' : [128, 0]}
215+
try:
216+
spy.envi.save_image(fname, img, metadata=meta)
217+
except spy.envi.EnviFeatureNotSupported:
218+
pass
219+
else:
220+
raise Exception('File erroneously saved.')
221+
222+
def test_save_zero_frame_offset_passes(self):
223+
'''Opening files with nonzero frame offsets should fail.'''
224+
import os
225+
import spectral as spy
226+
img = spy.open_image('92AV3C.lan')
227+
fname = os.path.join(testdir, 'test_save_zero_frame_offset_passes.hdr')
228+
meta = {'major frame offsets' : 0}
229+
spy.envi.save_image(fname, img, metadata=meta)
230+
231+
178232
def run():
179233
print('\n' + '-' * 72)
180234
print('Running ENVI tests.')

0 commit comments

Comments
 (0)