def _prepared_data_and_metadata(hdr_file, image, **kwargs): ''' Return data array and metadata dict representing `image`. ''' import os import sys import spectral from spectral.io.spyfile import SpyFile, interleave_transpose endian_out = str(kwargs.get('byteorder', sys.byteorder)).lower() if endian_out in ('0', 'little'): endian_out = 'little' elif endian_out in ('1', 'big'): endian_out = 'big' else: raise ValueError('Invalid byte order: "%s".' % endian_out) if isinstance(image, np.ndarray): data = image src_interleave = 'bip' swap = False elif isinstance(image, SpyFile): if image.using_memmap is True: data = image._memmap src_interleave = {spectral.BSQ: 'bsq', spectral.BIL: 'bil', spectral.BIP: 'bip'}[image.interleave] swap = image.swap else: data = image.load(dtype=image.dtype, scale=False) src_interleave = 'bip' swap = False else: data = image.load() src_interleave = 'bip' swap = False metadata = kwargs.get('metadata', {}).copy() add_image_info_to_metadata(image, metadata) if hasattr(image, 'bands'): add_band_info_to_metadata(image.bands, metadata) dtype = np.dtype(kwargs.get('dtype', data.dtype)).char _validate_dtype(dtype) if dtype != data.dtype.char: data = data.astype(dtype) metadata['data type'] = dtype_to_envi[dtype] interleave = kwargs.get('interleave', 'bip').lower() if interleave not in ['bil', 'bip', 'bsq']: raise ValueError('Invalid interleave: %s' % str(kwargs['interleave'])) if interleave != src_interleave: data = data.transpose(interleave_transpose(src_interleave, interleave)) metadata['interleave'] = interleave metadata['byte order'] = 1 if endian_out == 'big' else 0 if (endian_out == sys.byteorder and not data.dtype.isnative) or \ (endian_out != sys.byteorder and data.dtype.isnative): data = data.byteswap() return data, metadata
def save_image(hdr_file, image, **kwargs): ''' Saves an image to disk. Arguments: `hdr_file` (str): Header file (with ".hdr" extension) name with path. `image` (SpyFile object or numpy.ndarray): The image to save. Keyword Arguments: `dtype` (numpy dtype or type string): The numpy data type with which to store the image. For example, to store the image in 16-bit unsigned integer format, the argument could be any of `numpy.uint16`, "u2", "uint16", or "H". `force` (bool): If the associated image file or header already exist and `force` is True, the files will be overwritten; otherwise, if either of the files exist, an exception will be raised. `ext` (str): The extension to use for the image file. If not specified, the default extension ".img" will be used. If `ext` is an empty string, the image file will have the same name as the header but without the ".hdr" extension. `interleave` (str): The band interleave format to use in the file. This argument should be one of "bil", "bip", or "bsq". If not specified, the image will be written in BIP interleave. `byteorder` (int or string): Specifies the byte order (endian-ness) of the data as written to disk. For little endian, this value should be either 0 or "little". For big endian, it should be either 1 or "big". If not specified, native byte order will be used. `metadata` (dict): A dict containing ENVI header parameters (e.g., parameters extracted from a source image). Example:: >>> # Save the first 10 principal components of an image >>> data = open_image('92AV3C.lan').load() >>> pc = principal_components(data) >>> pcdata = pc.reduce(num=10).transform(data) >>> envi.save_image('pcimage.hdr', pcdata, dtype=np.float32) If the source image being saved was already in ENVI format, then the SpyFile object for that image will contain a `metadata` dict that can be passed as the `metadata` keyword. However, care should be taken to ensure that all the metadata fields from the source image are still accurate (e.g., band names or wavelengths will no longer be correct if the data being saved are from a principal components transformation). ''' import os import sys import __builtin__ import spectral from spectral.io.spyfile import SpyFile, interleave_transpose metadata = kwargs.get('metadata', {}).copy() force = kwargs.get('force', False) img_ext = kwargs.get('ext', '.img') endian_out = str(kwargs.get('byteorder', sys.byteorder)).lower() if endian_out in ('0', 'little'): endian_out = 'little' elif endian_out in ('1', 'big'): endian_out = 'big' else: raise ValueError('Invalid byte order: "%s".' % endian_out) (hdr_file, img_file) = check_new_filename(hdr_file, img_ext, force) if isinstance(image, np.ndarray): data = image src_interleave = 'bip' swap = False elif isinstance(image, SpyFile): if image.using_memmap is True: data = image._memmap src_interleave = {spectral.BSQ: 'bsq', spectral.BIL: 'bil', spectral.BIP: 'bip'}[image.interleave] swap = image.swap else: data = image.load(dtype=image.dtype, scale=False) src_interleave = 'bip' swap = False if image.scale_factor != 1: metadata['reflectance scale factor'] = image.scale_factor else: data = image.load() src_interleave = 'bip' swap = False dtype = np.dtype(kwargs.get('dtype', data.dtype)).char if dtype != data.dtype.char: data = data.astype(dtype) metadata['data type'] = dtype_to_envi[dtype] # A few header parameters need to be set independent of what is provided # in the supplied metadata. # Always write data from start of file, regardless of what was in # provided metadata. offset = int(metadata.get('header offset', 0)) if offset != 0: print 'Ignoring non-zero header offset in provided metadata.' metadata['header offset'] = 0 metadata['lines'] = image.shape[0] metadata['samples'] = image.shape[1] if len(image.shape) == 3: metadata['bands'] = image.shape[2] else: metadata['bands'] = 1 metadata['file type'] = 'ENVI Standard' interleave = kwargs.get('interleave', 'bip').lower() if interleave not in ['bil', 'bip', 'bsq']: raise ValueError('Invalid interleave: %s' % str(kwargs['interleave'])) if interleave != src_interleave: data = data.transpose(interleave_transpose(src_interleave, interleave)) metadata['interleave'] = interleave metadata['byte order'] = 1 if endian_out == 'big' else 0 if (endian_out == sys.byteorder and not data.dtype.isnative) or \ (endian_out != sys.byteorder and data.dtype.isnative): data = data.byteswap() if hasattr(image, 'bands'): add_band_info_to_metadata(image.bands, metadata) write_envi_header(hdr_file, metadata, is_library=False) print 'Saving', img_file bufsize = data.shape[0] * data.shape[1] * np.dtype(dtype).itemsize fout = __builtin__.open(img_file, 'wb', bufsize) fout.write(data.tostring()) fout.close()
def _prepared_data_and_metadata(hdr_file, image, **kwargs): ''' Return data array and metadata dict representing `image`. ''' import os import sys import spectral from spectral.io.spyfile import SpyFile, interleave_transpose endian_out = str(kwargs.get('byteorder', sys.byteorder)).lower() if endian_out in ('0', 'little'): endian_out = 'little' elif endian_out in ('1', 'big'): endian_out = 'big' else: raise ValueError('Invalid byte order: "%s".' % endian_out) if isinstance(image, np.ndarray): data = image src_interleave = 'bip' if len(data.shape) == 2: data = data[:, :, np.newaxis] swap = False metadata = {} elif isinstance(image, SpyFile): if image.using_memmap is True: data = image._memmap src_interleave = { spectral.BSQ: 'bsq', spectral.BIL: 'bil', spectral.BIP: 'bip' }[image.interleave] swap = image.swap else: data = image.load(dtype=image.dtype, scale=False) src_interleave = 'bip' swap = False metadata = image.metadata.copy() else: data = image.load(scale=False) src_interleave = 'bip' swap = False if hasattr(image, 'metadata'): metadata = image.metadata.copy() else: metadata = {} metadata.update(kwargs.get('metadata', {})) add_image_info_to_metadata(image, metadata) if hasattr(image, 'bands'): add_band_info_to_metadata(image.bands, metadata) dtype = np.dtype(kwargs.get('dtype', data.dtype)).char _validate_dtype(dtype) if dtype != data.dtype.char: data = data.astype(dtype) metadata['data type'] = dtype_to_envi[dtype] interleave = kwargs.get('interleave', 'bip').lower() if interleave not in ['bil', 'bip', 'bsq']: raise ValueError('Invalid interleave: %s' % str(kwargs['interleave'])) if interleave != src_interleave: data = data.transpose(interleave_transpose(src_interleave, interleave)) metadata['interleave'] = interleave metadata['byte order'] = 1 if endian_out == 'big' else 0 if (endian_out == sys.byteorder and not data.dtype.isnative) or \ (endian_out != sys.byteorder and data.dtype.isnative): data = data.byteswap() return data, metadata