Skip to content

Commit 8a18b7b

Browse files
committed
display vector images with 5D viewer
1 parent dd9a67b commit 8a18b7b

File tree

4 files changed

+94
-43
lines changed

4 files changed

+94
-43
lines changed

ImageM/+imagem/+actions/+image/ConvertVectorImageToRGB.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function run(obj, frame) %#ok<INUSL,INUSD>
4343
errordlg('Requires a vector image');
4444
return;
4545
end
46-
nc = channelNumber(img);
46+
nc = channelCount(img);
4747
if nc < 3
4848
errordlg('Requires at least three channels in image');
4949
return;

ImageM/+imagem/+gui/Image5DSliceViewer.m

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
% This class displas a side panel that allows to choose:
55
% * the current slice index (Z coordinate)
66
% * the current frame index (T coordinate)
7-
% * the current channel, or the way the hannel is displayed.
7+
% * the current channel, or the way the channels are displayed.
88
%
99
% Example
1010
% Image5DSliceViewer
@@ -28,9 +28,12 @@
2828
% The index of the visible slice (between 1 and TMax).
2929
FrameIndex;
3030

31-
% The XY slice to be displayed, as an instance of Image class.
32-
SliceImage;
31+
% The way to display vector images.
32+
% Default is to display the norm.
33+
VectorImageConverter = imagem.util.vectorImage.VectorImageNorm();
3334

35+
% The image to be displayed, as a 2D intensity or RGB Image.
36+
ImageToDisplay;
3437

3538
% Specify how to change the zoom when figure is resized.
3639
% Can be one of:
@@ -54,11 +57,11 @@
5457
% setup initial slice and frame indices
5558
obj.SliceIndex = ceil(size(obj.Doc.Image, 3) / 2);
5659
obj.FrameIndex = ceil(size(obj.Doc.Image, 5) / 2);
57-
58-
% setup default display options
59-
[mini, maxi] = imagem.gui.ImageUtils.computeDisplayRange(obj.Doc.Image);
60-
obj.DisplayRange = [mini maxi];
61-
60+
61+
% initialize the image to display
62+
updateImageToDisplay(obj);
63+
computeDefaultDisplayRange(obj);
64+
6265

6366
% computes a new handle index large enough not to collide with
6467
% common figure handles
@@ -134,6 +137,27 @@ function setupLayout(obj)
134137
'Parent', obj.Handles.HorzPanel, ...
135138
'Padding', 5);
136139

140+
141+
% setup widgets for vector images display
142+
vectorImage = 'off';
143+
if isVectorImage(img) && ~isColorImage(img)
144+
vectorImage = 'on';
145+
end
146+
obj.Handles.VectorImageConvertLabel = uicontrol(...
147+
'Parent', obj.Handles.DisplayOptionsPanel, ...
148+
'Style', 'text', ...
149+
'String', 'Vector Image Display', ...
150+
'Enable', vectorImage, ...
151+
'HorizontalAlignment', 'left');
152+
153+
obj.Handles.VectorImageConvertCombo = uicontrol('Style', 'popupmenu', ...
154+
'Parent', obj.Handles.DisplayOptionsPanel, ...
155+
'String', {'Norm', 'Max Channel', 'First Channel'}, ...
156+
'Value', 1, ...
157+
'Enable', vectorImage, ...
158+
'Callback', @obj.onVectorImageConvertChanged, ...
159+
'BackgroundColor', [1 1 1]);
160+
137161

138162
% setup widgets for slice index
139163
zmin = 1;
@@ -194,7 +218,7 @@ function setupLayout(obj)
194218
'Enable', 'off');
195219
end
196220

197-
obj.Handles.DisplayOptionsPanel.Heights = [30 20 30 20];
221+
obj.Handles.DisplayOptionsPanel.Heights = [30 20 30 20 30 20];
198222

199223
% vertical layout: image display and status bar
200224
mainPanel = uix.VBox('Parent', obj.Handles.HorzPanel, ...
@@ -257,7 +281,7 @@ function updateSliceIndex(obj, newIndex)
257281

258282
text = sprintf('Slice index (%d/%d)', newIndex, size(obj.Doc.Image, 3));
259283
set(obj.Handles.SliceIndexLabel, 'String', {'', text});
260-
% updateSliceImage(obj);
284+
% updateImageToDisplay(obj);
261285

262286
updateDisplay(obj);
263287
% set(obj.Handles.Image, 'CData', obj.Slice);
@@ -284,9 +308,9 @@ function updateFrameIndex(obj, newIndex)
284308
end
285309

286310

287-
function sliceImage = updateSliceImage(obj)
288-
% Recompute the slice image from image and slice+frame indices.
289-
311+
function sliceImage = updateImageToDisplay(obj)
312+
% Recompute the image to display from slice/frame/channel indices.
313+
290314
% current image is either the document image, or the preview image
291315
% if there is one
292316
img = obj.Doc.Image;
@@ -295,17 +319,22 @@ function updateFrameIndex(obj, newIndex)
295319
end
296320

297321
% extract the 2D image to display (can be color or channel)
298-
obj.SliceImage = slice(frame(img, obj.FrameIndex), obj.SliceIndex);
322+
obj.ImageToDisplay = slice(frame(img, obj.FrameIndex), obj.SliceIndex);
299323

300-
if strcmpi(obj.SliceImage.Type, 'vector')
301-
obj.SliceImage = norm(obj.SliceImage);
324+
if strcmpi(obj.ImageToDisplay.Type, 'vector')
325+
obj.ImageToDisplay = convert(obj.VectorImageConverter, obj.ImageToDisplay);
302326
end
303327

304328
if nargout > 0
305-
sliceImage = obj.SliceImage;
329+
sliceImage = obj.ImageToDisplay;
306330
end
307331
end
308332

333+
function computeDefaultDisplayRange(obj)
334+
% Compute default display range from image to display.
335+
[mini, maxi] = imagem.gui.ImageUtils.computeDisplayRange(obj.ImageToDisplay);
336+
obj.DisplayRange = [mini maxi];
337+
end
309338
end
310339

311340
%% Methods for Display
@@ -325,10 +354,11 @@ function updateDisplay(obj)
325354
end
326355

327356
img = obj.Doc.Image;
328-
sliceImage = updateSliceImage(obj);
357+
sliceImage = updateImageToDisplay(obj);
329358

330359
% compute display data
331-
cdata = imagem.gui.ImageUtils.computeDisplayImage(sliceImage, obj.Doc.ColorMap, obj.Doc.BackgroundColor);
360+
cdata = imagem.gui.ImageUtils.computeDisplayImage(sliceImage, ...
361+
obj.Doc.ColorMap, obj.DisplayRange, obj.Doc.BackgroundColor);
332362

333363
% changes current display data
334364
api = iptgetapi(obj.Handles.ScrollPanel);
@@ -354,7 +384,7 @@ function updateDisplay(obj)
354384
% api.setVisibleLocation(loc);
355385

356386
% eventually adjust displayrange (for the whole image)
357-
if isGrayscaleImage(img) || isIntensityImage(img) || isVectorImage(img)
387+
if isGrayscaleImage(sliceImage) || isIntensityImage(sliceImage)
358388
mini = obj.DisplayRange(1);
359389
maxi = obj.DisplayRange(2);
360390
set(obj.Handles.ImageAxis, 'CLim', [mini maxi]);
@@ -377,7 +407,7 @@ function updateDisplay(obj)
377407
% % display each shape stored in document
378408
% drawShapes(obj);
379409
end
380-
410+
381411
function copySettings(obj, that)
382412
% copy display settings from another viewer
383413
obj.DisplayRange = that.DisplayRange;
@@ -431,6 +461,30 @@ function setZoomMode(obj, mode)
431461

432462
%% GUI Widgets listeners
433463
methods
464+
function onVectorImageConvertChanged(obj, hObject, eventdata) %#ok<*INUSD>
465+
if isempty(obj.Doc.Image)
466+
return;
467+
end
468+
469+
index = round(get(hObject, 'Value'));
470+
switch index
471+
case 1
472+
obj.VectorImageConverter = imagem.util.vectorImage.VectorImageNorm();
473+
case 2
474+
obj.VectorImageConverter = imagem.util.vectorImage.VectorImageMaxChannel();
475+
case 3
476+
obj.VectorImageConverter = imagem.util.vectorImage.VectorImageSingleChannel(1);
477+
otherwise
478+
error('Can not interpret value');
479+
end
480+
481+
% recompute image to display, to be able to update display ranges
482+
updateImageToDisplay(obj);
483+
computeDefaultDisplayRange(obj);
484+
485+
updateDisplay(obj);
486+
end
487+
434488
function onSliceSliderChanged(obj, hObject, eventdata) %#ok<*INUSD>
435489
if isempty(obj.Doc.Image)
436490
return;

ImageM/+imagem/+gui/ImagemGUI.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,19 @@
137137

138138
% creates a display for the new image depending on image dimension
139139
if size(img, 5) > 1
140+
% in case of time-lapse images, always use 5D viewer
140141
frame = imagem.gui.Image5DSliceViewer(obj, doc);
142+
143+
elseif size(img, 4) > 3
144+
% if more than 3 channels, switch to 5D viewer
145+
frame = imagem.gui.Image5DSliceViewer(obj, doc);
146+
141147
elseif size(img, 3) > 1
148+
% more simple viewer for 4D scalar/color images
142149
frame = imagem.gui.Image3DSliceViewer(obj, doc);
150+
143151
else
152+
% default viewer for 2D images
144153
frame = imagem.gui.PlanarImageViewer(obj, doc);
145154
end
146155
addView(doc, frame);

ImageM/+imagem/+tools/PlotVectorImageChannels.m

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function select(obj) %#ok<*MANU>
6060
% configure axis
6161
ax = gca;
6262
hold(ax, 'on');
63-
set(ax, 'xlim', [0 channelNumber(img)+1]);
63+
set(ax, 'xlim', [0 channelCount(img)+1]);
6464
set(ax, 'ylim', displayRange);
6565
titleStr = 'Spectral Profile';
6666
if ~isempty(img.Name)
@@ -114,11 +114,17 @@ function deselect(obj)
114114
function onMouseButtonPressed(obj, hObject, eventdata) %#ok<INUSD>
115115

116116
pos = get(obj.Viewer.Handles.ImageAxis, 'CurrentPoint');
117-
obj.LastClickedPoint = pos(1,:);
117+
pos = pos(1, 1:2);
118+
if is3dImage(obj.Viewer.Doc.Image)
119+
pos = [pos obj.Viewer.SliceIndex];
120+
end
118121

122+
obj.LastClickedPoint = pos;
123+
119124
img = obj.Viewer.Doc.Image;
120125
% coord = round(pointToIndex(img, [pos(1, 1:2) obj.Viewer.SliceIndex]));
121-
coord = round(pointToIndex(img, [pos(1, 1:2) 1]));
126+
127+
coord = round(pointToIndex(img, pos));
122128
coord = coord(1:2);
123129

124130
% control on bounds of image
@@ -155,24 +161,6 @@ function onMouseButtonPressed(obj, hObject, eventdata) %#ok<INUSD>
155161
warning('Unknown channel display type');
156162
end
157163
end
158-
159-
% % add profile to axis user data
160-
% userdata = get(obj.Handles.CProfileAxis, 'userdata');
161-
% % if strcmp(get(obj.Handles.Figure, 'SelectionType'), 'normal')
162-
% % % replace profile list with current profile
163-
% % userdata.profiles = profile;
164-
% % delete(userdata.profileHandles);
165-
% h = plot(obj.Handles.CProfileAxis, profile, 'b');
166-
% % userdata.profileHandles = h;
167-
% % else
168-
% % % add the current profile to profile list
169-
% % userdata.profiles = [userdata.profiles profile];
170-
% % h = plot(obj.Handles.ZProfileAxis, profile, 'b');
171-
% % userdata.profileHandles = [userdata.profileHandles h];
172-
% % end
173-
%
174-
% set(obj.Handles.CProfileAxis, 'userdata', userdata);
175-
176164
end
177165

178166
function onMouseButtonReleased(obj, hObject, eventdata) %#ok<INUSD>

0 commit comments

Comments
 (0)