Esempio n. 1
0
def load_dataset_vsimem(data_element: DataElement) -> "gdal.Dataset":
    """
    Load GDAL dataset from element by writing its bytes to a virtual file
    and loading a dataset from that virtual file.

    Requires GDAL major version 2 or greater.

    :param smqtk.representation.DataElement data_element:
        Element to load dataset from.

    :return: GDAL Dataset
    :rtype: gdal.Dataset

    """
    # Unguarded next() call is OK in this case because the generator returned
    # by ``_get_candidate_names()`` does not terminate.
    # noinspection PyProtectedMember
    get_candidate_names = tempfile._get_candidate_names  # type: ignore
    tmp_vsimem_path = '/vsimem/{}'.format(
        next(get_candidate_names())  # lgtm[py/unguarded-next-in-generator]
    )
    gdal.FileFromMemBuffer(tmp_vsimem_path, data_element.get_bytes())
    try:
        yield gdal.Open(tmp_vsimem_path)
    finally:
        rc = gdal.Unlink(tmp_vsimem_path)
        if rc != 0:
            raise RuntimeError("Failed to gdal.Unlink virtual file '{}' "
                               "containing bytes from {}.".format(
                                   tmp_vsimem_path, data_element))
Esempio n. 2
0
def is_loadable_image(data_element: DataElement) -> bool:
    """
    Determine if an image is able to be loaded by PIL.

    :param data_element: A data element to check
    :type data_element: DataElement

    :return: Whether or not the image is loadable
    :rtype: bool

    Example:
    >>>

    """
    log = logging.getLogger(__name__)

    try:
        PIL.Image.open(io.BytesIO(data_element.get_bytes()))
        return True
    except IOError as ex:
        # noinspection PyProtectedMember
        log.debug(
            "Failed to convert '%s' bytes into an image "
            "(error: %s). Skipping", data_element, str(ex))
        return False
Esempio n. 3
0
    def _load_as_matrix(
        self, data_element: DataElement,
            pixel_crop: Optional[AxisAlignedBoundingBox] = None) \
            -> numpy.ndarray:
        """
        Internal method to be implemented that attempts loading an image
        from the given data element and returning it as an image matrix.

        Pre-conditions:
            - ``pixel_crop`` has a non-zero volume and is composed of integer
              types.

        :param smqtk.representation.DataElement data_element:
            DataElement to load image data from.
        :param None|smqtk.representation.AxisAlignedBoundingBox pixel_crop:
            Optional pixel crop region to load from the given data.  If this
            is provided it must represent a valid sub-region within the loaded
            image, otherwise a RuntimeError is raised.

        :raises RuntimeError: A crop region was specified but did not specify a
            valid sub-region of the image.

        :return: Numpy ndarray of the image data. Specific return format is
            implementation dependant.
        :rtype: numpy.ndarray

        """
        # We may have to add a mode where we use write_temp and load from that
        # if loading large images straight from bytes-in-memory is a problem
        # and that approach actually alleviates anything.

        # Catch and raise alternate IOError exception for readability.
        try:
            #: :type: PIL.Image.Image
            img = PIL.Image.open(BytesIO(data_element.get_bytes()))
        except IOError as ex:
            ex_str = str(ex)
            if 'cannot identify image file' in ex_str:
                raise IOError("Failed to identify image from bytes provided "
                              "by {}".format(data_element))
            else:
                # pass through other exceptions
                raise

        if pixel_crop:
            if not crop_in_bounds(pixel_crop, *img.size):
                raise RuntimeError("Crop provided not within input image. "
                                   "Image shape: {}, crop: {}".format(
                                       img.size, pixel_crop))
            img = img.crop(pixel_crop.min_vertex.tolist() +
                           pixel_crop.max_vertex.tolist())

        # If the loaded image is not already the optionally provided
        # explicit mode, convert it.
        if self._explicit_mode and img.mode != self._explicit_mode:
            img = img.convert(mode=self._explicit_mode)

        # noinspection PyTypeChecker
        return numpy.asarray(img)