Пример #1
0
def as_vtkimagedata(x, ndim=None):
    """Convert **x** to a vtkImageData.

    **x** can be any of the following:

    - A vtkImageData.
    - A 2D or 3D numpy array.
    - A file or filename to be read.
    - A Pillow image.

    Some VTK methods require a greyscale image. Using ``ndim=2`` will convert to
    greyscale.

    """
    assert (ndim is None) or (2 <= ndim <= 3)

    # From file.
    if nuts_and_bolts.isinstance_PathLike(x):
        x = str(x)
    if nuts_and_bolts.isinstance_PathLike(x, allow_buffers=True):
        try:
            from matplotlib.pylab import imread
            x = imread(x)
        except Exception:
            x = read(x)

    # From PILLOW.
    if nuts_and_bolts.isinstance_no_import(x, "PIL.Image", "Image"):
        x = np.array(x)

    # From array.
    if isinstance(x, np.ndarray):
        if x.ndim == 2 and ndim == 3:
            x = x[:, :, np.newaxis]
        elif x.ndim == 3 and ndim == 2:
            x = x.mean(-1).astype(x.dtype)
        x = vtkimagedata_from_array(x)

    # From vtk.
    if isinstance(x, vtk.vtkImageData):
        return x

    raise TypeError("Unable to convert type {} to vtkImageData".format(
        type(x)))
Пример #2
0
def write(arr, path, format=None, quality=95):
    """Write an image from a file using one of VTK's ``vtkFormatWriter`` classes
    where ``Format`` is replaced by JPEG or PNG.

    :param arr: **arr** can be a `vtkImageData`_ or a numpy array.
    :type arr: np.ndarray

    :param path: File path to write to.
    :type path: str, os.Pathlike, io.BytesIO,

    :param format: Image format extension (e.g. jpg), not needed if format can be determined from **path**, defaults to ``None``.
    :type format: str, optional

    :param quality: Lossy compression quality, only applicable to JPEGs, defaults to 95.
    :type quality: int from 0 to 100, optional

    :return: The raw image binary if ``path is None``, ``NotImplemented`` if the filetype is unknown. Otherwise no return value.
    :rtype: bytes

    See :meth:`read` for more information.

    .. note::

        BytesIO and raw bytes functionality is new in vtkplotlib >= 1.3.0.
        Older versions are hardcoded to write to disk and therefore **path**
        must be a filename and not a BytesIO or similar pseudo file object.

    """
    format = _normalise_format(path, format)
    try:
        Writer = getattr(vtk, "vtk{}Writer".format(format))
    except AttributeError:
        return NotImplemented
    im_data = as_vtkimagedata(arr)
    im_data.Modified()

    writer = Writer()
    writer.SetInputDataObject(im_data)

    if Writer is vtk.vtkJPEGWriter:
        writer.SetQuality(quality)

    if nuts_and_bolts.isinstance_PathLike(path):
        with PathHandler(path, "w") as path_handler:
            writer.SetFileName(path_handler.access_path)
            writer.Update()
            writer.Write()
        return
    writer.WriteToMemoryOn()
    writer.Update()
    writer.Write()
    binary = vtk_to_numpy(writer.GetResult()).tobytes()

    if path is None:
        return binary
    path.write(binary)
Пример #3
0
    def __init__(self, array, interpolate=False):
        from vtkplotlib.nuts_and_bolts import isinstance_PathLike
        if isinstance_PathLike(array):
            array = str(array)
        if isinstance(array, str):
            path = array
            from vtkplotlib.image_io import read
            array = read(path)
            if array is NotImplemented:
                try:
                    from matplotlib.pylab import imread
                    array = imread(path)
                except Exception as ex:
                    _future_utils.raise_from(
                        NotImplementedError(
                            "Could not find a suitable VTKImageReader for \"{}\" "
                            "and matplotlib's search failed with the following:"
                        ), ex)

            array = np.swapaxes(array, 0, 1)[:, ::-1]
        from vtkplotlib.nuts_and_bolts import isinstance_no_import
        if isinstance_no_import(array, "PIL.Image", "Image"):
            array = np.array(array)
            array = np.swapaxes(array, 0, 1)[:, ::-1]

        ex = lambda x: TypeError("`array` must be an np.ndarray with shape"
                                 " (m, n, 3) or (m, n, 4). Got {} {}".format(
                                     x, repr(array)))
        if not isinstance(array, np.ndarray):
            raise ex(type(array))
        if len(array.shape) != 3:
            raise ex(array.shape)
        if not (3 <= array.shape[2] <= 4):
            raise ex(array.shape)

        if array.dtype.kind in "ui":
            array = array / ((1 << (8 * array.dtype.itemsize)) - 1)

        self.array = array
        self.interpolate = interpolate

        self.shape = np.array(self.array.shape[:2])
Пример #4
0
def as_qicon(obj):
    pixmap = None

    if isinstance(obj, QtGui.QIcon):
        return obj

    from vtkplotlib.nuts_and_bolts import isinstance_PathLike, isinstance_no_import
    if isinstance_PathLike(obj):
        pixmap = QtGui.QPixmap(str(obj))

    if isinstance_no_import(obj, "PIL.Image", "Image"):
        pixmap = obj.toqpixmap()

    if pixmap is not None:
        return QtGui.QIcon(pixmap)
    else:
        raise TypeError("""Icons can be created from any of the following:
    - str
    - os.Pathlike
    - QtGui.QIcon
    - PIL.Image.Image
Received {}""".format(type(obj)))
Пример #5
0
def read(path, raw_bytes=None, format=None, convert_to_array=True):
    """Read an image from a file using one of VTK's ``vtkFormatReader`` classes
    where ``Format`` is replaced by JPEG, PNG, BMP or TIFF.

    :param path: Filename or file handle or ``None`` if using the **raw_bytes** argument.
    :type path: str, os.PathLike, io.BytesIO

    :param raw_bytes: Image compressed binary data, defaults to ``None``.
    :type raw_bytes: bytes, optional

    :param format: Image format extension (e.g. jpg), not needed if format can be determined from **path**, defaults to ``None``.
    :type format: str, optional

    :param convert_to_array: If true, convert to numpy, otherwise leave as vtkImageData, defaults to ``True``.
    :type convert_to_array: bool, optional

    :return: Read image.
    :rtype: np.ndarray or `vtkImageData`_

    The file format can be determined automatically from the **path** suffix or the beginning
    of **raw_bytes**. **format** can be any of JPEG, PNG, TIFF, BMP. It is case
    insensitive, tolerant to preceding '.'s e.g. ``format=".jpg"`` and
    understands the aliases JPG \u21d4 JPEG and TIF \u21d4 TIFF.

    The following demonstrates how to use pseudo file objects to avoid temporary
    files when reading an image from the web.

    .. code-block:: python

        import vtkplotlib as vpl

        # Link you're image url here
        url = "https://raw.githubusercontent.com/bwoodsend/vtkplotlib/master/vtkplotlib/data/icons/Right.jpg"

        # You can make the url request with either:
        from urllib import request
        raw_bytes = request.urlopen(url).read()

        # Or if you have the more modern requests library installed:
        # import requests
        # raw_bytes = requests.get(url).content

        # Pass the bytes to :meth:`read` using:
        image = vpl.image_io.read(path=None, raw_bytes=raw_bytes)

        # Visualize using matplotlib.
        from matplotlib import pyplot
        pyplot.imshow(image)
        pyplot.show()


    .. warning::

        Some formats only support reading from disk. See
        ``vtkplotlib.image_io.BUFFERABLE_FORMAT_MODES`` or for which these are.

    .. note::

        BytesIO and raw bytes functionality is new in vtkplotlib >= 1.3.0.
        Older versions are hardcoded to write to disk and therefore **path**
        must be a filename and not a BytesIO or similar pseudo file object.

    .. note::

        There is a bug in VTK==9.0.0


    """
    if isinstance(raw_bytes, bool):
        raise TypeError(
            "The arguments for this method have changed. If you meant to set the `convert_to_array` argument, please treat it as keyword only. i.e ``convert_to_array={}``"
            .format(raw_bytes))

    if (path is None) == (raw_bytes is None):
        raise TypeError(
            "Exactly one of `path` and `raw_bytes` should be specified.")

    if isinstance(path, io.IOBase):
        raw_bytes = path.read()

    format = _normalise_format(path, format, raw_bytes)
    try:
        Reader = getattr(vtk, "vtk{}Reader".format(format))
    except AttributeError:
        return NotImplemented

    reader = Reader()

    with VTKErrorRaiser(reader):

        if nuts_and_bolts.isinstance_PathLike(path):
            with PathHandler(path) as path_handler:
                reader.SetFileName(path_handler.access_path)
                reader.Update()
        else:
            if raw_bytes is not None:
                bytes_arr = np.frombuffer(raw_bytes, dtype=np.uint8)
                vtk_bytes = numpy_to_vtk(bytes_arr)
                vtk_bytes._numpy_ref = bytes_arr
                reader.SetMemoryBuffer(vtk_bytes)
                reader.SetMemoryBufferLength(len(bytes_arr))
                reader.Update()

        im_data = reader.GetOutput()

    if format == "TIFF" and VTK_VERSION_INFO >= (9, 0, 0):
        # There's a bug in VTK 9 that reads TIFFs upside-down.
        im_data = vtkimagedata_to_array(im_data)[::-1]
        return im_data if convert_to_array else vtkimagedata_from_array(im_data)

    if convert_to_array:
        return vtkimagedata_to_array(im_data)

    return im_data