Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/examples/_valid_examples.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ files = [
"viz_textblock.py",
"viz_sliders.py",
"viz_button.py",
"viz_image_container.py",
]

[animation]
Expand Down
51 changes: 51 additions & 0 deletions docs/examples/viz_image_container.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
==================
ImageContainer2D
==================
"""

##############################################################################
# First, a bunch of imports

import numpy as np

from fury.ui import ImageContainer2D
from fury.window import (
Scene,
ShowManager,
)

##############################################################################
# Creating a Scene

scene = Scene()

##############################################################################
# Creating a sample image

img = np.random.randint(0, 255, (200, 200), dtype=np.uint8)

##############################################################################
# Creating the ImageContainer2D UI element

image_ui = ImageContainer2D(
img,
position=(250, 250),
size=(200, 200),
)

scene.add(image_ui)

###############################################################################
# Starting the ShowManager

if __name__ == "__main__":
current_size = (700, 700)

show_manager = ShowManager(
scene=scene,
size=current_size,
title="FURY 2.0: ImageContainer2D Example",
)

show_manager.start()
4 changes: 2 additions & 2 deletions fury/ui/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ __all__ = [
"Panel2D",
# "TabPanel2D",
# "TabUI",
# "ImageContainer2D",
"ImageContainer2D",
# "GridUI",
"Rectangle2D",
"Disk2D",
Expand Down Expand Up @@ -45,7 +45,7 @@ __all__ = [
# from .containers import GridUI, ImageContainer2D, Panel2D, TabPanel2D, TabUI
# from .core import UI, Button2D, Disk2D, Rectangle2D, TextBlock2D

from .containers import Panel2D
from .containers import ImageContainer2D, Panel2D
from .context import UIContext
from .core import UI, Anchor, Disk2D, Rectangle2D, TextBlock2D
from .elements import LineSlider2D, TextButton2D, TexturedButton2D
Expand Down
193 changes: 46 additions & 147 deletions fury/ui/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import numpy as np

from fury import io
from fury.actor import image as image_actor
from fury.ui.core import UI, Anchor, Rectangle2D


Expand Down Expand Up @@ -979,159 +981,56 @@ def border_width(self, side_width):
# i_ren.force_render()


# # class ImageContainer2D(UI):
# # """A 2D container to hold an image.
class ImageContainer2D(UI):
"""A 2D UI component to display images.

# # Currently Supports:
# # - png and jpg/jpeg images

# # Attributes
# # ----------
# # size: (float, float)
# # Image size (width, height) in pixels.
# # img : ImageData
# # The image loaded from the specified path.

# # """

# # @warn_on_args_to_kwargs()
# # def __init__(self, img_path, *, position=(0, 0), size=(100, 100)):
# # """Init class instance.

# # Parameters
# # ----------
# # img_path : string
# # URL or local path of the image
# # position : (float, float), optional
# # Absolute coordinates (x, y) of the lower-left corner of the image.
# # size : (int, int), optional
# # Width and height in pixels of the image.

# # """
# # super(ImageContainer2D, self).__init__(position=position)
# # self.img = load_image(img_path, as_vtktype=True)
# # self.set_img(self.img)
# # self.resize(size)

# # def _get_size(self):
# # lower_left_corner = self.texture_points.GetPoint(0)
# # upper_right_corner = self.texture_points.GetPoint(2)
# # size = np.array(upper_right_corner) - np.array(lower_left_corner)
# # return abs(size[:2])

# # def _setup(self):
# # """Setup this UI Component.

# # Return an image as a 2D actor with a specific position.

# # Returns
# # -------
# # :class:`vtkTexturedActor2D`

# # """
# # self.texture_polydata = PolyData()
# # self.texture_points = Points()
# # self.texture_points.SetNumberOfPoints(4)

# # polys = CellArray()
# # polys.InsertNextCell(4)
# # polys.InsertCellPoint(0)
# # polys.InsertCellPoint(1)
# # polys.InsertCellPoint(2)
# # polys.InsertCellPoint(3)
# # self.texture_polydata.SetPolys(polys)

# # tc = FloatArray()
# # tc.SetNumberOfComponents(2)
# # tc.SetNumberOfTuples(4)
# # tc.InsertComponent(0, 0, 0.0)
# # tc.InsertComponent(0, 1, 0.0)
# # tc.InsertComponent(1, 0, 1.0)
# # tc.InsertComponent(1, 1, 0.0)
# # tc.InsertComponent(2, 0, 1.0)
# # tc.InsertComponent(2, 1, 1.0)
# # tc.InsertComponent(3, 0, 0.0)
# # tc.InsertComponent(3, 1, 1.0)
# # self.texture_polydata.GetPointData().SetTCoords(tc)

# # texture_mapper = PolyDataMapper2D()
# # texture_mapper = set_input(texture_mapper, self.texture_polydata)

# # image = TexturedActor2D()
# # image.SetMapper(texture_mapper)

# # self.texture = Texture()
# # image.SetTexture(self.texture)

# # image_property = Property2D()
# # image_property.SetOpacity(1.0)
# # image.SetProperty(image_property)
# # self.actor = image

# # # Add default events listener to the VTK actor.
# # self.handle_events(self.actor)

# # def _get_actors(self):
# # """Return the actors that compose this UI component."""
# # return [self.actor]

# # def _add_to_scene(self, scene):
# # """Add all subcomponents or VTK props that compose this UI component.

# # Parameters
# # ----------
# # scene : scene

# # """
# # scene.add(self.actor)

# # def resize(self, size):
# # """Resize the image.

# # Parameters
# # ----------
# # size : (float, float)
# # image size (width, height) in pixels.

# # """
# # # Update actor.
# # self.texture_points.SetPoint(0, 0, 0, 0.0)
# # self.texture_points.SetPoint(1, size[0], 0, 0.0)
# # self.texture_points.SetPoint(2, size[0], size[1], 0.0)
# # self.texture_points.SetPoint(3, 0, size[1], 0.0)
# # self.texture_polydata.SetPoints(self.texture_points)

# # def _set_position(self, coords):
# # """Set the lower-left corner position of this UI component.

# # Parameters
# # ----------
# # coords: (float, float)
# # Absolute pixel coordinates (x, y).

# # """
# # self.actor.SetPosition(*coords)

# # def scale(self, factor):
# # """Scale the image.
Parameters
----------
image_input : str or numpy.ndarray
Path to the image file or a numpy image array.
position : (float, float), optional
Absolute coordinates (x, y) of the lower-left corner of the image.
size : (float, float), optional
Scaling factor (width, height) in pixels.
"""

# # Parameters
# # ----------
# # factor : (float, float)
# # Scaling factor (width, height) in pixels.
def __init__(self, image_input, position=(0, 0), size=None):
if isinstance(image_input, str):
image = io.load_image(image_input)
elif isinstance(image_input, np.ndarray):
image = image_input
else:
raise TypeError(
"image_input must be a file path (str) or a NumPy array."
)
if image.ndim == 3:
image = image.mean(axis=2).astype(np.uint8)
if image.ndim != 2:
raise ValueError("Only 2D images are supported.")
if size is not None and len(size) != 2:
raise ValueError("size must be (width, height)")
self._img = image
self._size = size
self._image_actor = image_actor(self._img)
super().__init__(position=position)

# # """
# # self.resize(self.size * factor)
def _setup(self):
self._actors = [self._image_actor]

# # def set_img(self, img):
# # """Modify the image used by the vtkTexturedActor2D.
def _get_actors(self):
return [self._image_actor]

# # Parameters
# # ----------
# # img : imageData
def _get_size(self):
if self._size is not None:
return self._size
return self._img.shape[1], self._img.shape[0]

# # """
# # self.texture = set_input(self.texture, img)
def _update_actors_position(self):
self.set_actor_position(
self._image_actor,
self.get_position(),
self.z_order,
)


# # class GridUI(UI):
Expand Down
32 changes: 32 additions & 0 deletions fury/ui/tests/test_containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from PIL import Image
import numpy as np
import numpy.testing as npt
import pytest

from fury import ui, window

Expand Down Expand Up @@ -179,6 +180,37 @@ def test_panel2d_visual_snapshot(
npt.assert_almost_equal(np.mean(arr_hidden[..., :3]), 0, decimal=0)


def test_image_container_creation():
"""Test ImageContainer2D creation with grayscale image."""
img = np.zeros((10, 10), dtype=np.uint8)
container = ui.ImageContainer2D(img)

assert container is not None
assert len(container.actors) == 1


def test_image_container_rgb():
"""Test that RGB images are converted to grayscale."""
img = np.zeros((10, 10, 3), dtype=np.uint8)
container = ui.ImageContainer2D(img)

assert container is not None


def test_image_container_size():
"""Test custom size parameter."""
img = np.zeros((10, 10), dtype=np.uint8)
container = ui.ImageContainer2D(img, size=(50, 50))

assert container._get_size() == (50, 50)


def test_image_container_invalid_input():
"""Test invalid input type raises TypeError."""
with pytest.raises(TypeError):
ui.ImageContainer2D(123)


# def setup_module():
# fetch_viz_icons()

Expand Down