package fr.unistra.pelican.algorithms.conversion; import fr.unistra.pelican.*; /** * This class realizes a processing on all bands of a multiband image and return * single band image * * MASK MANAGEMENT (by Régis) : absent pixels don't count in the min/max/sum/mean calculations. * * @author Lefevre * */ public class ProcessChannels extends Algorithm { /** * Input parameter */ public Image input; /** * The operation to be computed */ public int op; public static final int MAXIMUM = 0; public static final int MINIMUM = 1; public static final int SUM = 2; public static final int AVERAGE = 3; public static final int NORM = 4; /** * Output parameter */ public Image output; /** * Constructor */ public ProcessChannels() { super.inputs = "input,op"; super.outputs = "output"; } /* * (non-Javadoc) * * @see fr.unistra.pelican.Algorithm#launch() */ public void launch() throws AlgorithmException { int xdim = input.getXDim(); int ydim = input.getYDim(); int zdim = input.getZDim(); int tdim = input.getTDim(); int bdim = input.getBDim(); if (bdim < 1) throw new AlgorithmException("The input must be a multiband image"); output = input.newInstance(xdim, ydim, zdim, tdim, 1); output.setColor(false); if (input instanceof DoubleImage) { double val; for (int t = 0; t < tdim; t++) for (int z = 0; z < zdim; z++) for (int y = 0; y < ydim; y++) for (int x = 0; x < xdim; x++) { switch (op) { case MAXIMUM: val = Double.NEGATIVE_INFINITY; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) if (input.getPixelDouble(x, y, z, t, b) > val) val = input.getPixelDouble(x, y, z, t, b); output.setPixelDouble(x, y, z, t, 0, val); break; case MINIMUM: val = Double.POSITIVE_INFINITY; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) if (input.getPixelDouble(x, y, z, t, b) < val) val = input.getPixelDouble(x, y, z, t, b); output.setPixelDouble(x, y, z, t, 0, val); break; case SUM: val = 0; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) val += input.getPixelDouble(x, y, z, t, b); output.setPixelDouble(x, y, z, t, 0, val); break; case AVERAGE: val = 0; int n = 0; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) { val += input.getPixelDouble(x, y, z, t, b); n++; } if ( n == 0 ) output.setPixelDouble( x,y,z,t,0, val ); else output.setPixelDouble( x, y, z, t, 0, (double)((double)val /(double)n) ); break; case NORM: val = 0; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) { double v=input.getPixelDouble(x, y, z, t, b); val += v*v; } output.setPixelDouble( x, y, z, t, 0, Math.sqrt(val) ); break; } } } if (input instanceof IntegerImage) { int val; for (int t = 0; t < tdim; t++) for (int z = 0; z < zdim; z++) for (int y = 0; y < ydim; y++) for (int x = 0; x < xdim; x++) { switch (op) { case MAXIMUM: val = Integer.MIN_VALUE; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) if (input.getPixelInt(x, y, z, t, b) > val) val = input.getPixelInt(x, y, z, t, b); output.setPixelInt(x, y, z, t, 0, val); break; case MINIMUM: val = Integer.MAX_VALUE; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) if (input.getPixelInt(x, y, z, t, b) < val) val = input.getPixelInt(x, y, z, t, b); output.setPixelInt(x, y, z, t, 0, val); break; case SUM: val = 0; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) val += input.getPixelInt(x, y, z, t, b); output.setPixelInt(x, y, z, t, 0, val); break; case AVERAGE: val = 0; int n = 0; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) { val += input.getPixelInt(x, y, z, t, b); n++; } if ( n == 0 ) output.setPixelInt( x,y,z,t,0, val ); else output.setPixelInt(x, y, z, t, 0, (int)((double)val /(double)n) ); break; } } } if (input instanceof ByteImage) { int val; for (int t = 0; t < tdim; t++) for (int z = 0; z < zdim; z++) for (int y = 0; y < ydim; y++) for (int x = 0; x < xdim; x++) { switch (op) { case MAXIMUM: val = 0; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) if (input.getPixelByte(x, y, z, t, b) > val) val = input.getPixelByte(x, y, z, t, b); output.setPixelByte(x, y, z, t, 0, val); break; case MINIMUM: val = 255; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) if (input.getPixelByte(x, y, z, t, b) < val) val = input.getPixelByte(x, y, z, t, b); output.setPixelByte(x, y, z, t, 0, val); break; case SUM: val = 0; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) val += input.getPixelByte(x, y, z, t, b); output.setPixelByte(x, y, z, t, 0, val); break; case AVERAGE: val = 0; int n = 0; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) { val += input.getPixelByte(x, y, z, t, b); n++; } // output.setPixelByte( x,y,z,t,0, val/bdim ); if ( n == 0 ) output.setPixelByte( x,y,z,t,0, val ); else output.setPixelByte(x, y, z, t, 0, (byte)((double)val /(double)n) ); break; } } } if (input instanceof BooleanImage) { boolean val; for (int t = 0; t < tdim; t++) for (int z = 0; z < zdim; z++) for (int y = 0; y < ydim; y++) for (int x = 0; x < xdim; x++) { switch (op) { case MAXIMUM: val = false; for (int b = 0; b < bdim && !val ; b++) if ( input.isPresent( x,y,z,t,b ) ) if (input.getPixelBoolean(x, y, z, t, b)) val = true; output.setPixelBoolean(x, y, z, t, 0, val); break; case MINIMUM: val = true; for (int b = 0; b < bdim && val ; b++) if ( input.isPresent( x,y,z,t,b ) ) if (!input.getPixelBoolean(x, y, z, t, b)) val = false; output.setPixelBoolean(x, y, z, t, 0, val); break; case SUM: System.err .println("ProcessChannels: SUM with BooleanImage not available"); break; case AVERAGE: int sum = 0; int n = 0; for (int b = 0; b < bdim; b++) if ( input.isPresent( x,y,z,t,b ) ) if (input.getPixelBoolean(x, y, z, t, b)) { sum++; n++; } // output.setPixelBoolean( x,y,z,t,0, sum > (bdim/2.0) ); output.setPixelBoolean( x,y,z,t,0, (double)sum > (double)((double)n/2.0) ); break; } } } } /** * Apply a processing on all bands of a multiband image and return a single * band image * * @param image * The multiband image * @param op * The operation to be applied * @return The graylevel image. */ @SuppressWarnings("unchecked") public static <T extends Image> T exec(T input, int op) { return (T) new ProcessChannels().process(input, op); } }