package fr.unistra.pelican.algorithms.geometric;
import fr.unistra.pelican.*;
/**
* This class perform a uniform spatial subdivision of an image
*
* The supported outputs are:
* <ul>
* <li> {@link #Uniform2x2} (4 subimages) : ByteImage format
* <li> {@link #Uniform3x3} (9 subimages) : ByteImage format
* <li> {@link #Map5} (5 subimages: north,south,west,east,center) : ByteImage format
* <li> {@link #Lil22} (2x2 subimages) : all formats
* </ul>
*
* @author Erchan Aptoula, Régis Witz
*/
public class Subdivide extends Algorithm {
/** Input image. */
public Image input;
/** Subdivision method to be used. */
public int type;
/** Output images. */
public Image[] output;
/** Represents Uniform2x2 method. */
public static final int Uniform2x2 = 0;
/** Represents Uniform3x3 method. */
public static final int Uniform3x3 = 1;
/** Represents Map5 method. */
public static final int Map5 = 2;
/** Represents Lil4 method.
* This method subdivides an input image into as much
* littles 2 pixels x 2 pixels subimages as possible.
*/
public static final int Lil22 = 3;
/** Default constructor. */
public Subdivide() {
super.inputs = "input,type";
super.outputs = "output";
}
/**
*
* @param input input image
* @param type subdivision type
* @return output images
*/
public static Image[] exec(Image input,Integer type)
{
return (Image[]) new Subdivide().process(input,type);
}
private void computeMap5Kernel( int k, int xOffset, int yOffset, int xSize, int ySize ) {
output[k] = new ByteImage( xSize,ySize,1,1,input.getBDim() );
for ( int b = 0 ; b < input.getBDim() ; b++ )
for ( int x = 0 ; x < xSize; x++ )
for ( int y = 0 ; y < ySize; y++ )
output[k].setPixelXYBByte( x,y,b,
input.getPixelXYBByte( x+xOffset, y+yOffset, b ) );
}
/*
* (non-Javadoc)
* @see fr.unistra.pelican.Algorithm#launch()
*/
public void launch() throws AlgorithmException {
int _xDim,_yDim;
switch ( this.type ) {
case Uniform2x2 :
output = new Image[4];
_xDim = input.getXDim() / 2;
_yDim = input.getYDim() / 2;
for (int _x = 0; _x < 2; _x++) {
for (int _y = 0; _y < 2; _y++) {
output[_x * 2 + _y] = new ByteImage(_xDim, _yDim, 1, 1,
input.getBDim());
// fill it up
for (int b = 0; b < input.getBDim(); b++) {
for (int x = _xDim * _x; x < _xDim * (_x + 1); x++) {
for (int y = _yDim * _y; y < _yDim * (_y + 1); y++) {
output[_x * 2 + _y].setPixelXYBByte(x - _xDim
* _x, y - _yDim * _y, b, input
.getPixelXYBByte(x, y, b));
}
}
}
}
}
break;
case Uniform3x3 :
output = new Image[9];
_xDim = input.getXDim() / 3;
_yDim = input.getYDim() / 3;
for (int _x = 0; _x < 3; _x++) {
for (int _y = 0; _y < 3; _y++) {
output[_x * 3 + _y] = new ByteImage(_xDim, _yDim, 1, 1,
input.getBDim());
// fill it up
for (int b = 0; b < input.getBDim(); b++) {
for (int x = _xDim * _x; x < _xDim * (_x + 1); x++) {
for (int y = _yDim * _y; y < _yDim * (_y + 1); y++) {
output[_x * 3 + _y].setPixelXYBByte(x - _xDim
* _x, y - _yDim * _y, b, input
.getPixelXYBByte(x, y, b));
}
}
}
}
}
break;
case Map5 :
output = new Image[5];
_xDim = (int) Math.ceil( input.getXDim()*0.25 );
_yDim = (int) Math.ceil( input.getYDim()*0.25 );
// compute NORTH
this.computeMap5Kernel( 0, 0,0, input.getXDim(),_yDim );
// compute SOUTH
this.computeMap5Kernel( 1, 0,input.getYDim()-_yDim, input.getXDim(),_yDim );
// compute WEST
this.computeMap5Kernel( 2, 0,_yDim, _xDim,input.getYDim()-2*_yDim );
// compute CENTER
this.computeMap5Kernel( 3,_xDim,_yDim,input.getXDim()-2*_xDim,input.getYDim()-2*_yDim );
// compute EAST
this.computeMap5Kernel( 4, input.getXDim()-_xDim,_yDim, _xDim,input.getYDim()-2*_yDim );
break;
case Lil22 :
// nb. in java int = int / int is the division floored.
int xdim = this.input.getXDim() / 2;
int ydim = this.input.getYDim() / 2;
int zdim = this.input.getZDim();
int tdim = this.input.getTDim();
int bdim = this.input.getBDim();
this.output = new Image[ xdim*ydim ];
int index;
double p;
for ( int y = 0 ; y < ydim ; y++ ) {
_yDim = y*2;
for ( int x = 0 ; x < xdim ; x++ ) {
_xDim = x*2;
index = y*xdim+x;
if ( this.input instanceof BooleanImage )
this.output[ index ] = new BooleanImage( 2,2, zdim,tdim,bdim );
else if ( this.input instanceof ByteImage )
this.output[ index ] = new ByteImage( 2,2, zdim,tdim,bdim );
else if ( this.input instanceof IntegerImage )
this.output[ index ] = new IntegerImage( 2,2, zdim,tdim,bdim );
else if ( this.input instanceof DoubleImage )
this.output[ index ] = new DoubleImage( 2,2, zdim,tdim,bdim );
for ( int t = 0 ; t < tdim ; t++ ) {
for ( int z = 0 ; z < zdim ; z++ ) {
for ( int b = 0 ; b < bdim ; b++ ) {
p = this.input.getPixelXYZTBDouble( _xDim ,_yDim , z,t,b );
this.output[ index ].setPixelXYZTBDouble( 0,0,z,t,b, p );
p = this.input.getPixelXYZTBDouble( _xDim+1,_yDim , z,t,b );
this.output[ index ].setPixelXYZTBDouble( 1,0,z,t,b, p );
p = this.input.getPixelXYZTBDouble( _xDim ,_yDim+1, z,t,b );
this.output[ index ].setPixelXYZTBDouble( 0,1,z,t,b, p );
p = this.input.getPixelXYZTBDouble( _xDim+1,_yDim+1, z,t,b );
this.output[ index ].setPixelXYZTBDouble( 1,1,z,t,b, p );
} } }
}
}
break;
default : throw new PelicanException( "Unsupported subdivision type." );
}
}
}