def create_image(hdr_file, metadata=None, **kwargs): ''' Creates an image file and ENVI header with a memmep array for write access. Arguments: `hdr_file` (str): Header file (with ".hdr" extension) name with path. `metadata` (dict): Metadata to specify the image file format. The following parameters (in ENVI header format) are required, if not specified via corresponding keyword arguments: "bands", "lines", "samples", and "data type". 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". If this keyword is given, it will override the "data type" parameter in the `metadata` argument. `force` (bool, False by default): 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): Must be one of "bil", "bip", or "bsq". This keyword supercedes the value of "interleave" in the metadata argument, if given. If no interleave is specified (via keyword or `metadata`), "bip" is assumed. `shape` (tuple of integers): Specifies the number of rows, columns, and bands in the image. This keyword should be either of the form (R, C, B) or (R, C), where R, C, and B specify the number or rows, columns, and bands, respectively. If B is omitted, the number of bands is assumed to be one. If this keyword is given, its values supercede the values of "bands", "lines", and "samples" if they are present in the `metadata` argument. `offset` (integer, default 0): The offset (in bytes) of image data from the beginning of the file. This value supercedes the value of "header offset" in the metadata argument (if given). Returns: `SpyFile` object: To access a `numpy.memmap` for the returned `SpyFile` object, call the `open_memmap` method of the returned object. Examples: Creating a new image from metadata:: >>> md = {'lines': 30, 'samples': 40, 'bands': 50, 'data type': 12} >>> img = envi.create_image('new_image.hdr', md) Creating a new image via keywords:: >>> img = envi.create_image('new_image2.hdr', shape=(30, 40, 50), dtype=np.uint16) Writing to the new image using a memmap interface:: >>> # Set all band values for a single pixel to 100. >>> mm = img.open_memmap(writable=True) >>> mm[30, 30] = 100 ''' from exceptions import NotImplementedError, TypeError import numpy as np import os import spectral force = kwargs.get('force', False) img_ext = kwargs.get('ext', '.img') memmap_mode = kwargs.get('memmap_mode', 'w+') (hdr_file, img_file) = check_new_filename(hdr_file, img_ext, force) default_metadata = {'header offset': 0, 'interleave': 'bip'} if metadata is None: metadata = default_metadata else: default_metadata.update(metadata) metadata = default_metadata # Keyword args supercede metadata dict if 'shape' in kwargs: shape = kwargs['shape'] metadata['lines'] = shape[0] metadata['samples'] = shape[1] if len(shape) == 3: metadata['bands'] = shape[2] else: metadata['bands'] = 1 if 'offset' in kwargs: metadata['offset'] = kwargs['offset'] if 'dtype' in kwargs: metadata['data type'] = dtype_to_envi[np.dtype(kwargs['dtype']).char] metadata['byte order'] = spectral.byte_order # Verify minimal set of parameters have been provided if 'lines' not in metadata: raise Exception('Number of image rows is not defined.') elif 'samples' not in metadata: raise Exception('Number of image columns is not defined.') elif 'bands' not in metadata: raise Exception('Number of image bands is not defined.') elif 'samples' not in metadata: raise Exception('Number of image columns is not defined.') elif 'data type' not in metadata: raise Exception('Image data type is not defined.') params = gen_params(metadata) dt = np.dtype(params.dtype).char params.filename = img_file is_library = False if metadata.get('file type') == 'ENVI Spectral Library': is_library = True raise NotImplementedError('ENVI Spectral Library cannot be created ') # Create the appropriate object type -> the memmap (=image) will be # created on disk inter = metadata["interleave"] (R, C, B) = (params.nrows, params.ncols, params.nbands) if inter.lower() not in ['bil', 'bip', 'bsq']: raise ValueError('Invalid interleave specified: %s.' % str(inter)) if inter.lower() == 'bil': from spectral.io.bilfile import BilFile memmap = np.memmap(img_file, dtype=dt, mode=memmap_mode, offset=params.offset, shape=(R, B, C)) img = BilFile(params, metadata) img._memmap = memmap elif inter.lower() == 'bip': from spectral.io.bipfile import BipFile memmap = np.memmap(img_file, dtype=dt, mode=memmap_mode, offset=params.offset, shape=(R, C, B)) img = BipFile(params, metadata) img._memmap = memmap else: from spectral.io.bsqfile import BsqFile memmap = np.memmap(img_file, dtype=dt, mode=memmap_mode, offset=params.offset, shape=(B, R, C)) img = BsqFile(params, metadata) img._memmap = memmap # Write the header file after the image to assure write success write_envi_header(hdr_file, metadata, is_library=is_library) return img
def create_image(hdr_file, metadata=None, **kwargs): ''' Creates an image file and ENVI header with a memmep array for write access. Arguments: `hdr_file` (str): Header file (with ".hdr" extension) name with path. `metadata` (dict): Metadata to specify the image file format. The following parameters (in ENVI header format) are required, if not specified via corresponding keyword arguments: "bands", "lines", "samples", and "data type". 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". If this keyword is given, it will override the "data type" parameter in the `metadata` argument. `force` (bool, False by default): 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): Must be one of "bil", "bip", or "bsq". This keyword supercedes the value of "interleave" in the metadata argument, if given. If no interleave is specified (via keyword or `metadata`), "bip" is assumed. `shape` (tuple of integers): Specifies the number of rows, columns, and bands in the image. This keyword should be either of the form (R, C, B) or (R, C), where R, C, and B specify the number or rows, columns, and bands, respectively. If B is omitted, the number of bands is assumed to be one. If this keyword is given, its values supercede the values of "bands", "lines", and "samples" if they are present in the `metadata` argument. `offset` (integer, default 0): The offset (in bytes) of image data from the beginning of the file. This value supercedes the value of "header offset" in the metadata argument (if given). Returns: `SpyFile` object: To access a `numpy.memmap` for the returned `SpyFile` object, call the `open_memmap` method of the returned object. Examples: Creating a new image from metadata:: >>> md = {'lines': 30, 'samples': 40, 'bands': 50, 'data type': 12} >>> img = envi.create_image('new_image.hdr', md) Creating a new image via keywords:: >>> img = envi.create_image('new_image2.hdr', shape=(30, 40, 50), dtype=np.uint16) Writing to the new image using a memmap interface:: >>> # Set all band values for a single pixel to 100. >>> mm = img.open_memmap(writable=True) >>> mm[30, 30] = 100 ''' import numpy as np import os import spectral force = kwargs.get('force', False) img_ext = kwargs.get('ext', '.img') memmap_mode = kwargs.get('memmap_mode', 'w+') (hdr_file, img_file) = check_new_filename(hdr_file, img_ext, force) default_metadata = {'header offset': 0, 'interleave': 'bip'} if metadata is None: metadata = default_metadata else: default_metadata.update(metadata) metadata = default_metadata # Keyword args supercede metadata dict if 'shape' in kwargs: shape = kwargs['shape'] metadata['lines'] = shape[0] metadata['samples'] = shape[1] if len(shape) == 3: metadata['bands'] = shape[2] else: metadata['bands'] = 1 if 'offset' in kwargs: metadata['header offset'] = kwargs['offset'] if 'dtype' in kwargs: metadata['data type'] = dtype_to_envi[np.dtype(kwargs['dtype']).char] if 'interleave' in kwargs: metadata['interleave'] = kwargs['interleave'] metadata['byte order'] = spectral.byte_order # Verify minimal set of parameters have been provided if 'lines' not in metadata: raise EnviException('Number of image rows is not defined.') elif 'samples' not in metadata: raise EnviException('Number of image columns is not defined.') elif 'bands' not in metadata: raise EnviException('Number of image bands is not defined.') elif 'samples' not in metadata: raise EnviException('Number of image columns is not defined.') elif 'data type' not in metadata: raise EnviException('Image data type is not defined.') params = gen_params(metadata) dt = np.dtype(params.dtype).char _validate_dtype(dt) params.filename = img_file is_library = False if metadata.get('file type') == 'ENVI Spectral Library': is_library = True raise NotImplementedError('ENVI Spectral Library cannot be created ') # Create the appropriate object type -> the memmap (=image) will be # created on disk inter = metadata["interleave"] (R, C, B) = (params.nrows, params.ncols, params.nbands) if inter.lower() not in ['bil', 'bip', 'bsq']: raise ValueError('Invalid interleave specified: %s.' % str(inter)) if inter.lower() == 'bil': from spectral.io.bilfile import BilFile memmap = np.memmap(img_file, dtype=dt, mode=memmap_mode, offset=params.offset, shape=(R, B, C)) img = BilFile(params, metadata) img._memmap = memmap elif inter.lower() == 'bip': from spectral.io.bipfile import BipFile memmap = np.memmap(img_file, dtype=dt, mode=memmap_mode, offset=params.offset, shape=(R, C, B)) img = BipFile(params, metadata) img._memmap = memmap else: from spectral.io.bsqfile import BsqFile memmap = np.memmap(img_file, dtype=dt, mode=memmap_mode, offset=params.offset, shape=(B, R, C)) img = BsqFile(params, metadata) img._memmap = memmap # Write the header file after the image to assure write success write_envi_header(hdr_file, metadata, is_library=is_library) return img