Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix persistence of more image adjustment settings: brightness, contrast, and opacity #79

Merged
merged 3 commits into from
Sep 22, 2021
Merged
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
71 changes: 58 additions & 13 deletions magmap/gui/plot_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,21 +377,29 @@ def show_overview(self):
self.hline = None
self.vline = None

# prep 2D image from main image, assumed to be an intensity image
# prep 2D image from main image, assumed to be an intensity image,
# with settings for each channel within this main image
imgs2d = [self._get_img2d(0, self.img3d, self.max_intens_proj)]
self._channels = [config.channel]
cmaps = [config.cmaps]
alphas = [config.alphas[0]]
shapes = [self._img3d_shapes[0][1:3]]
vmaxs = [None]
vmins = [None]
brightnesses = [None]
contrasts = [None]
if self._plot_ax_imgs:
# use vmin/vmax from norm values in previously displayed images
# if available; None specifies auto-scaling
vmaxs[0] = [p.vmax if p.vmax is None else p.ax_img.norm.vmax
for p in self._plot_ax_imgs[0]]
vmins[0] = [p.vmin if p.vmin is None else p.ax_img.norm.vmin
for p in self._plot_ax_imgs[0]]

# use opacity, brightness, anc contrast from prior images
alphas[0] = [p.ax_img.get_alpha() for p in self._plot_ax_imgs[0]]
brightnesses[0] = [p.brightness for p in self._plot_ax_imgs[0]]
contrasts[0] = [p.contrast for p in self._plot_ax_imgs[0]]

if self.img3d_labels is not None:
# prep labels with discrete colormap and prior alpha if available
Expand Down Expand Up @@ -461,7 +469,8 @@ def show_overview(self):
if self.scale_bar:
plot_support.add_scale_bar(self.axes, self._downsample[0])

# store displayed images in the PlotAxImg container class
# store displayed images in the PlotAxImg container class and update
# displayed brightness/contrast
if len(ax_imgs) > 1: self._ax_img_labels = ax_imgs[1][0]
self._plot_ax_imgs = []
for i, imgs in enumerate(ax_imgs):
Expand All @@ -473,6 +482,11 @@ def show_overview(self):
# norm, which holds the values used for the displayed image
plot_ax_img.vmin = libmag.get_if_within(vmins[i], j)
plot_ax_img.vmax = libmag.get_if_within(vmaxs[i], j)

# set brightness/contrast
self.change_brightness_contrast(
plot_ax_img, libmag.get_if_within(brightnesses[i], j),
libmag.get_if_within(contrasts[i], j))
plot_ax_imgs.append(plot_ax_img)
self._plot_ax_imgs.append(plot_ax_imgs)

Expand Down Expand Up @@ -630,7 +644,45 @@ def get_displayed_img(self, imgi, chl=None):
"""
return self.get_plot_ax_img(
self._plot_ax_imgs, imgi, self._channels, chl)


@staticmethod
def change_brightness_contrast(
plot_ax_img: PlotAxImg, brightness: Optional[float],
contrast: Optional[float]):
"""Change image brightness and contrast.

All changes are made relative to the original image, so both
brightness and contrast should be given together. For example, if
brightness is changed, and later contrast is changed, the contrast
change will wipe out the brightness change unless the brightness
value is given again.

Args:
plot_ax_img: Axes image storage instance.
brightness: Brightness value, centered on 0. Can be None to
ignore brightness changes.
contrast: Contrast value, centered on 1. Can be None to
ignore contrast changes.

"""
# get the array for the currently displayed image, which adjusts
# dynamically to array changes
data = plot_ax_img.ax_img.get_array()
info = libmag.get_dtype_info(data)
img = plot_ax_img.img

if brightness is not None:
# shift original image array by brightness
img = np.clip(plot_ax_img.img + brightness, info.min, info.max)
data[:] = img
plot_ax_img.brightness = brightness

if contrast is not None:
# stretch original image array by contrast
img = np.clip(img * contrast, info.min, info.max)
data[:] = img
plot_ax_img.contrast = contrast

@staticmethod
def update_plot_ax_img_display(plot_ax_img, minimum=np.nan, maximum=np.nan,
brightness=None, contrast=None, alpha=None):
Expand Down Expand Up @@ -685,16 +737,9 @@ def update_plot_ax_img_display(plot_ax_img, minimum=np.nan, maximum=np.nan,
else:
norm.vmax = norm.vmin
if brightness is not None or contrast is not None:
data = plot_ax_img.ax_img.get_array()
info = libmag.get_dtype_info(data)
if brightness is not None:
# shift original image array by brightness
data[:] = np.clip(
plot_ax_img.img + brightness, info.min, info.max)
if contrast is not None:
# stretch original image array by contrast
data[:] = np.clip(
plot_ax_img.img * contrast, info.min, info.max)
# adjust brightness and contrast together
PlotEditor.change_brightness_contrast(
plot_ax_img, brightness, contrast)
if alpha is not None:
# adjust opacity
plot_ax_img.ax_img.set_alpha(alpha)
Expand Down
25 changes: 20 additions & 5 deletions magmap/gui/visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ class Visualization(HasTraits):
_labels_img_name = Str
_labels_img_names = Instance(TraitsList)

_labels_ref_path = File # labels ontology reference path
_labels_ref_path = Str # labels ontology reference path
_labels_ref_btn = Button("Browse") # button to select ref file
_reload_btn = Button("Reload") # button to reload images

# ROI selection
Expand Down Expand Up @@ -494,8 +495,8 @@ class Visualization(HasTraits):
editor=CheckListEditor(
name="object._labels_img_names.selections",
format_func=lambda x: x)),
Item("_labels_ref_path", label="Reference", style="simple",
editor=FileEditor(entries=10, allow_dir=False)),
Item("_labels_ref_path", label="Reference", style="simple"),
Item("_labels_ref_btn", show_label=False),
),
label="Registered Images",
),
Expand Down Expand Up @@ -1121,11 +1122,15 @@ def _adjust_img_max_auto(self):

@on_trait_change("_imgadj_brightness")
def _adjust_img_brightness(self):
self._adjust_displayed_imgs(brightness=self._imgadj_brightness)
# include contrast to restore its value while adjusting the original img
self._adjust_displayed_imgs(
brightness=self._imgadj_brightness, contrast=self._imgadj_contrast)

@on_trait_change("_imgadj_contrast")
def _adjust_img_contrast(self):
self._adjust_displayed_imgs(contrast=self._imgadj_contrast)
# include brightness to restore its value while adjusting the orig img
self._adjust_displayed_imgs(
brightness=self._imgadj_brightness, contrast=self._imgadj_contrast)

@on_trait_change("_imgadj_alpha")
def _adjust_img_alpha(self):
Expand Down Expand Up @@ -1797,6 +1802,16 @@ def _reload_images(self):
# re-setup image
self.update_filename(self._filename, reset=False)

@on_trait_change("_labels_ref_btn")
def _labels_ref_path_updated(self):
"""Open a Pyface file dialog with path set to current image directory.
"""
open_dialog = FileDialog(
action="open", default_path=os.path.dirname(self._filename))
if open_dialog.open() == OK:
# get user selected path
self._labels_ref_path = open_dialog.path

@on_trait_change("_channel")
def update_channel(self):
"""Update the selected channel, resetting the current state to
Expand Down