/*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2016 University of Dundee. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package org.openmicroscopy.shoola.agents.imviewer.view;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import omero.model.Length;
import omero.model.LengthI;
import omero.model.PlaneInfo;
import omero.model.enums.UnitsLength;
import omero.romio.PlaneDef;
import org.apache.commons.io.FilenameUtils;
import org.openmicroscopy.shoola.agents.events.iviewer.CopyRndSettings;
import org.openmicroscopy.shoola.agents.imviewer.AcquisitionDataLoader;
import org.openmicroscopy.shoola.agents.imviewer.BirdEyeLoader;
import org.openmicroscopy.shoola.agents.imviewer.ContainerLoader;
import org.openmicroscopy.shoola.agents.imviewer.DataLoader;
import org.openmicroscopy.shoola.agents.imviewer.ImViewerAgent;
import org.openmicroscopy.shoola.agents.imviewer.ImageDataLoader;
import org.openmicroscopy.shoola.agents.imviewer.ImageLoader;
import org.openmicroscopy.shoola.agents.imviewer.MeasurementsLoader;
import org.openmicroscopy.shoola.agents.imviewer.OverlaysRenderer;
import org.openmicroscopy.shoola.agents.imviewer.PlaneInfoLoader;
import org.openmicroscopy.shoola.agents.imviewer.ProjectionSaver;
import org.openmicroscopy.shoola.agents.imviewer.RenderingSettingsCreator;
import org.openmicroscopy.shoola.agents.imviewer.RenderingSettingsLoader;
import org.openmicroscopy.shoola.agents.imviewer.TileLoader;
import org.openmicroscopy.shoola.agents.imviewer.actions.ZoomAction;
import org.openmicroscopy.shoola.agents.imviewer.browser.Browser;
import org.openmicroscopy.shoola.agents.imviewer.browser.BrowserFactory;
import org.openmicroscopy.shoola.agents.imviewer.util.HistoryItem;
import org.openmicroscopy.shoola.agents.imviewer.util.player.ChannelPlayer;
import org.openmicroscopy.shoola.agents.imviewer.util.player.Player;
import org.openmicroscopy.shoola.agents.imviewer.util.proj.ProjectionRef;
import org.openmicroscopy.shoola.agents.metadata.rnd.Renderer;
import org.openmicroscopy.shoola.agents.metadata.view.MetadataViewer;
import org.openmicroscopy.shoola.agents.metadata.view.MetadataViewerFactory;
import org.openmicroscopy.shoola.agents.util.EditorUtil;
import org.openmicroscopy.shoola.env.LookupNames;
import org.openmicroscopy.shoola.env.data.OmeroImageService;
import org.openmicroscopy.shoola.env.data.model.ProjectionParam;
import omero.gateway.SecurityContext;
import omero.gateway.exception.DSOutOfServiceException;
import omero.gateway.exception.RenderingServiceException;
import omero.gateway.model.TableResult;
import org.openmicroscopy.shoola.env.event.EventBus;
import org.openmicroscopy.shoola.env.rnd.RenderingControl;
import org.openmicroscopy.shoola.env.rnd.RndProxyDef;
import org.openmicroscopy.shoola.env.rnd.data.Region;
import org.openmicroscopy.shoola.env.rnd.data.ResolutionLevel;
import org.openmicroscopy.shoola.env.rnd.data.Tile;
import org.openmicroscopy.shoola.util.CommonsLangUtils;
import org.openmicroscopy.shoola.util.file.modulo.ModuloInfo;
import org.openmicroscopy.shoola.util.image.geom.Factory;
import org.openmicroscopy.shoola.util.ui.UIUtilities;
import omero.gateway.model.ChannelData;
import omero.gateway.model.DataObject;
import omero.gateway.model.ExperimenterData;
import omero.gateway.model.GroupData;
import omero.gateway.model.ImageData;
import omero.gateway.model.ObjectiveData;
import omero.gateway.model.PixelsData;
import omero.gateway.model.WellData;
import omero.gateway.model.WellSampleData;
/**
* The Model component in the <code>ImViewer</code> MVC triad.
* This class tracks the <code>ImViewer</code>'s state and knows how to
* initiate data retrievals. It also knows how to store and manipulate
* the results. This class provides a suitable data loader.
* The {@link ImViewerComponent} intercepts the results of data loadings, feeds
* them back to this class and fires state transitions as appropriate.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author Andrea Falconi
* <a href="mailto:a.falconi@dundee.ac.uk">a.falconi@dundee.ac.uk</a>
* @author Donald MacDonald
* <a href="mailto:donald@lifesci.dundee.ac.uk">
* donald@lifesci.dundee.ac.uk</a>
* @version 3.0
* @since OME2.2
*/
class ImViewerModel
{
/** Default maximum export size, 12kx12kx image */
static int DEFAULT_MAX_EXPORT_SIZE = 144000000;
/** The maximum size for the bird eye view for standard screen size.*/
private static final int BIRD_EYE_SIZE_LOWER = 128;
/** The maximum size for the bird eye view for a.*/
private static final int BIRD_EYE_SIZE_MEDIUM = 196;
/** The maximum size for the bird eye view.*/
private static final int BIRD_EYE_SIZE_HEIGH = 256;
/** The maximum number of items in the history. */
private static final int MAX_HISTORY = 10;
/** The maximum width of the thumbnail. */
private static final int THUMB_MAX_WIDTH = 24;
/** The maximum height of the thumbnail. */
private static final int THUMB_MAX_HEIGHT = 24;
/** Index of the <code>RenderingSettings</code> loader. */
private static final int SETTINGS = 0;
/** Index of the <code>ImageLoader</code> loader. */
private static final int IMAGE = 1;
/** Index of the <code>ImageLoader</code> loader. */
private static final int BIRD_EYE_VIEW = 2;
/** The image to view. */
private DataObject image;
/** Holds one of the state flags defined by {@link ImViewer}. */
private int state;
/** Reference to the component that embeds this model. */
private ImViewer component;
/** Map hosting the various loaders. */
private Map<Integer, DataLoader> loaders;
/** The sub-component that hosts the display. */
private Browser browser;
/** Reference to the current player. */
private ChannelPlayer player;
/** The width of the thumbnail if the window is iconified. */
private int sizeX;
/** The height of the thumbnail if the window is iconified. */
private int sizeY;
/** The magnification factor for the thumbnail. */
private double factor;
/** The image icon. */
private BufferedImage imageIcon;
/** The bounds of the component requesting the viewer. */
private Rectangle requesterBounds;
/** The index of the selected tab. */
private int tabbedIndex;
/**
* Flag indicating to paint or not some textual information on top
* of the grid image.
*/
private boolean textVisible;
/** Flag indicating that a movie is played. */
private boolean playingMovie;
/** Flag indicating that a movie is played. */
private boolean playingChannelMovie;
/** Collection of history item. */
private List<HistoryItem> historyItems;
/**
* The index of the movie, not that we set to <code>-1</code>
* when the movie player is launched.
*/
private int movieIndex;
/** The rendering setting related to a given set of pixels. */
private Map renderingSettings;
/** The metadata viewer. */
private MetadataViewer metadataViewer;
/** Flag indicating if the metadata are loaded. */
private boolean metadataLoaded;
/** The ID of the last selected pixels set. */
private long currentPixelsID;
/** The rendering settings set by another user. */
private RndProxyDef alternativeSettings;
/** The id of the selected user. */
private long selectedUserID;
/**
* Flag to compute the magnification factor when the image
* is set for the first time.
*/
private boolean initMagnificationFactor;
/** The parent of the image or <code>null</code> if no context specified. */
private DataObject parent;
/**
* The grandparent of the image or <code>null</code> if no
* context specified.
*/
private DataObject grandParent;
/** The plane information. */
private Map<Integer, PlaneInfo> planeInfos;
/** The id of the image. */
private long imageID;
/** Copy of the original rendering settings. */
private RndProxyDef originalDef;
/** Copy of the last rendering settings for the main image. */
private RndProxyDef lastMainDef;
/** Copy of the last rendering settings of the projection preview. */
private RndProxyDef lastProjDef;
/** The projection's preview parameters. */
private ProjectionParam lastProjRef;
/** The last projection timepoint. */
private int lastProjTime;
/** The collection of containers hosting the image. */
private Collection containers;
/**
* The collection of measurements linked to either the image or the plate.
*/
private Collection measurements;
/**
* Flag indicating if the viewer should be opened as a separate window
* or not. The default value is <code>true</code>.
*/
private boolean separateWindow;
/** The id of the table containing the overlay. */
private long overlayTableID;
/**
* The value indicating the reduction factor used for big images.
* The default value is <code>1</code>.
*/
private double originalRatio;
/** The tiles to display. */
private Map<Integer, Tile> tiles;
/** The number of rows, default is <code>1</code>.*/
private int numberOfRows;
/** The number of columns, default is <code>1</code>.*/
private int numberOfColumns;
/** The collection of resolutions levels.*/
private List<ResolutionLevel> resolutions;
/** The size of the tiled image along the X-axis.*/
private int tiledImageSizeX;
/** The size of the tiled image along the Y-axis.*/
private int tiledImageSizeY;
/** Flag indicating that the image is loaded for the first time.*/
private boolean firstTime;
/** The security context.*/
private SecurityContext ctx;
/** The channels.*/
private List<ChannelData> channels;
/** The display mode.*/
private int displayMode;
/** The number of tiles to load.*/
private int tileTotalCount;
/** The number of tiles already loaded.*/
private int tileLoadedCount;
/** The default plane size.*/
private int planeSize;
/** The units corresponding to the pixels size.*/
private UnitsLength refUnit;
/** The unit used for the scale bar */
private UnitsLength scaleBarUnit;
/** The selected rendering settings in under "User Setting".*/
private long selectedRndDefID;
/**
* Returns the default resolution level.
*
* @return See above.
*/
private int getDefaultResolutionLevel()
{
String zoomLevel = (String) ImViewerAgent.getRegistry().lookup(
LookupNames.BIGIMAGE_INITIAL_ZOOM);
if (isBigImage() && CommonsLangUtils.isNotBlank(zoomLevel)) {
//Use the default zoom level from the properties
return Integer.parseInt(zoomLevel);
}
// Determine the level according to the window size.
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int w = 9 * (screenSize.width / 10);
int h = 8 * (screenSize.height / 10);
ResolutionLevel level;
Dimension d;
for (int i = resolutions.size() - 1; i >= 0; i--) {
level = resolutions.get(i);
d = level.getImageSize();
if (d.width < w || d.height < h)
return level.getLevel();
}
return 0;
}
/**
* Creates the plane to retrieve.
*
* @return See above.
*/
private PlaneDef createPlaneDef()
{
PlaneDef pDef = new PlaneDef();
pDef.t = getDefaultT();
pDef.z = getDefaultZ();
pDef.slice = omero.romio.XY.value;
return pDef;
}
/** Initializes the tiles objects.*/
private void initializeTiles()
{
ResolutionLevel level = getResolutionDescription();
Dimension d = level.getTileSize();
int w = d.width;
int h = d.height;
int edgeWidth = w;
int edgeHeight = h;
int size = level.getImageSize().width;
edgeWidth = w;
int n = size/w;
tiledImageSizeX = n*w;
if (n*w < size) {
edgeWidth = size-n*w;
tiledImageSizeX += edgeWidth;
n++;
}
numberOfColumns = n;
size = level.getImageSize().height;
edgeHeight = h;
n = size/h;
tiledImageSizeY = n*h;
if (n*h < size) {
edgeHeight = size-n*h;
tiledImageSizeY += edgeHeight;
n++;
}
numberOfRows = n;
int index = 0;
Tile tile;
Region region;
int x = 0;
int y = 0;
int ww;
int hh;
if (numberOfColumns <= 0) numberOfColumns = 1;
if (numberOfColumns <= 0) numberOfColumns = 1;
for (int i = 0; i < numberOfRows; i++) {
if (i == (numberOfRows-1)) hh = edgeHeight;
else hh = h;
for (int j = 0; j < numberOfColumns; j++) {
if (j == (numberOfColumns-1)) ww = edgeWidth;
else ww = w;
index = i*numberOfColumns+j;
tile = new Tile(index, i, j);
region = new Region(x, y, ww, hh);
tile.setRegion(region);
x += d.width;
tiles.put(index, tile);
}
y += d.height;
x = 0;
}
}
/**
* Sorts the tiles by index.
*
* @param tiles The tiles to sort.
*/
private void sortTilesByIndex(List<Tile> tiles)
{
if (tiles == null || tiles.size() == 0) return;
Comparator c = new Comparator() {
public int compare(Object o1, Object o2)
{
int n1 = ((Tile) o1).getIndex(), n2 = ((Tile) o2).getIndex();
int v = 0;
if (n1 < n2) v = -1;
else if (n1 > n2) v = 1;
return v;
}
};
Collections.sort(tiles, c);
}
/**
* Transforms 3D coordinates into linear coordinates.
* The returned value <code>L</code> is calculated as follows:
* <code>L = sizeZ*sizeC*t + sizeZ*c + z</code>.
*
* @param z The z coordinate. Must be in the range <code>[0, sizeZ)</code>.
* @param c The c coordinate. Must be in the range <code>[0, sizeC)</code>.
* @param t The t coordinate. Must be in the range <code>[0, sizeT)</code>.
* @return See above.
*/
private Integer linearize(int z, int c, int t)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return -1;
int sizeZ = rnd.getPixelsDimensionsZ();
int sizeC = rnd.getPixelsDimensionsC();
int sizeT = rnd.getPixelsDimensionsT();
if (z < 0 || sizeZ <= z) return -1;
if (c < 0 || sizeC <= c) return -1;
if (t < 0 || sizeT <= t) return -1;
return Integer.valueOf(sizeZ*sizeC*t+sizeZ*c+z);
}
/** Computes the values of the {@link #sizeX} and {@link #sizeY} fields. */
private void computeSizes()
{
if (sizeX == -1 && sizeY == -1) {
sizeX = THUMB_MAX_WIDTH;
sizeY = THUMB_MAX_HEIGHT;
double x = sizeX/(double) getMaxX();
double y = sizeY/(double) getMaxY();
if (x > y) factor = x;
else factor = y;
double ratio = (double) getMaxX()/getMaxY();
if (ratio < 1) sizeX *= ratio;
else if (ratio > 1 && ratio != 0) sizeY *= 1/ratio;
}
}
/**
* Computes the magnification factor.
*
* @return See above
*/
private double initZoomFactor()
{
/* 28/02
if (initMagnificationFactor) return -1;
int maxX = getMaxX();
int maxY = getMaxY();
initMagnificationFactor = true;
if (maxX > IMAGE_MAX_WIDTH || maxY >IMAGE_MAX_HEIGHT) {
double ratioX = (double) IMAGE_MAX_WIDTH/maxX;
double ratioY = (double) IMAGE_MAX_HEIGHT/maxY;
if (ratioX < ratioY) return ratioX;
return ratioY;
}
return -1;
*/
return -1;
}
/**
* Initializes the model.
*
* @param bounds The bounds of the component invoking the {@link ImViewer}.
* @param separateWindow Pass <code>true</code> to open the viewer in a
* separate window, <code>false</code> otherwise.
*/
private void initialize(Rectangle bounds, boolean separateWindow)
{
firstTime = true;
this.separateWindow = separateWindow;
tiles = new HashMap<Integer, Tile>();
originalRatio = 1;
overlayTableID = -1;
requesterBounds = bounds;
state = ImViewer.NEW;
initMagnificationFactor = false;
sizeX = sizeY = -1;
tabbedIndex = ImViewer.VIEW_INDEX;
textVisible = true;
movieIndex = -1;
loaders = new HashMap<Integer, DataLoader>();
metadataViewer = null;
metadataLoaded = false;
currentPixelsID = -1;
selectedUserID = -1;
lastProjTime = -1;
lastProjRef = null;
planeSize = (Integer)
ImViewerAgent.getRegistry().lookup(LookupNames.PLANE_SIZE);
checkDefaultDisplayMode();
}
/**
* Invokes the value is not set.
*/
private void checkDefaultDisplayMode()
{
Integer value = (Integer) ImViewerAgent.getRegistry().lookup(
LookupNames.DATA_DISPLAY);
if (value == null) setDisplayMode(LookupNames.EXPERIMENTER_DISPLAY);
else setDisplayMode(value.intValue());
}
/** Initializes the {@link #metadataViewer}. */
private void initializeMetadataViewer()
{
metadataViewer = MetadataViewerFactory.getViewer("",
MetadataViewer.RND_SPECIFIC, alternativeSettings, selectedRndDefID);
metadataViewer.setRootObject(image, metadataViewer.getUserID(),
getSecurityContext());
// there might already exist another MetadataViewer with modified
// rendering settings; if so copy its original settings
MetadataViewer otherViewer = MetadataViewerFactory.getViewerFromId(
ImageData.class.getName(), image.getId());
if (otherViewer != null) {
Renderer otherRenderer = otherViewer.getRenderer();
if (otherRenderer != null)
originalDef = otherRenderer.getInitialRndSettings();
}
}
/**
* Reloads the 'saved by' thumbnails of the the rendering panel
*/
void reloadRenderingThumbs() {
metadataViewer.loadViewedBy();
}
/**
* Creates a new instance.
*
* @param ctx The security context.
* @param imageID The id of the image.
* @param bounds The bounds of the component invoking the
* {@link ImViewer}.
* @param separateWindow Pass <code>true</code> to open the viewer in a
* separate window, <code>false</code> otherwise.
*/
ImViewerModel(SecurityContext ctx, long imageID, Rectangle bounds,
boolean separateWindow)
{
this.ctx = ctx;
this.imageID = imageID;
initialize(bounds, separateWindow);
}
/**
* Returns the image to view.
*
* @return See above.
*/
ImageData getImage()
{
if (image instanceof WellSampleData)
return ((WellSampleData) image).getImage();
return (ImageData) image;
}
/**
* Creates a new object and sets its state to {@link ImViewer#NEW}.
*
* @param ctx The security context.
* @param image The image or well sample to view.
* @param bounds The bounds of the component invoking the
* {@link ImViewer}.
* @param separateWindow Pass <code>true</code> to open the viewer in a
* separate window, <code>false</code> otherwise.
*/
ImViewerModel(SecurityContext ctx, DataObject image, Rectangle bounds,
boolean separateWindow)
{
this.image = image;
this.ctx = ctx;
initialize(bounds, separateWindow);
numberOfRows = 1;
numberOfColumns = 1;
if (getImage().getDefaultPixels() != null) {
currentPixelsID = getImage().getDefaultPixels().getId();
}
}
/**
* Called by the <code>ImViewer</code> after creation to allow this
* object to store a back reference to the embedding component.
*
* @param component The embedding component.
*/
void initialize(ImViewer component)
{
this.component = component;
browser = BrowserFactory.createBrowser(component,
ImViewerFactory.getPreferences());
selectedRndDefID = -1;
}
/**
* Checks if the {@link Renderer} is loaded
* @return <code>true</code> if the Renderer is loaded, <code>false</code> otherwise
*/
boolean isRendererLoaded() {
return metadataViewer.getRenderer() != null;
}
/**
* Get the unit for the scalebar.
* Determined by assuming a 100px wide scalebar.
*
* @return The unit used for the scalebar
*/
public UnitsLength getScaleBarUnit() {
if (scaleBarUnit == null) {
if (getPixelsSizeX() == null)
return UnitsLength.MICROMETER;
// Determine a reasonable unit by assuming a 100px wide scalebar
Length tmp = new LengthI(getPixelsSizeX().getValue() * 100,
getPixelsSizeX().getUnit());
tmp = UIUtilities.transformSize(tmp);
this.scaleBarUnit = tmp.getUnit();
}
return scaleBarUnit;
}
/**
* Returns the current user's details.
*
* @return See above.
*/
ExperimenterData getUserDetails()
{
return (ExperimenterData) ImViewerAgent.getRegistry().lookup(
LookupNames.CURRENT_USER_DETAILS);
}
/**
* Sets the settings set by another user.
*
* @param alternativeSettings The value to set.
* @param userID The id of the user who set the settings.
*/
void setAlternativeSettings(RndProxyDef alternativeSettings, long userID)
{
this.alternativeSettings = alternativeSettings;
selectedUserID = userID;
}
/**
* Returns the id of the owner of the alternatives settings.
*
* @return See above.
*/
long getAlternativeSettingsOwnerId() { return selectedUserID; }
/**
* Compares another model to this one to tell if they would result in
* having the same display.
*
* @param other The other model to compare.
* @return <code>true</code> if <code>other</code> would lead to a viewer
* with the same display as the one in which this model belongs;
* <code>false</code> otherwise.
*/
boolean isSameDisplay(ImViewerModel other)
{
if (other == null) return false;
return true;
}
/**
* Returns <code>true</code> if it is the same parent, <code>false</code>
* otherwise.
*
* @param data The data to handle.
* @return See above
*/
boolean isSameParent(DataObject data)
{
if (data != null && parent != null) {
if (parent instanceof WellData) {
if (grandParent != null) {
if (data.getClass().getName().equals(
grandParent.getClass().getName()))
return data.getId() == grandParent.getId();
}
} else {
if (data.getClass().getName().equals(
parent.getClass().getName()))
return data.getId() == parent.getId();
}
}
return false;
}
/**
* Returns the name of the image.
*
* @return See above.
*/
String getImageName()
{
if (image == null) return "";
return getImage().getName();
}
/**
* Returns the name of image and id.
*
* @return See above.
*/
String getImageTitle()
{
GroupData group = getSelectedGroup();
StringBuffer buffer = new StringBuffer();
if (group != null) {
buffer.append("Group: ");
buffer.append(group.getName());
}
buffer.append(" [ID: "+getImageID()+"] ");
buffer.append(EditorUtil.getPartialName(getImageName()));
return buffer.toString();
}
/**
* Returns the current state.
*
* @return One of the flags defined by the {@link ImViewer} interface.
*/
int getState() { return state; }
/** Cancels the bird eye view loading.*/
void cancelBirdEyeView()
{
state = ImViewer.CANCELLED;
DataLoader loader = loaders.get(BIRD_EYE_VIEW);
if (loader != null) {
loader.cancel();
loaders.remove(BIRD_EYE_VIEW);
}
discard();
}
/**
* Sets the object in the {@link ImViewer#DISCARDED} state.
* Any ongoing data loading will be canceled.
*/
void discard()
{
state = ImViewer.DISCARDED;
imageIcon = null;
browser.discard();
if (image == null) return;
resetTiles();
Iterator<Integer> i = loaders.keySet().iterator();
while (i.hasNext()) {
loaders.get(i.next()).cancel();
}
browser.discard();
if (metadataViewer != null && metadataViewer.getRenderer() != null) {
metadataViewer.getRenderer().discard();
}
if (player == null) return;
player.setPlayerState(Player.STOP);
player = null;
}
/**
* Returns the sizeX.
*
* @return See above.
*/
int getMaxX()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getPixelsDimensionsX();
}
/**
* Returns the sizeY.
*
* @return See above.
*/
int getMaxY()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getPixelsDimensionsY();
}
/**
* Returns the maximum number of z-sections.
*
* @return See above.
*/
int getMaxZ()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getPixelsDimensionsZ()-1;
}
/**
* Returns the maximum number of timepoints.
*
* @return See above.
*/
int getMaxT()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getPixelsDimensionsT();
}
/**
* Returns the currently selected z-section.
*
* @return See above.
*/
int getDefaultZ()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getDefaultZ();
}
/**
* Returns the currently selected timepoint.
*
* @return See above.
*/
int getDefaultT()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getDefaultT();
}
/**
* Returns the currently selected time-point.
*
* @return See above.
*/
int getRealSelectedT()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getRealSelectedT();
}
/**
* Returns the number of time points if modulo available.
*
* @return See above.
*/
int getRealT()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getRealT();
}
/**
* Returns the currently selected color model.
*
* @return See above.
*/
String getColorModel()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return Renderer.GREY_SCALE_MODEL;
return rnd.getColorModel();
}
/**
* Returns a sorted list of <code>ChannelData</code> objects.
*
* @return See above.
*/
List<ChannelData> getChannelData()
{
if (channels != null) return channels;
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return new ArrayList<ChannelData>();
channels = rnd.getChannelData();
return channels;
}
/**
* Sets the channels associated to the image.
*
* @param channels The channels to set.
*/
void setChannels(List<ChannelData> channels)
{
this.channels = channels;
if (metadataViewer != null)
metadataViewer.onUpdatedChannels(channels);
}
/**
* Returns the <code>ChannelData</code> object corresponding to the
* given index.
*
* @param index The index of the channel.
* @return See above.
*/
ChannelData getChannelData(int index)
{
List<ChannelData> list = getChannelData();
Iterator<ChannelData> i = list.iterator();
ChannelData channel;
while (i.hasNext()) {
channel = i.next();
if (channel.getIndex() == index) return channel;
}
return null;
}
/**
* Returns the color associated to a channel.
*
* @param w The index of the channel.
* @return See above.
*/
Color getChannelColor(int w)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return null;
return rnd.getChannelColor(w);
}
/**
* Returns <code>true</code> if the channel is mapped, <code>false</code>
* otherwise.
*
* @param w The index of the channel.
* @return See above.
*/
boolean isChannelActive(int w)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return false;
return rnd.isChannelActive(w);
}
/**
* Starts an asynchronous call to retrieve the plane info related
* to the image. This method should only be invoked for fast connection.
*/
void firePlaneInfoRetrieval()
{
if (planeInfos != null && planeInfos.size() > 0) return;
int size = getMaxT()*getMaxC()*getMaxZ();
if (size > OmeroImageService.MAX_PLANE_INFO) return;
PlaneInfoLoader loader = new PlaneInfoLoader(component, ctx,
getPixelsID());
loader.load();
}
/**
* Fires an asynchronous retrieval of the rendered image.
*
* @param compression The compression level.
*/
void fireImageRetrieval(int compression)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
PlaneDef pDef = createPlaneDef();
state = ImViewer.LOADING_IMAGE;
if (firstTime) {
browser.setUnitBar(true);
long pixelsID = getImage().getDefaultPixels().getId();
ImageLoader loader = new ImageLoader(component, ctx,
pixelsID, pDef, false, compression);
loader.load();
loaders.put(IMAGE, loader);
} else {
component.setImage(rnd.renderPlane(pDef, compression));
}
}
/**
* Returns <code>true</code> if the image is rendered for the first time,
* <code>false</code> otherwise.
*
* @return See above
*/
boolean isFirstTime() { return firstTime; }
/**
* This method should only be invoked when we save the displayed image
* and split its components.
*
* @return See above.
*/
BufferedImage getSplitComponentImage()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return null;
PlaneDef pDef = new PlaneDef();
pDef.t = getDefaultT();
pDef.z = getDefaultZ();
pDef.slice = omero.romio.XY.value;
return rnd.renderPlane(pDef);
}
/** Notifies that the rendering control has been loaded. */
void onRndLoaded()
{
state = ImViewer.READY;
Renderer rnd = metadataViewer.getRenderer();
if (rnd != null && isBigImage()) {
resolutions = rnd.getResolutionDescriptions();
setSelectedResolutionLevel(getDefaultResolutionLevel());
}
double f = initZoomFactor();
if (f > 0)
browser.initializeMagnificationFactor(f);
try {
if (alternativeSettings != null && rnd != null)
rnd.resetSettings(alternativeSettings, false);
alternativeSettings = null;
if (rnd != null && originalDef == null) {
originalDef = rnd.getRndSettingsCopy();
}
} catch (Exception e) {}
}
/**
* Returns the {@link Browser}.
*
* @return See above.
*/
Browser getBrowser() { return browser; }
/**
* Returns the {@link MetadataViewer}.
*
* @return See above.
*/
MetadataViewer getMetadataViewer() { return metadataViewer; }
/**
* Sets the zoom factor.
*
* @param factor The factor to set.
* @param reset Pass <code>true</code> to reset the magnification factor.
* <code>false</code> to set it.
*/
void setZoomFactor(double factor, boolean reset)
{
browser.setZoomFactor(factor, reset);
}
/**
* Returns the zoom factor.
*
* @return The factor to set.
*/
double getZoomFactor() { return browser.getZoomFactor(); }
/**
* This method determines if the browser image should be resized to fit
* the window size if the window is resized.
*
* @return <code>true</code> if image should resize on window resize.
*/
boolean isZoomFitToWindow()
{
return getZoomFactor() == ZoomAction.ZOOM_FIT_FACTOR;
}
/**
* Sets the retrieved image, returns the a magnification or <code>-1</code>
* if no magnification factor computed.
*
* @param image The image to set.
* @return See above.
*/
double setImage(BufferedImage image)
{
state = ImViewer.READY;
if (image != null) browser.setRenderedImage(image);
loaders.remove(IMAGE);
firstTime = false;
//update image icon
//28/02 added to speed up process, turn back on for 4.1
/*
if (imageIcon == null) {
computeSizes();
imageIcon = Factory.magnifyImage(factor, image);
}
*/
if (image == null) return 1;
return initZoomFactor();
}
/** Creates the image icon. */
void createImageIcon()
{
BufferedImage img = browser.getRenderedImage();
if (img != null) {
computeSizes();
imageIcon = Factory.magnifyImage(factor, img);
}
}
/**
* Returns <code>true</code> if the magnification factor was set
* when the image was first loaded, <code>false</code> otherwise.
*
* @return See above.
*/
boolean isInitMagnificationFactor() { return initMagnificationFactor; }
/**
* Sets the color model.
*
* @param colorModel The color model to set.
* @param update Flag indicating to fire a property change
* indicating to update the image.
* @throws RenderingServiceException If an error occurred while setting
* the value.
* @throws DSOutOfServiceException If the connection is broken.
*/
void setColorModel(String colorModel, boolean update)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
if (ImViewer.GREY_SCALE_MODEL.equals(colorModel)) {
rnd.setOverlays(overlayTableID, null);
rnd.setColorModel(colorModel, update);
} else if (ImViewer.RGB_MODEL.equals(colorModel))
rnd.setColorModel(ImViewer.RGB_MODEL, update);
}
/**
* Sets the selected plane.
*
* @param z The z-section to set.
* @param t The timepoint to set.
* @param bin The selected small t.
*/
void setSelectedXYPlane(int z, int t, int bin)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
rnd.setSelectedXYPlane(z, t, bin);
}
/**
* Sets the color for the specified channel.
*
* @param index The channel's index.
* @param c The color to set.
*/
void setChannelColor(int index, Color c)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
rnd.setChannelColor(index, c, false);
}
/**
* Sets the channel active.
*
* @param index The channel's index.
* @param active Pass <code>true</code> to select the channel,
* <code>false</code> otherwise.
*/
void setChannelActive(int index, boolean active)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
rnd.setActive(index, active);
}
/**
* Returns the number of bins per time interval
*
* @return See above
*/
int getMaxLifetimeBin()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getMaxLifetimeBin();
}
/**
* Returns <code>true</code> if the image is a lifetime image,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isLifetimeImage()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return false;
return rnd.isLifetimeImage();
}
/**
* Returns <code>true</code> if the split view is allowed i.e. if the
* image is not too big, <code>false</code> otherwise.
*
* @return See above.
*/
boolean allowSplitView()
{
if (isBigImage()) return false;
if (getMaxC() <= 1) return false;
if (getModuloT() != null) return true;
if (isLifetimeImage()) return false;
return true;
}
/**
* Returns <code>true</code> if it is a large image,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isBigImage()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return false;
return rnd.isBigImage();
}
/**
* Checks if the image can be exported, i. e. it does not exceed the maximum
* size for being able to get exported as jpg, png or tif
*
* @return See above
*/
public boolean isExportable() {
if (getPixelsData() == null)
return false;
int imgSize = getPixelsData().getSizeX() * getPixelsData().getSizeY();
int maxSize = DEFAULT_MAX_EXPORT_SIZE;
String tmp = (String) ImViewerAgent.getRegistry().lookup(
LookupNames.MAX_EXPORT_SIZE);
if (tmp != null) {
try {
maxSize = Integer.parseInt(tmp);
} catch (NumberFormatException e) {
ImViewerAgent
.getRegistry()
.getLogger()
.warn(this,
"Non integer value provided for "
+ LookupNames.MAX_EXPORT_SIZE);
}
}
return imgSize <= maxSize;
}
/**
* Returns <code>true</code> if it is a large image,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isLargePlane()
{
return getMaxX()*getMaxY() > planeSize;
}
/**
* Returns the number of channels.
*
* @return See above.
*/
int getMaxC()
{
return getImage().getDefaultPixels().getSizeC();
}
/**
* Returns the number of active channels.
*
* @return See above.
*/
int getActiveChannelsCount() { return getActiveChannels().size(); }
/**
* Returns a list of active channels.
*
* @return See above.
*/
List<Integer> getActiveChannels()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return new ArrayList<Integer>();
return rnd.getActiveChannels();
}
/**
* Starts the channels movie player, invokes in the event-dispatcher
* thread for safety reason.
*
* @param play Pass <code>true</code> to play the movie, <code>false</code>
* to stop it.
*/
void playMovie(boolean play)
{
if (player != null && !play) {
player.setPlayerState(Player.STOP);
List l = player.getChannels();
if (l != null) {
Iterator i = l.iterator();
while (i.hasNext())
setChannelActive(((Integer) i.next()).intValue(), true);
}
player = null;
if (state != ImViewer.LOADING_IMAGE)
state = ImViewer.READY;
playingChannelMovie = false;
return;
}
playingChannelMovie = true;
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
player = new ChannelPlayer(component);
player.setPlayerState(Player.START);
}
});
state = ImViewer.CHANNEL_MOVIE;
}
/**
* Returns <code>true</code> if playing movie across channels,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isPlayingChannelMovie() { return playingChannelMovie; }
/**
* Sets the state.
*
* @param state The value to set.
*/
void setState(int state) { this.state = state; };
/**
* Returns the displayed image.
*
* @return See above.
*/
BufferedImage getDisplayedImage() { return browser.getDisplayedImage(); }
/**
* Returns the original image returned by the image service.
*
* @return See above.
*/
BufferedImage getOriginalImage() { return browser.getRenderedImage(); }
/**
* Returns the projected image returned by the image service.
*
* @return See above.
*/
BufferedImage getProjectedImage() { return browser.getProjectedImage(); }
/**
* Returns the image displayed in the grid view.
*
* @return See above.
*/
BufferedImage getGridImage() { return browser.getGridImage(); }
/**
* Returns the size of a pixel along the X-axis.
*
* @return See above.
*/
Length getPixelsSizeX()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null)
return new LengthI(1, UnitsLength.PIXEL);
return rnd.getPixelsSizeX();
}
/**
* Returns the size of a pixel along the Y-axis.
*
* @return See above.
*/
Length getPixelsSizeY()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return new LengthI(1, UnitsLength.PIXEL);
return rnd.getPixelsSizeY();
}
/**
* Returns the size of a pixel along the Y-axis.
*
* @return See above.
*/
Length getPixelsSizeZ()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return new LengthI(1, UnitsLength.PIXEL);
return rnd.getPixelsSizeZ();
}
/**
* Returns <code>true</code> if the unit bar is painted on top of
* the displayed image, <code>false</code> otherwise.
*
* @return See above.
*/
boolean isUnitBar() { return browser.isUnitBar(); }
/**
* Returns an iconified version of the displayed image.
*
* @return See above.
*/
BufferedImage getImageIcon() { return imageIcon; }
/**
* Returns the bounds of the component invoking the {@link ImViewer},
* or <code>null</code> if not available.
*
* @return See above.
*/
Rectangle getRequesterBounds() { return requesterBounds; }
/**
* Returns the ID of the pixels set.
*
* @return See above.
*/
long getPixelsID() { return currentPixelsID; }
/**
* Returns the index of the selected tab.
*
* @return See above.
*/
int getTabbedIndex() { return tabbedIndex; }
/**
* Sets the tab index.
*
* @param index The value to set.
*/
void setTabbedIndex(int index) { tabbedIndex = index; }
/**
* Returns a 3-dimensional array of boolean value, one per color band.
* The first (resp. second, third) element is set to <code>true</code>
* if an active channel is mapped to <code>RED</code> (resp.
* <code>GREEN</code>, <code>BLUE</code>), to <code>false</code> otherwise.
*
* @return See above
*/
boolean[] hasRGB()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return null;
return rnd.hasRGB();
}
/**
* Returns <code>true</code> if the textual information is painted on
* top of the grid image, <code>false</code> otherwise.
*
* @return See above.
*/
boolean isTextVisible() { return textVisible; }
/**
* Sets to <code>true</code> if the textual information is painted on
* top of the grid image, <code>false</code> otherwise.
*
* @param textVisible The value to set.
*/
void setTextVisible(boolean textVisible) { this.textVisible = textVisible; }
/**
* Returns <code>true</code> if the image has been loaded,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isImageLoaded() { return (image != null); }
/**
* Returns the ID of the viewed image.
*
* @return See above.
*/
long getImageID()
{
if (image == null) return imageID;
return getImage().getId();
}
/**
* Saves the rendering settings.
*
* @param reset Pass <code>true</code> to reset the original settings,
* <code>false</code> otherwise.
* @throws RenderingServiceException If an error occurred while setting
* the value.
* @throws DSOutOfServiceException If the connection is broken.
*/
void saveRndSettings(boolean reset)
throws RenderingServiceException, DSOutOfServiceException
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
RndProxyDef def = rnd.saveCurrentSettings();
if (reset) {
originalDef = def;
if (def != null && renderingSettings != null) {
renderingSettings.put(ImViewerAgent.getUserDetails(), def);
}
}
}
/**
* Sets to <code>true</code> when the movie is played, to <code>false</code>
* otherwise.
*
* @param play The value to set.
* @param index The movie index.
*/
void setPlayingMovie(boolean play, int index)
{
playingMovie = play;
movieIndex = index;
}
/**
* Returns <code>true</code> if a movie is played, to <code>false</code>
* otherwise.
*
* @return See above.
*/
boolean isPlayingMovie() { return playingMovie; }
/**
* Returns <code>true</code> if the channel is mapped
* to <code>Red</code> if the band is <code>0</code>,
* to <code>Green</code> if the band is <code>1</code>,
* to <code>Blue</code> if the band is <code>2</code>,
* <code>false</code> otherwise.
*
* @param band The color band.
* @param index The index of the channel.
* @return See above.
*/
boolean isColorComponent(int band, int index)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return false;
return rnd.isColorComponent(band, index);
}
/**
* Returns a collection of pairs
* (active channel's index, active channel's color).
*
* @return See above.
*/
Map<Integer, Color> getActiveChannelsColorMap()
{
List<Integer> l = getActiveChannels();
Map<Integer, Color> m = new HashMap<Integer, Color>(l.size());
Iterator<Integer> i = l.iterator();
Integer index;
while (i.hasNext()) {
index = i.next();
m.put(index, getChannelColor(index.intValue()));
}
return m;
}
/**
* Returns a collection of pairs (channel's index, channel's color).
*
* @return See above.
*/
Map<Integer, Color> getChannelsColorMap()
{
Map<Integer, Color> m = new HashMap<Integer, Color>(getMaxC());
for (int i = 0; i < getMaxC(); i++)
m.put(i, getChannelColor(i));
return m;
}
/**
* Sets the settings before turning on/off channels in the grid view.
*
* @param index The index specified.
*/
void setLastSettingsRef(int index)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
switch (index) {
case ImViewer.GRID_INDEX:
case ImViewer.PROJECTION_INDEX:
lastMainDef = rnd.getRndSettingsCopy();
break;
case ImViewer.VIEW_INDEX:
//lastProjDef = rnd.getRndSettingsCopy();
}
}
/**
* Creates a new history item and adds it to the list of elements.
* Returns the newly created item.
*
* @param title The title of the history item.
* @return See above.
*/
HistoryItem createHistoryItem()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return null;
String title = null;
BufferedImage img = null;
Color c = null;
//Make a smaller image
RndProxyDef def = rnd.getRndSettingsCopy();
switch (getTabbedIndex()) {
case ImViewer.PROJECTION_INDEX:
title = ImViewer.TITLE_PROJECTION_INDEX;
img = browser.getProjectedImage();
lastProjDef = def;
c = Color.GREEN.brighter();
break;
case ImViewer.VIEW_INDEX:
title = ImViewer.TITLE_VIEW_INDEX;
img = browser.getRenderedImage();
lastMainDef = def;
}
if (img == null) return null;
double ratio = 1;
int w = img.getWidth();
int h = img.getHeight();
if (w < ImViewer.MINIMUM_SIZE || h < ImViewer.MINIMUM_SIZE) ratio = 1;
else {
if (w >= h) ratio = (double) ImViewer.MINIMUM_SIZE/w;
else ratio = (double) ImViewer.MINIMUM_SIZE/h;
}
BufferedImage thumb = Factory.magnifyImage(ratio, img);
HistoryItem i = new HistoryItem(def, thumb, title);
i.setHighlight(c);
i.allowClose(false);
i.setIndex(getTabbedIndex());
if (historyItems == null) historyItems = new ArrayList<HistoryItem>();
if (historyItems.size() == MAX_HISTORY)
historyItems.remove(1); //always keep the first one
historyItems.add(i);
return i;
}
/**
* Returns the original rendering settings for the main image.
*
* @return See above.
*/
RndProxyDef getOriginalDef() { return originalDef; }
/**
* Returns the last rendering settings for the main image.
*
* @return See above.
*/
RndProxyDef getLastMainDef() { return lastMainDef; }
/**
* Returns the last rendering settings for the projection preview image.
*
* @return See above.
*/
RndProxyDef getLastProjDef() { return lastProjDef; }
/**
* Removes the item from the list.
*
* @param node The node to remove.
*/
void removeHistoryItem(HistoryItem node)
{
if (historyItems != null) historyItems.remove(node);
}
/** Clears the history. */
void clearHistory()
{
if (historyItems == null || historyItems.size() == 0) return;
HistoryItem node = historyItems.get(0);
historyItems.clear();
historyItems.add(node);
lastMainDef = node.getRndSettings();
lastProjDef = null;
lastProjTime = -1;
}
/**
* Returns the collection of history items.
*
* @return See above.
*/
List<HistoryItem> getHistory() { return historyItems; }
/**
* Partially resets the rendering settings.
*
* @param settings The value to set.
*/
void resetMappingSettings(RndProxyDef settings)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
rnd.resetSettings(settings, true);
}
/**
* Sets the last rendering settings.
*
* @param settings The settings to set.
*/
void setLastRndDef(RndProxyDef settings)
{
switch (getTabbedIndex()) {
case ImViewer.PROJECTION_INDEX:
//lastProjDef = settings;
break;
case ImViewer.VIEW_INDEX:
lastMainDef = settings;
}
}
/**
* Sets the original settings, the method should only be invoked when
* keeping track of the value after a save from the preview.
*
* @param settings The settings to set.
*/
void resetOriginalSettings(RndProxyDef settings)
{
originalDef = settings;
if (settings != null && renderingSettings != null) {
renderingSettings.put(ImViewerAgent.getUserDetails(), settings);
}
}
/**
* Starts an asynchronous call to retrieve the rendering settings to paste.
*/
void fireLoadRndSettingsToPaste()
{
state = ImViewer.PASTING;
if(ImViewerFactory.getRefSettings()==null) {
RenderingSettingsLoader loader = new RenderingSettingsLoader(component,
ctx, ImViewerFactory.getRefImage().getDefaultPixels().getId(), true);
loader.load();
}
else {
component.setSettingsToPaste(ImViewerFactory.getRefSettings());
}
}
/** Resets the default settings. */
void resetDefaultRndSettings()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
rnd.resetSettings();
}
/** Sets the original default settings. */
void setOriginalRndSettings()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
rnd.setOriginalRndSettings();
}
/**
* Returns <code>true</code> if we have rendering settings to paste,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean hasRndToPaste()
{
if (metadataViewer == null) return false;
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return false;
ImageData image = ImViewerFactory.getRefImage();
if (image == null) return false;
PixelsData pixels = image.getDefaultPixels();
if (pixels == null) return false;
return rnd.validatePixels(pixels);
}
/** Posts a {@link CopyRndSettings} event. */
void copyRenderingSettings()
{
RndProxyDef rndDef = null;
Renderer rnd = metadataViewer.getRenderer();
if (rnd != null && rnd.isModified()) {
rndDef = rnd.getRndSettingsCopy();
}
CopyRndSettings evt = new CopyRndSettings(getImage(), rndDef);
EventBus bus = ImViewerAgent.getRegistry().getEventBus();
bus.post(evt);
}
/**
* Returns the movie index.
*
* @return See above.
*/
int getMovieIndex() { return movieIndex; }
/**
* Returns <code>true</code> if the image is compressed,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isImageCompressed()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return false;
return rnd.isCompressed();
}
/**
* Sets the compression level.
*
* @param compressionLevel One of the compression level defined by
* {@link RenderingControl} I/F.
*/
void setCompressionLevel(int compressionLevel)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
rnd.setCompression(compressionLevel);
}
/**
* Returns the compression level.
*
* @return See above.
*/
int getCompressionLevel()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return RenderingControl.UNCOMPRESSED;
return rnd.getCompressionLevel();
}
/**
* Fires an asynchronous retrieval of the rendering settings
* linked to the currently viewed set of pixels.
*/
void fireRenderingSettingsRetrieval()
{
DataLoader loader = new RenderingSettingsLoader(component, ctx,
getImage().getDefaultPixels().getId());
loader.load();
if (loaders.get(SETTINGS) != null)
loaders.get(SETTINGS).cancel();
loaders.put(SETTINGS, loader);
}
/**
* Fires an asynchronous retrieval of the rendering settings
* linked to the currently viewed set of pixels.
*/
void fireOwnerSettingsRetrieval()
{
RenderingSettingsLoader loader = new RenderingSettingsLoader(component,
ctx, getImage().getDefaultPixels().getId());
loader.setOwner(getOwnerID());
loader.load();
if (loaders.get(SETTINGS) != null)
loaders.get(SETTINGS).cancel();
loaders.put(SETTINGS, loader);
}
/**
* Returns the rendering settings linked to the currently viewed set
* of pixels.
*
* @return See above.
*/
Map getRenderingSettings() { return renderingSettings; }
/**
* Sets the rendering settings linked to the currently viewed set
* of pixels.
*
* @param map The map to set.
*/
void setRenderingSettings(Map map)
{
renderingSettings = map;
loaders.remove(SETTINGS);
}
/**
* Applies the settings set by the selected user.
*
* @param exp The user to handle.
*/
void setUserSettings(ExperimenterData exp)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
RndProxyDef rndDef = (RndProxyDef) renderingSettings.get(exp);
rnd.resetSettings(rndDef, false);
}
/**
* Returns the id of the owner of the image.
*
* @return See above.
*/
long getOwnerID() { return image.getOwner().getId(); }
/**
* Returns <code>true</code> if data to save, <code>false</code>
* otherwise.
*
* @return See above.
*/
boolean hasMetadataToSave()
{
if (metadataViewer == null) return false;
return metadataViewer.hasDataToSave();
}
/** Saves the data. */
void saveMetadata()
{
if (metadataViewer != null)
metadataViewer.saveData();
}
/** Loads the data. */
void loadMetadata()
{
if (!metadataLoaded) {
metadataLoaded = true;
Map<ChannelData, Color> m = new LinkedHashMap<ChannelData, Color>();
List<ChannelData> sorted = getChannelData();
Iterator<ChannelData> i = sorted.iterator();
ChannelData channel;
while (i.hasNext()) {
channel = i.next();
m.put(channel, getChannelColor(channel.getIndex()));
}
metadataViewer.activate(m);
}
}
/** Resets the history when switching to a new rendering control.*/
void resetHistory() { historyItems = null; }
/**
* Starts an asynchronous call to render a preview of the projected image.
*
* @param startZ The lower bound of the z-section interval to project. (zero based)
* @param endZ The upper bound of the z-section interval to project. (zero based)
* @param stepping The stepping used, usually <code>1</code>.
* @param type The type of projection.
*/
void fireRenderProjected(int startZ, int endZ, int stepping, int type)
{
state = ImViewer.PROJECTION_PREVIEW;
ProjectionParam param = new ProjectionParam(getPixelsID(),
startZ, endZ, stepping, type);
param.setChannels(getActiveChannels());
lastProjRef = param;
lastProjDef = metadataViewer.getRenderer().getRndSettingsCopy();
ProjectionSaver loader = new ProjectionSaver(component, ctx, param,
ProjectionSaver.PREVIEW);
loader.load();
}
/**
* Starts an asynchronous call to project image.
*
* @param startZ The lower bound of the z-section interval to project.
* @param endZ The upper bound of the z-section interval to project.
* @param stepping The stepping used, usually <code>1</code>.
* @param type The type of projection.
* @param typeName A textual representation of the projection's type.
* @param ref Object with the projection's parameters.
*/
void fireImageProjection(int startZ, int endZ, int stepping, int type,
String typeName, ProjectionRef ref)
{
if (startZ < 0) startZ = ref.getStartZ();
if (endZ < startZ) endZ = ref.getEndZ();
state = ImViewer.PROJECTING;
StringBuffer buf = new StringBuffer();
buf.append("Original Image: "+getImageName());
buf.append("\n");
buf.append("Original Image ID: "+getImageID());
buf.append("\n");
buf.append("Projection type: "+typeName);
buf.append("\n");
buf.append("z-sections: "+(startZ+1)+"-"+(endZ+1));
buf.append("\n");
String imageNameWithRange = combineFilenameWith(ref.getImageName(),
getImageName());
int startT = ref.getStartT();
int endT = ref.getEndT();
if (startT == endT) buf.append("timepoint: "+(startT+1));
else buf.append("timepoints: "+(startT+1)+"-"+(endT+1));
List<Integer> channels = ref.getChannels();
ProjectionParam param = new ProjectionParam(getPixelsID(),
startZ, endZ, stepping, type, startT, endT, channels,
imageNameWithRange);
param.setDescription(buf.toString());
param.setDatasets(ref.getDatasets());
param.setDatasetParent(ref.getProject());
param.setChannels(getActiveChannels());
ProjectionSaver loader = new ProjectionSaver(component, ctx, param,
ProjectionSaver.PROJECTION, ref.isApplySettings());
loader.load();
}
/**
* Adds the ZRange to end of the the image name preserving the original
* file extension.
*
* @param imageName The name of the projection
* @param imageName The original name of the image
* @return See above.
*/
private String combineFilenameWith(String projectName, String imageName) {
String extension = FilenameUtils.getExtension(imageName);
StringBuilder nameBuilder = new StringBuilder();
nameBuilder.append(projectName);
nameBuilder.append(".");
nameBuilder.append(extension);
return nameBuilder.toString();
}
/**
* Starts an asynchronous retrieval of the containers containing the
* image.
*/
void fireContainersLoading()
{
state = ImViewer.LOADING_PROJECTION_DATA;
ContainerLoader loader = new ContainerLoader(component, ctx,
getImageID());
loader.load();
}
/**
* Returns the type of pixels.
*
* @return See above.
*/
String getPixelsType()
{
return getImage().getDefaultPixels().getPixelType();
}
/**
* Starts an asynchronous creation of the rendering settings
* for the pixels set.
*
* @param indexes The indexes of the projected channels.
* @param image The projected image.
*/
void fireProjectedRndSettingsCreation(List<Integer> indexes,
ImageData image)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
RndProxyDef def = rnd.getRndSettingsCopy();
RenderingSettingsCreator l = new RenderingSettingsCreator(component,
ctx, image, def, indexes);
l.load();
}
/**
* Sets the context of the node.
*
* @param parent The parent of the image or <code>null</code>
* if no context specified.
* @param grandParent The grandparent of the image or <code>null</code>
* if no context specified.
*/
void setContext(DataObject parent, DataObject grandParent)
{
this.parent = parent;
this.grandParent = grandParent;
if (metadataViewer != null)
metadataViewer.setParentRootObject(parent, grandParent);
if (isHCSImage()) fireMeasurementsLoading();
}
/**
* Returns the parent of the image or <code>null</code>
* if no context specified.
*
* @return See above.
*/
DataObject getParent() { return parent; }
/**
* Returns the grandparent of the image or <code>null</code>
* if no context specified.
*
* @return See above.
*/
DataObject getGrandParent() { return grandParent; }
/**
* Sets the plane information.
*
* @param objects The collection of <code>Plane Info</code> objects.
*/
void setPlaneInfo(Collection objects)
{
if (planeInfos == null) planeInfos = new HashMap<Integer, PlaneInfo>();
else planeInfos.clear();
Iterator i = objects.iterator();
PlaneInfo object;
Integer index;
while (i.hasNext()) {
object = (PlaneInfo) i.next();
if (object != null) {
index = linearize(object.getTheZ().getValue(),
object.getTheC().getValue(), object.getTheT().getValue());
if (index >= 0) planeInfos.put(index, object);
}
}
}
/**
* Returns the <code>Plane Info</code> for the specified XY-plane.
*
* @param z The z coordinate. Must be in the range <code>[0, sizeZ)</code>.
* @param c The w coordinate. Must be in the range <code>[0, sizeW)</code>.
* @param t The t coordinate. Must be in the range <code>[0, sizeT)</code>.
* @return See above.
*/
PlaneInfo getPlane(int z, int c, int t)
{
Integer index = null;
try {
index = linearize(z, c, t);
if (index < 0) return null;
return planeInfos.get(index);
} catch (Exception e) {}
return null;
}
/** Loads the image before doing anything else. */
void fireImageLoading()
{
state = ImViewer.LOADING_IMAGE_DATA;
ImageDataLoader loader = new ImageDataLoader(component, ctx,
getImageID());
loader.load();
}
/**
* Sets the image data.
*
* @param image The value to set.
*/
void setImageData(ImageData image)
{
state = ImViewer.LOADING_RND;
this.image = image;
initializeMetadataViewer();
currentPixelsID = image.getDefaultPixels().getId();
if (metadataViewer != null)
metadataViewer.setParentRootObject(parent, grandParent);
}
/**
* Returns <code>true</code> if the rendering settings are original,
* <code>false</code> otherwise.
* @param checkPlane Pass <code>true</code> to take z/t changes into account,
* <code>false</code> to ignore them
* @return See above.
*/
boolean isOriginalSettings(boolean checkPlane)
{
if (originalDef == null) return true;
if (metadataViewer == null) return true;
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return true;
return isSameSettings(originalDef, checkPlane);
}
/**
* Returns <code>true</code> if it is the original plane,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isOriginalPlane()
{
if (originalDef != null) {
if (originalDef.getDefaultZ() != getDefaultZ())
return false;
if (originalDef.getDefaultT() != getDefaultT())
return false;
}
return true;
}
/**
* Returns <code>true</code> if the passed rendering settings are the same
* that the current one, <code>false</code> otherwise.
*
* @param def The settings to check.
* @param checkPlane Pass <code>true</code> to check the plane,
* <code>false</code> otherwise.
* @return See above.
*/
boolean isSameSettings(RndProxyDef def, boolean checkPlane)
{
if (metadataViewer == null) return false;
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return false;
return rnd.isSameSettings(def, checkPlane);
}
/**
* Sets the projected image for preview.
*
* @param image The buffered image.
*/
void setRenderProjected(Object image)
{
state = ImViewer.READY;
browser.setRenderProjected(image);
}
/**
* Sets the collections of containers hosting the image.
*
* @param containers The collection of containers hosting the image.
*/
void setContainers(Collection containers)
{
this.containers = containers;
state = ImViewer.READY;
}
/**
* Returns the collections of containers hosting the image.
* @return See above.
*/
Collection getContainers() { return containers; }
/**
* Returns the pixels data.
*
* @return See above.
*/
PixelsData getPixelsData()
{
if (image == null) return null;
return getImage().getDefaultPixels();
}
/**
* Returns the last projection details.
*
* @return See above.
*/
ProjectionParam getLastProjRef() { return lastProjRef; }
/**
* Sets the last projection details.
*
* @param ref The value to set.
*/
void setLastProjectionRef(ProjectionParam ref) { lastProjRef = ref; }
/**
* Returns the time-point used for the projection's preview.
*
* @return See above.
*/
int getLastProjectionTime() { return lastProjTime; }
/**
* Sets the timepoint used for a projection's preview.
*
* @param time The value to set.
*/
void setLastProjectionTime(int time) { lastProjTime = time; }
/**
* Returns the unit used to determine the size of the unit bar.
* The unit depends on the size stored. The unit of reference in the
* OME model is in microns, but this is a transformed unit.
*
* @return See above.
*/
double getUnitInRefUnits() { return browser.getUnitInRefUnits(); }
/** Loads all the available datasets. */
void loadAllContainers()
{
ContainerLoader loader = new ContainerLoader(component, ctx);
loader.load();
}
/** Makes a movie. */
void makeMovie()
{
if (metadataViewer == null) return;
metadataViewer.makeMovie((int) getUnitInRefUnits(),
getBrowser().getUnitBarColor());
}
/**
* Returns the selected bin.
*
* @return See above.
*/
int getSelectedBin()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return -1;
return rnd.getSelectedBin();
}
/**
* Sets the selected channel.
*
* @param index The index of the channel.
*/
void setSelectedChannel(int index)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
rnd.setSelectedChannel(index);
}
/**
* Returns <code>true</code> if the viewer should be opened in a
* separate window, <code>false</code> otherwise.
* The default value is <code>true</code>.
*
* @return See above.
*/
boolean isSeparateWindow() { return separateWindow; }
/**
* Sets the {@link #separateWindow} flag.
*
* @param separateWindow Pass <code>true</code> to view the viewer
* in a separate window, <code>false</code> otherwise.
*/
void setSeparateWindow(boolean separateWindow)
{
this.separateWindow = separateWindow;
}
/** Loads the measurements associated to the plate if any specified. */
void fireMeasurementsLoading()
{
if (parent instanceof WellData) {
ImageData p = getImage();
MeasurementsLoader loader = new MeasurementsLoader(component, ctx,
p);
loader.load();
}
}
/**
* Sets the measurements associated to either the image or the plate.
*
* @param result The collection to set.
*/
void setMeasurements(Collection result)
{
measurements = result;
}
/**
* Returns the measurements if any.
*
* @return See above.
*/
Collection getMeasurements() { return measurements; }
/**
* Brings up the activity options.
*
* @param source The source of the mouse pressed.
* @param location The location of the mouse pressed.
*/
void activityOptions(Component source, Point location)
{
if (metadataViewer == null) return;
metadataViewer.activityOptions(source, location,
MetadataViewer.PUBLISHING_OPTION);
}
/**
* Returns <code>true</code> if the passed channels compose an RGB image,
* <code>false</code> otherwise.
*
* @param channels The collection of channels to handle.
* @return See above.
*/
boolean isMappedImageRGB(List channels)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return false;
return rnd.isMappedImageRGB(channels);
}
/**
* Returns the overlays associated to that image.
*
* @return See above.
*/
Map<Integer, Integer> getOverLays()
{
Iterator i = measurements.iterator();
Object object;
TableResult table = null;
while (i.hasNext()) {
object = i.next();
if (object instanceof TableResult) {
table = (TableResult) object;
overlayTableID = table.getTableID();
break;
}
}
if (table == null) return null;
Object[][] data = table.getData();
Map<Integer, Integer> overlays = new LinkedHashMap<Integer, Integer>();
int index = 0;
Color c = null;
Long value = -1L;
for (int j = 0; j < data.length; j++) {
value = (Long) data[j][2];
if (value != null) {
overlays.put((Integer) data[j][0], value.intValue());
} else {
if (index == 0) c = Color.red;
else if (index == 1) c = Color.green;
else if (index == 2) c = Color.blue;
overlays.put((Integer) data[j][0], UIUtilities.convertColor(c));
}
index++;
if (index%3 == 0) index = 0;
}
return overlays;
}
/**
* Renders the overlays.
*
* @param overlays
*/
void renderOverlays(Map<Long, Integer> overlays)
{
PlaneDef pDef = new PlaneDef();
pDef.t = getDefaultT();
pDef.z = getDefaultZ();
pDef.slice = omero.romio.XY.value;
state = ImViewer.LOADING_IMAGE;
OverlaysRenderer loader = new OverlaysRenderer(component, ctx,
getPixelsID(), pDef, overlayTableID, overlays);
loader.load();
}
/**
* Returns the original ratio.
*
* @return See above.
*/
double getOriginalRatio() { return originalRatio; }
/** Refreshes the renderer. */
void refresh()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd != null) rnd.refresh();
}
/**
* Returns <code>true</code> if the object is writable,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isWritable()
{
boolean b = isUserOwner();
if (b) return b;
GroupData g = ImViewerAgent.getUserDetails().getDefaultGroup();
switch (g.getPermissions().getPermissionsLevel()) {
case GroupData.PERMISSIONS_GROUP_READ_LINK:
case GroupData.PERMISSIONS_PUBLIC_READ_WRITE:
return true;
}
return false;
}
/**
* Returns <code>true</code> if the user logged in is the owner of the
* image, <code>false</code> otherwise.
*
* @return See above.
*/
boolean isUserOwner()
{
long userID = ImViewerAgent.getUserDetails().getId();
return EditorUtil.isUserOwner(getImage(), userID);
}
/**
* Sets the maximum range for channels.
*
* @param absolute Pass <code>true</code> to set it to the absolute value,
* <code>false</code> to the minimum and maximum.
*/
void setRangeAllChannels(boolean absolute)
{
metadataViewer.getRenderer().setRangeAllChannels(absolute);
}
/**
* Returns <code>true</code> if the data object is a well sample,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isHCSImage()
{
return (image instanceof WellSampleData);
}
/**
* Loads the bird eye view image for big image.
* @param scale If <code>true</code> just loads the thumbnail and scales it up (fast),
* otherwise requests the image with the intended size from the server directly (slow);
*/
void fireBirdEyeViewRetrieval(boolean scale) {
// use the lowest resolution
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null)
return;
int w = tiledImageSizeX;
int h = tiledImageSizeY;
BirdEyeLoader loader;
if (scale) {
double ratio = 1;
int ref = BIRD_EYE_SIZE_LOWER;
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
if (screen.height > 1200 && screen.height <= 1600)
ref = BIRD_EYE_SIZE_MEDIUM;
else if (screen.height > 1600)
ref = BIRD_EYE_SIZE_HEIGH;
if (w < ref || h < ref)
ratio = 1;
else {
if (w >= h)
ratio = (double) ref / w;
else
ratio = (double) ref / h;
}
ratio = (double) ref / Factory.THUMB_DEFAULT_WIDTH;
state = ImViewer.LOADING_BIRD_EYE_VIEW;
loader = new BirdEyeLoader(component, ctx, getImage(), ratio);
} else {
int imgSize = BIRD_EYE_SIZE_LOWER;
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
if (screen.height > 1200 && screen.height <= 1600)
imgSize = BIRD_EYE_SIZE_MEDIUM;
else if (screen.height > 1600)
imgSize = BIRD_EYE_SIZE_HEIGH;
loader = new BirdEyeLoader(component, ctx, getImage(), imgSize);
}
loader.load();
loaders.put(BIRD_EYE_VIEW, loader);
}
/**
* Returns the size of the tile.
*
* @return See above.
*/
Dimension getTileSize()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return null;
ResolutionLevel r = getResolutionDescription();
if (r == null) return rnd.getTileSize();
return r.getTileSize();
}
/**
* Returns the resolution level corresponding to the selected level.
*
* @return See above.
*/
ResolutionLevel getResolutionDescription()
{
return getResolutionDescription(getSelectedResolutionLevel());
}
/**
* Get the nominal magnification of the objective
*
* @return See above
*/
double getNominalMagnification() {
if (component.getImageAcquisitionData() != null) {
ObjectiveData objective = component.getImageAcquisitionData()
.getObjective();
return objective != null ? objective.getNominalMagnification() : -1;
} else {
fireImagAcquisitionDataLoading();
return -1;
}
}
/** Loads the image acquisition data. */
void fireImagAcquisitionDataLoading() {
if (component.getImageAcquisitionData() == null) {
AcquisitionDataLoader loader = new AcquisitionDataLoader(component,
ctx, image);
loader.load();
}
}
/**
* Returns the resolution level corresponding to the selected level.
*
* @param index The selected index.
* @return See above.
*/
ResolutionLevel getResolutionDescription(int index)
{
if (resolutions == null) return null;
Iterator<ResolutionLevel> i = resolutions.iterator();
ResolutionLevel level;
while (i.hasNext()) {
level = i.next();
if (index == level.getLevel())
return level;
}
return null;
}
/**
* Returns the number of rows, default is <code>1</code>.
*
* @return See above.
*/
int getRows() { return numberOfRows; }
/**
* Returns the number of columns, default is <code>1</code>.
*
* @return See above.
*/
int getColumns() { return numberOfColumns; }
/**
* Returns the tiles to display.
*
* @return See above.
*/
Map<Integer, Tile> getTiles() { return tiles; }
/**
* Fires an asynchronous call to load the tiles.
*
* @param selection The collection of tiles to load.
*/
void fireTileLoading(List<Tile> selection)
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null || selection == null) return;
PlaneDef pDef = new PlaneDef();
pDef.t = getDefaultT();
pDef.z = getDefaultZ();
pDef.slice = omero.romio.XY.value;
List<Tile> list;
list = selection;
sortTilesByIndex(list);
state = ImViewer.LOADING_TILES;
List<RenderingControl> proxies = rnd.getRenderingControls();
int m = proxies.size();
//Create n sublist
int n = selection.size();
int diff = n/m;
List<Tile> l;
int j;
int step = 0;
if (n < m) diff = 1;
tileTotalCount = n;
tileLoadedCount = 0;
RenderingControl proxy;
TileLoader loader;
for (int i = 0; i < m; i++) {
l = new ArrayList<Tile>();
j = step+diff;
if (i == (m-1)) j += (n-j);
if (j <= n) {
l = list.subList(step, j);
step += l.size();
}
if (l.size() > 0) {
proxy = proxies.get(i);
loader = new TileLoader(component, ctx, currentPixelsID,
pDef, proxy, l);
loader.load();
}
}
}
/** Resets the tiles.*/
void resetTiles()
{
if (tiles == null) return;
Iterator<Tile> i = tiles.values().iterator();
while (i.hasNext())
i.next().setImage(null);
}
/**
* Returns the possible resolution levels. This method should only be used
* when dealing with large images.
*
* @return See above.
*/
int getResolutionLevels()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 1;
return rnd.getResolutionLevels();
}
/**
* Returns the currently selected resolution level. This method should only
* be used when dealing with large images.
*
* @return See above.
*/
int getSelectedResolutionLevel()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return 0;
return rnd.getSelectedResolutionLevel();
}
/**
* Sets resolution level. This method should only be used when dealing with
* large images.
*
* @param level The value to set.
*/
void setSelectedResolutionLevel(int level)
{
if (level < 0) level = 0;
if (level >= getResolutionLevels())
level = getResolutionLevels()-1;
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return;
clearTileImages(tiles.values());
tiles.clear();
rnd.setSelectedResolutionLevel(level);
initializeTiles();
}
/**
* Returns the size of the tiled image along the X-axis i.e.
* the size of a tile along the X-axis multiplied by the number of columns.
*
* @return See above.
*/
int getTiledImageSizeX()
{
if (!isBigImage()) return getMaxX();
return tiledImageSizeX;
}
/**
* Returns the size of the tiled image along the Y-axis i.e.
* the size of a tile along the Y-axis multiplied by the number of rows.
*
* @return See above.
*/
int getTiledImageSizeY()
{
if (!isBigImage()) return getMaxY();
return tiledImageSizeY;
}
/**
* Clears the images hosted by the tile if not <code>null</code>.
*
* @param toClear The collection to handle.
*/
void clearTileImages(Collection<Tile> toClear)
{
if (toClear == null || toClear.size() == 0) return;
Iterator<Tile> i = toClear.iterator();
Tile tile;
Object image;
BufferedImage bi;
while (i.hasNext()) {
tile = i.next();
image = tile.getImage();
if (image != null && image instanceof BufferedImage) {
bi = (BufferedImage) image;
bi.getGraphics().dispose();
bi.flush();
tile.setImage(null);
}
}
}
/** Cancels the rendering of the image.*/
void cancelRendering()
{
if (metadataViewer == null) return;
Renderer rnd = metadataViewer.getRenderer();
if (rnd != null) rnd.discard();
state = ImViewer.CANCELLED;
}
/**
* Sets the image for the bird eye view. (If it is a scaled image, the image
* will be used temporary while a request for an unscaled image (better
* quality) is triggered)
*
* @param image
* The image to set.
* @param scaled
* Indicates if the image is a scaled image
*/
void setBirdEyeView(BufferedImage image, boolean scaled)
{
loaders.remove(BIRD_EYE_VIEW);
getBrowser().setBirdEyeView(image);
if (scaled) {
fireBirdEyeViewRetrieval(false);
}
}
/**
* Returns <code>true</code> if it is the same viewer, <code>false</code>
* otherwise.
*
* @param pixelsID The id of the pixels set.
* @param ctx The security context.
* @return See above.
*/
boolean isSame(long pixelsID, SecurityContext ctx)
{
if (getPixelsID() == pixelsID) //add server check
return true;
return false;
}
/**
* Returns <code>true</code> if it is the same viewer, <code>false</code>
* otherwise.
*
* @param imageID The id of the image.
* @param ctx The security context.
* @return See above.
*/
boolean isSameImage(long imageID, SecurityContext ctx)
{
if (getImageID() == imageID) //add server check
return true;
return false;
}
/**
* Returns the security context.
*
* @return See above.
*/
SecurityContext getSecurityContext() { return ctx; }
/**
* Returns the group the image belongs to.
*
* @return See above.
*/
GroupData getSelectedGroup()
{
Collection set = (Collection) ImViewerAgent.getRegistry().lookup(
LookupNames.USER_GROUP_DETAILS);
if (set == null || set.size() <= 1)
return null;
Iterator i = set.iterator();
GroupData g;
while (i.hasNext()) {
g = (GroupData) i.next();
if (g.getId() == ctx.getGroupID())
return g;
}
return null;
}
/**
* Returns the relevant units associated to the pixels size.
*
* @return See above.
*/
UnitsLength getRefUnit()
{
if (refUnit != null)
return refUnit;
Length tmp = UIUtilities.transformSize(getPixelsSizeX());
refUnit = tmp.getUnit();
return refUnit;
}
/**
* Returns the display mode. One of the constants defined by
* {@link LookupNames}.
*
* @return See above.
*/
int getDisplayMode() { return displayMode; }
/**
* Sets the display mode.
*
* @param value The value to set.
*/
void setDisplayMode(int value)
{
if (value < 0) {
checkDefaultDisplayMode();
return;
}
switch (value) {
case LookupNames.EXPERIMENTER_DISPLAY:
case LookupNames.GROUP_DISPLAY:
displayMode = value;
break;
default:
displayMode = LookupNames.EXPERIMENTER_DISPLAY;
}
if (containers != null) {
containers.clear();
containers = null;
}
}
/**
* Returns <code>true</code> if all the tiles are loaded,
* <code>false</code> otherwise.
*
* @param count The number of loaded tiles.
* @return See above.
*/
boolean isTileLoaded(int count)
{
tileLoadedCount += count;
return tileLoadedCount == tileTotalCount;
}
/**
* Returns the modulo info if it exists.
*
* @return See above.
*/
ModuloInfo getModuloT()
{
Renderer rnd = metadataViewer.getRenderer();
if (rnd == null) return null;
return rnd.getModuloT();
}
/**
* Returns if interpolation is enabled or not
* @return
*/
boolean isInterpolation() {
return browser.isInterpolation();
}
/**
* En-/Disables interpolation
* @param interpolation
*/
void setInterpolation(boolean interpolation) {
browser.setInterpolation(interpolation);
}
void setSelectedRndDef(long defID)
{
selectedRndDefID = defID;
}
/**
* Reload the ROI count
*/
public void reloadROICount() {
metadataViewer.reloadROICount();
}
}