package fr.unistra.pelican.algorithms.geometric;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.IntegerImage;
/**
* This class performs a spatial resampling of the images, and work in any
* dimensions
*
* @author Lefevre
*
* TODO: améliorer la gestion des bords
*/
public class ResamplingByValue extends Algorithm {
/**
* The input image
*/
public Image input;
/**
* The resampling value on the dimension X
*/
public Integer vx;
/**
* The resampling value on the dimension Y
*/
public Integer vy;
/**
* The resampling value on the dimension Z
*/
public Integer vz;
/**
* The resampling value on the dimension T
*/
public Integer vt;
/**
* The resampling value on the dimension B
*/
public Integer vb;
/**
* The resampling method : NEAREST, BILINEAR
*/
public Integer resamplingMethod;
/**
* The output image
*/
public Image output;
/**
* Constant to represent NEAREST method: Considers one pixel every X
*/
public final static int NEAREST = 0;
/**
* Constant to represent BILINEAR method: Considers the average of X pixels
*/
public final static int BILINEAR = 1;
/**
* Default constructor
*/
public ResamplingByValue() {
super.inputs = "input,vx,vy,vz,vt,vb,resamplingMethod";
super.outputs = "output";
}
/**
* Performs a spatial resampling of the images and work in any dimensions
* @param input The input image
* @param vx The resampling value on the dimension X
* @param vy The resampling value on the dimension Y
* @param vz The resampling value on the dimension Z
* @param vt The resampling value on the dimension T
* @param vb The resampling value on the dimension B
* @param resamplingMethod The resampling method : NEAREST, BILINEAR
* @return The output image
*/
public static Image exec(Image input, Integer vx, Integer vy, Integer vz, Integer vt, Integer vb, int resamplingMethod) {
return (Image) new ResamplingByValue().process(input,vx,vy,vz,vt,vb,resamplingMethod);
}
@Override
public void launch() throws AlgorithmException {
double xdim = input.getXDim();
double ydim = input.getYDim();
double zdim = input.getZDim();
double tdim = input.getTDim();
double bdim = input.getBDim();
double rx = vx.doubleValue()/xdim;
double ry = vy.doubleValue()/ydim;
double rz = vz.doubleValue()/zdim;
double rt = vt.doubleValue()/tdim;
double rb = vb.doubleValue()/bdim;
output = input.newInstance(vx, vy, vz, vt, vb);
output.copyAttributes(input);
if (resamplingMethod == NEAREST) {
if(input instanceof IntegerImage)
{
for (int z = 0; z < vz; z++)
for (int t = 0; t < vt; t++)
for (int b = 0; b < vb; b++)
for (int x = 0; x < vx; x++)
for (int y = 0; y < vy; y++)
output.setPixelInt(x, y, z, t, b, input
.getPixelInt((int) (x / rx),
(int) (y / ry),
(int) (z / rz),
(int) (t / rt),
(int) (b / rb)));
} else
{
for (int z = 0; z < vz; z++)
for (int t = 0; t < vt; t++)
for (int b = 0; b < vb; b++)
for (int x = 0; x < vx; x++)
for (int y = 0; y < vy; y++)
output.setPixelDouble(x, y, z, t, b, input
.getPixelDouble((int) (x / rx),
(int) (y / ry),
(int) (z / rz),
(int) (t / rt),
(int) (b / rb)));
}
} else if (resamplingMethod == BILINEAR) {
double sum, val, weight, norm;
double px, py, pz, pt, pb;
int mx, my, mz, mt, mb;
for (int z = 0; z < vz; z++)
for (int t = 0; t < vt; t++)
for (int b = 0; b < vb; b++)
for (int x = 0; x < vx; x++)
for (int y = 0; y < vy; y++) {
// cas particulier pour les pixels exacts
if (x % rx == 0 && y % ry == 0 && z % rz == 0
&& t % rt == 0 && b % rb == 0) {
output.setPixelDouble(x, y, z, t, b, input
.getPixelDouble((int) (x / rx),
(int) (y / ry),
(int) (z / rz),
(int) (t / rt),
(int) (b / rb)));
continue;
}
sum = 0;
norm = 0;
px = x / rx;
py = y / ry;
pz = z / rz;
pt = t / rt;
pb = b / rb;
// TODO: améliorer la gestion des bords
mx = (rx == 1 || px >= xdim - 1 || x % rx == 0 ? 1
: 2);
my = (ry == 1 || py >= ydim - 1 || y % ry == 0 ? 1
: 2);
mz = (rz == 1 || pz >= zdim - 1 || z % rz == 0 ? 1
: 2);
mt = (rt == 1 || pt >= tdim - 1 || t % rt == 0 ? 1
: 2);
mb = (rb == 1 || pb >= bdim - 1 || b % rb == 0 ? 1
: 2);
for (int dt = 0; dt < mt; dt++)
for (int dz = 0; dz < mz; dz++)
for (int db = 0; db < mb; db++)
for (int dy = 0; dy < my; dy++)
for (int dx = 0; dx < mx; dx++) {
val = input.getPixelDouble(
(int) px + dx,
(int) py + dy,
(int) pz + dz,
(int) pt + dt,
(int) pb + db);
weight = Math.pow(px-(int) (px + dx),2)
+ Math.pow(py-(int) (py + dy),2)
+ Math.pow(pz-(int) (pz + dz),2)
+ Math.pow(pt- (int) (pt + dt),2)
+ Math.pow(px- (int) (pb + db),2);
sum += val / weight;
norm += 1 / weight;
}
output
.setPixelDouble(x, y, z, t, b, sum
/ norm);
}
}
}
}