/*
* $Id$
*
* Copyright 2011 Glencoe Software, Inc. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package omero.util;
import omero.ClientError;
import omero.ServerError;
import omero.api.RawPixelsStorePrx;
import omero.api.ServiceFactoryPrx;
import omero.model.Pixels;
/**
* Helper subclass of {@link TileLoop} which handles
* unloaded {@link Pixels} instances and manages the
* creation of the {@link RPSTileData}.
*
* @author Josh Moore, josh at glencoesoftware.com
* @since 4.3.0
*/
public class RPSTileLoop extends TileLoop {
protected final ServiceFactoryPrx session;
/**
* Instance will be replaced on {@link RawPixelsStorePrx#save()}
*/
protected volatile Pixels pixels;
public RPSTileLoop(ServiceFactoryPrx session, Pixels pixels) {
this.session = session;
this.pixels = pixels;
if (pixels == null || pixels.getId() == null) {
throw new ClientError("pixels instance must be managed!");
}
}
protected ServiceFactoryPrx getSession() {
return session;
}
/**
* After saving the binary data, the update event of the
* {@link Pixels} instance will be updated and therefore
* need to be reloaded. As a convenience the returned
* value is accessible here.
*/
public Pixels getPixels() {
return this.pixels;
}
/**
* Called by the {@link TileData} implementation to update
* the {@link #pixels} instance for re-use by the client.
*/
public void setPixels(Pixels pixels) {
this.pixels = pixels;
}
public TileData createData() {
try {
RawPixelsStorePrx rps = getSession().createRawPixelsStore();
rps.setPixelsId(getPixels().getId().getValue(), false); // 'false' is ignored here.
return new RPSTileData(this, rps);
} catch (ServerError se) {
throw new RuntimeException(se);
}
}
/**
* Iterates over every tile in a given pixel based on the
* over arching dimensions and a requested maximum tile width and height.
* @param iteration Invoker to call for each tile.
* @param tileWidth <b>Maximum</b> width of the tile requested. The tile
* request itself will be smaller than the original tile width requested if
* <code>x + tileWidth > sizeX</code>.
* @param tileHeight <b>Maximum</b> height of the tile requested. The tile
* request itself will be smaller if <code>y + tileHeight > sizeY</code>.
* @return The total number of tiles iterated over.
*/
public int forEachTile(int tileWidth, int tileHeight,
TileLoopIteration iteration) throws ClientError, ServerError {
if (!pixels.isLoaded()) {
try {
pixels = getSession().getPixelsService().retrievePixDescription(pixels.getId().getValue());
} catch (Exception e) {
throw new ClientError("Failed to load " + pixels.getId().getValue() + "\n" + e);
}
}
final int sizeX = pixels.getSizeX().getValue();
final int sizeY = pixels.getSizeY().getValue();
final int sizeZ = pixels.getSizeZ().getValue();
final int sizeC = pixels.getSizeC().getValue();
final int sizeT = pixels.getSizeT().getValue();
return forEachTile(sizeX, sizeY, sizeZ, sizeT, sizeC, tileWidth, tileHeight, iteration);
}
}