Exemplo n.º 1
0
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
Exemplo n.º 2
0
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