/* JAI-Ext - OpenSource Java Advanced Image Extensions Library * http://www.geo-solutions.it/ * Copyright 2014 GeoSolutions * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package it.geosolutions.jaiext.algebra; import it.geosolutions.jaiext.range.Range; import java.awt.RenderingHints; import java.awt.image.DataBuffer; import java.awt.image.RenderedImage; import java.awt.image.renderable.RenderableImage; import javax.media.jai.JAI; import javax.media.jai.OperationDescriptorImpl; import javax.media.jai.ParameterBlockJAI; import javax.media.jai.ROI; import javax.media.jai.RenderableOp; import javax.media.jai.RenderedOp; import javax.media.jai.registry.RenderableRegistryMode; import javax.media.jai.registry.RenderedRegistryMode; import com.sun.media.jai.util.ImageUtil; public class AlgebraDescriptor extends OperationDescriptorImpl { public enum Operator { SUM(0, 0, true) { @Override public byte calculate(byte... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] += values[i]; } } return values[0]; } @Override public short calculate(boolean isUshort, short... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] += values[i]; } } return values[0]; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] += values[i]; } } return values[0]; } @Override public float calculate(float... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] += values[i]; } } return values[0]; } @Override public double calculate(double... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] += values[i]; } } return values[0]; } @Override public long calculateL(long... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] += values[i]; } } return values[0]; } }, SUBTRACT(1, 0, true) { @Override public byte calculate(byte... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] -= values[i]; } } return values[0]; } @Override public short calculate(boolean isUshort, short... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] -= values[i]; } } return values[0]; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] -= values[i]; } } return values[0]; } @Override public float calculate(float... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] -= values[i]; } } return values[0]; } @Override public double calculate(double... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] -= values[i]; } } return values[0]; } @Override public long calculateL(long... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] -= values[i]; } } return values[0]; } }, MULTIPLY(2, 1, true) { @Override public byte calculate(byte... values) { long temp = 1; if (values.length > 1) { for (int i = 0; i < values.length; i++) { temp *= values[i]; } if (temp > Byte.MAX_VALUE) { values[0] = Byte.MAX_VALUE; } else if (temp < Byte.MIN_VALUE) { values[0] = Byte.MIN_VALUE; } else { values[0] = (byte) temp; } } return values[0]; } @Override public short calculate(boolean isUshort, short... values) { long temp = 1; if (values.length > 1) { for (int i = 0; i < values.length; i++) { temp *= values[i]; } if (isUshort) { if (temp > USHORT_MAX_VALUE) { values[0] = (short) USHORT_MAX_VALUE; } else if (temp < 0) { values[0] = 0; } else { values[0] = (short) temp; } } else { if (temp > Short.MAX_VALUE) { values[0] = Short.MAX_VALUE; } else if (temp < Short.MIN_VALUE) { values[0] = Short.MIN_VALUE; } else { values[0] = (short) temp; } } } return values[0]; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { long temp = 1; if (values.length > 1) { for (int i = 0; i < values.length; i++) { temp *= values[i]; } if (temp > Integer.MAX_VALUE) { values[0] = Integer.MAX_VALUE; } else if (temp < Integer.MIN_VALUE) { values[0] = Integer.MIN_VALUE; } else { values[0] = (int) temp; } } return values[0]; } @Override public float calculate(float... values) { double temp = 1; if (values.length > 1) { for (int i = 0; i < values.length; i++) { temp *= values[i]; } if (temp > Float.MAX_VALUE) { values[0] = Float.MAX_VALUE; } else if (temp < -Float.MAX_VALUE) { values[0] = -Float.MAX_VALUE; } else { values[0] = (float) temp; } } return values[0]; } @Override public double calculate(double... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] *= values[i]; } } return values[0]; } @Override public long calculateL(long... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] *= values[i]; } } return values[0]; } }, DIVIDE(3, 1, true) { @Override public byte calculate(byte... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { if (values[i] == 0 && values[0] >= 0) { values[0] = Byte.MAX_VALUE; } else if (values[i] == 0 && values[0] < 0) { values[0] = Byte.MIN_VALUE; } else { values[0] /= values[i]; } } } return values[0]; } @Override public short calculate(boolean isUshort, short... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { if (values[i] == 0 && values[0] >= 0) { values[0] = (short) (isUshort ? USHORT_MAX_VALUE : Short.MAX_VALUE); } else if (values[i] == 0 && values[0] < 0) { values[0] = isUshort ? 0 : Short.MIN_VALUE; } else { values[0] /= values[i]; } } } return values[0]; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { if (values[i] == 0 && values[0] >= 0) { values[0] = Integer.MAX_VALUE; } else if (values[i] == 0 && values[0] < 0) { values[0] = Integer.MIN_VALUE; } else { values[0] /= values[i]; } } } return values[0]; } @Override public float calculate(float... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] /= values[i]; } } return values[0]; } @Override public double calculate(double... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] /= values[i]; } } return values[0]; } @Override public long calculateL(long... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { if (values[i] == 0 && values[0] >= 0) { values[0] = Long.MAX_VALUE; } else if (values[i] == 0 && values[0] < 0) { values[0] = Long.MIN_VALUE; } else { values[0] /= values[i]; } } } return values[0]; } }, AND(4, Long.MAX_VALUE, true) { @Override public byte calculate(byte... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] &= values[i]; } } return values[0]; } @Override public short calculate(boolean isUshort, short... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] &= values[i]; } } return values[0]; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] &= values[i]; } } return values[0]; } @Override public float calculate(float... values) { throw new UnsupportedOperationException( "Float data type is not supported for this operation"); } @Override public double calculate(double... values) { throw new UnsupportedOperationException( "Double data type is not supported for this operation"); } @Override public long calculateL(long... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] &= values[i]; } } return values[0]; } public boolean isDataTypeSupported(int dataType) { return dataType != DataBuffer.TYPE_FLOAT && dataType != DataBuffer.TYPE_DOUBLE; } }, OR(5, 0, true) { @Override public byte calculate(byte... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] |= values[i]; } } return values[0]; } @Override public short calculate(boolean isUshort, short... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] |= values[i]; } } return values[0]; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] |= values[i]; } } return values[0]; } @Override public float calculate(float... values) { throw new UnsupportedOperationException( "Float data type is not supported for this operation"); } @Override public double calculate(double... values) { throw new UnsupportedOperationException( "Double data type is not supported for this operation"); } @Override public long calculateL(long... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] |= values[i]; } } return values[0]; } public boolean isDataTypeSupported(int dataType) { return dataType != DataBuffer.TYPE_FLOAT && dataType != DataBuffer.TYPE_DOUBLE; } }, NOT(6, 0, false) { @Override public byte calculate(byte... values) { return (byte) ~values[0]; } @Override public short calculate(boolean isUshort, short... values) { return (short) ~values[0]; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { return ~values[0]; } @Override public float calculate(float... values) { throw new UnsupportedOperationException( "Float data type is not supported for this operation"); } @Override public double calculate(double... values) { throw new UnsupportedOperationException( "Double data type is not supported for this operation"); } @Override public long calculateL(long... values) { return ~values[0]; } public boolean isDataTypeSupported(int dataType) { return dataType != DataBuffer.TYPE_FLOAT && dataType != DataBuffer.TYPE_DOUBLE; } }, XOR(7, 0, true) { @Override public byte calculate(byte... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] ^= values[i]; } } return values[0]; } @Override public short calculate(boolean isUshort, short... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] ^= values[i]; } } return values[0]; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] ^= values[i]; } } return values[0]; } @Override public float calculate(float... values) { throw new UnsupportedOperationException( "Float data type is not supported for this operation"); } @Override public double calculate(double... values) { throw new UnsupportedOperationException( "Double data type is not supported for this operation"); } @Override public long calculateL(long... values) { if (values.length > 1) { for (int i = 1; i < values.length; i++) { values[0] ^= values[i]; } } return values[0]; } public boolean isDataTypeSupported(int dataType) { return dataType != DataBuffer.TYPE_FLOAT && dataType != DataBuffer.TYPE_DOUBLE; } }, EXP(8, 0, false) { private byte[] byteTable; protected void initialization() { if (byteTable != null) return; byteTable = new byte[0x100]; /* * exp(5) = 148.4131591... exp(6) = 403.4287935... Calculate up to 5 and set the rest to the maximum value. */ byteTable[0] = 1; for (int i = 1; i < 6; i++) { byteTable[i] = (byte) (Math.exp(i) + 0.5); } for (int i = 6; i < 0x100; i++) { byteTable[i] = (byte) ImageUtil.BYTE_MASK; } } @Override public byte calculate(byte... values) { return byteTable[values[0] & ImageUtil.BYTE_MASK]; } @Override public short calculate(boolean isUshort, short... values) { double value = values[0]; if (isUshort) { value = values[0] & ImageUtil.USHORT_MASK; if (value == 0) { return 1; } else if (value > USHORT_UPPER_BOUND) { return (short) ImageUtil.USHORT_MASK; } else { return (short) (Math.exp(value) + 0.5); } } else { if (value < LOWER_BOUND) { return 0; } else if (value == 0) { return 1; } else if (value > SHORT_UPPER_BOUND) { return Short.MAX_VALUE; } else { return (short) (Math.exp(value) + 0.5); } } } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { double value = values[0]; if (value < LOWER_BOUND) { return 0; } else if (value == 0) { return 1; } else if (value > INT_UPPER_BOUND) { return Integer.MAX_VALUE; } else { return (int) (Math.exp(value) + 0.5); } } @Override public float calculate(float... values) { return (float) Math.exp(values[0]); } @Override public double calculate(double... values) { return Math.exp(values[0]); } @Override public long calculateL(long... values) { double value = values[0]; if (value < LOWER_BOUND) { return 0; } else if (value == 0) { return 1; } else if (value > LONG_UPPER_BOUND) { return Long.MAX_VALUE; } else { return (long) (Math.exp(value) + 0.5); } } @Override public boolean isUshortSupported() { return true; } }, LOG(9, 0, false) { private byte[] byteTable; protected void initialization() { if (byteTable != null) return; byteTable = new byte[0x100]; byteTable[0] = 0; // minimum byte value byteTable[1] = 0; for (int i = 2; i < 0x100; i++) { byteTable[i] = (byte) (Math.log(i) + 0.5); } } @Override public byte calculate(byte... values) { return byteTable[values[0] & ImageUtil.BYTE_MASK]; } @Override public short calculate(boolean isUshort, short... values) { return (short) Math .log((isUshort ? values[0] & ImageUtil.USHORT_MASK : values[0]) + 0.5); } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { double value = values[0]; if (value > 0) { return (int) (Math.log(value) + 0.5); } else if (value == 0) { return 0; } else { return -1; } } @Override public float calculate(float... values) { return (float) Math.log(values[0]); } @Override public double calculate(double... values) { return Math.log(values[0]); } @Override public long calculateL(long... values) { double value = values[0]; if (value > 0) { return (long) (Math.log(value) + 0.5); } else if (value == 0) { return 0; } else { return -1; } } @Override public boolean isUshortSupported() { return true; } }, ABSOLUTE(10, 0, false) { @Override public byte calculate(byte... values) { return values[0]; } @Override public short calculate(boolean isUshort, short... values) { if (isUshort) { return values[0]; } short value = values[0]; if ((value != Short.MIN_VALUE) && (value & Short.MIN_VALUE) != 0) { // negative value return (short) -values[0]; } else { // It is either the minimum of short // or a positive number; return values[0]; } } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { int value = values[0]; if ((value != Integer.MIN_VALUE) && (value & Integer.MIN_VALUE) != 0) { // negative value return -values[0]; } else { // It is either the minimum of integer // or a positive number; return values[0]; } } @Override public float calculate(float... values) { if (values[0] <= 0.0f) { return 0.0f - values[0]; } else { return values[0]; } } @Override public double calculate(double... values) { if (values[0] <= 0.0d) { return 0.0d - values[0]; } else { return values[0]; } } @Override public long calculateL(long... values) { long value = values[0]; if ((value != Long.MIN_VALUE) && (value & Long.MIN_VALUE) != 0) { // negative value return -values[0]; } else { // It is either the minimum of long // or a positive number; return values[0]; } } @Override public boolean isUshortSupported() { return true; } }, INVERT(11, 0, false) { @Override public byte calculate(byte... values) { return (byte) (255 - (values[0] & 0xFF)); } @Override public short calculate(boolean isUshort, short... values) { return (short) (isUshort ? USHORT_MAX_VALUE - values[0] : (Short.MAX_VALUE - values[0])); } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { return Integer.MAX_VALUE - values[0]; } @Override public float calculate(float... values) { throw new UnsupportedOperationException( "Float data type is not supported for this operation"); } @Override public double calculate(double... values) { throw new UnsupportedOperationException( "Double data type is not supported for this operation"); } @Override public long calculateL(long... values) { return Long.MAX_VALUE - values[0]; } @Override public boolean isUshortSupported() { return true; } public boolean isDataTypeSupported(int dataType) { return dataType != DataBuffer.TYPE_FLOAT && dataType != DataBuffer.TYPE_DOUBLE; } }, DIVIDE_INTO(12, 0, true) { @Override public byte calculate(byte... values) { if (values.length > 1) { if(values.length == 2){ if (values[0] == 0 && values[1] >= 0) { return Byte.MAX_VALUE; } else if (values[0] == 0 && values[1] < 0) { return Byte.MIN_VALUE; } else { return (byte) (values[1] / values[0]); } } else { int result = 0; int first = values.length - 1; for (int i = first; i <= 0; i--) { if(i == 0){ return (byte) result; } else if(i == first){ result = values[i]; }else{ if (values[i - 1] == 0 && values[i] >= 0) { result = Byte.MAX_VALUE; } else if (values[i - 1] == 0 && values[i] < 0) { result = Byte.MIN_VALUE; } else { result = result / values[i - 1]; } } } } } return values[0]; } @Override public short calculate(boolean isUshort, short... values) { if (values.length > 1) { if(values.length == 2){ if (values[0] == 0 && values[1] >= 0) { return (short) (isUshort ? USHORT_MAX_VALUE : Short.MAX_VALUE); } else if (values[0] == 0 && values[1] < 0) { return (short) (isUshort ? USHORT_MAX_VALUE : Short.MAX_VALUE); } else { return (short) (values[1] / values[0]); } } else { int result = 0; int first = values.length - 1; for (int i = first; i <= 0; i--) { if(i == 0){ return (short) result; } else if(i == first){ result = values[i]; }else{ if (values[i - 1] == 0 && values[i] >= 0) { result = (short) (isUshort ? USHORT_MAX_VALUE : Short.MAX_VALUE); } else if (values[i - 1] == 0 && values[i] < 0) { result = (short) (isUshort ? USHORT_MAX_VALUE : Short.MAX_VALUE); } else { result = result / values[i - 1]; } } } } } return values[0]; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { if (values.length > 1) { if(values.length == 2){ if (values[0] == 0 && values[1] >= 0) { return Integer.MAX_VALUE; } else if (values[0] == 0 && values[1] < 0) { return Integer.MIN_VALUE; } else { return (int) (values[1] / values[0]); } } else { long result = 0; int first = values.length - 1; for (int i = first; i <= 0; i--) { if(i == 0){ return (int) result; } else if(i == first){ result = values[i]; }else{ if (values[i - 1] == 0 && values[i] >= 0) { result = Integer.MAX_VALUE; } else if (values[i - 1] == 0 && values[i] < 0) { result = Integer.MIN_VALUE; } else { result = result / values[i - 1]; } } } } } return values[0]; } @Override public float calculate(float... values) { if (values.length > 1) { if(values.length == 2){ return values[1]/values[0]; } else { double result = 0; int first = values.length - 1; for (int i = first; i <= 0; i--) { if(i == 0){ return (float) result; } else if(i == first){ result = values[i]; }else{ result = result / values[i - 1]; } } } } return values[0]; } @Override public double calculate(double... values) { if (values.length > 1) { if(values.length == 2){ return values[1]/values[0]; } else { double result = 0; int first = values.length - 1; for (int i = first; i <= 0; i--) { if(i == 0){ return result; } else if(i == first){ result = values[i]; }else{ result = result / values[i - 1]; } } } } return values[0]; } @Override public long calculateL(long... values) { if (values.length > 1) { if(values.length == 2){ if (values[0] == 0 && values[1] >= 0) { return Long.MAX_VALUE; } else if (values[0] == 0 && values[1] < 0) { return Long.MIN_VALUE; } else { return (values[1] / values[0]); } } else { long result = 0; int first = values.length - 1; for (int i = first; i <= 0; i--) { if(i == 0){ return (int) result; } else if(i == first){ result = values[i]; }else{ if (values[i - 1] == 0 && values[i] >= 0) { result = Long.MAX_VALUE; } else if (values[i - 1] == 0 && values[i] < 0) { result = Long.MIN_VALUE; } else { result = result / values[i - 1]; } } } } } return values[0]; } },SUBTRACT_FROM(13, 0, true) { @Override public byte calculate(byte... values) { int length = values.length; byte result = values[length - 1]; if (length > 1) { for (int i = length -2; i >= 0; i--) { result -= values[i]; } } return result; } @Override public short calculate(boolean isUshort, short... values) { int length = values.length; short result = values[length - 1]; if (length > 1) { for (int i = length -2; i >= 0; i--) { result -= values[i]; } } return result; } @Override public short calculate(short... values) { return calculate(false, values); } @Override public int calculate(int... values) { int length = values.length; int result = values[length - 1]; if (length > 1) { for (int i = length -2; i >= 0; i--) { result -= values[i]; } } return result; } @Override public float calculate(float... values) { int length = values.length; float result = values[length - 1]; if (length > 1) { for (int i = length -2; i >= 0; i--) { result -= values[i]; } } return result; } @Override public double calculate(double... values) { int length = values.length; double result = values[length - 1]; if (length > 1) { for (int i = length -2; i >= 0; i--) { result -= values[i]; } } return result; } @Override public long calculateL(long... values) { int length = values.length; long result = values[length - 1]; if (length > 1) { for (int i = length -2; i >= 0; i--) { result -= values[i]; } } return result; } }; private final double nullValue; private final int type; private final boolean supportsMultipleValues; private Operator(int type, double nullValue, boolean supportsMultipleValues) { this.nullValue = nullValue; this.type = type; this.supportsMultipleValues = supportsMultipleValues; initialization(); } protected void initialization() { } /** * The largest unsigned short to get a non-overflowed exponential result. i.e. cloeset to 65536. exp(11) = 59874.14171, exp(12) = 162754.7914 */ private static int USHORT_UPPER_BOUND = 11; /** * The largest short to get a non-overflowed exponential result. i.e. closest to 32767. exp(10) = 22026.46579, exp(11) = 59874.14171 */ public static int SHORT_UPPER_BOUND = 10; /** * The largest int to get a non-overflowed exponential result. i.e. closest to 2**31-1 = 2147483647. exp(21) = 1318815734, exp(22) = * 3584912846. */ public static int INT_UPPER_BOUND = 21; /** * The largest int to get a non-overflowed exponential result. i.e. closest to 2**63-1 */ public static int LONG_UPPER_BOUND = 43; /** * The smallest integer to get a non-zero exponential result is 0. i.e. exp(0) = 1; exp(-1) = 0.367879441, which will be stored as 0. all * other negative values will result in 0. */ public static int LOWER_BOUND = 0; /** * Ushort maximum allowed value */ public static int USHORT_MAX_VALUE = Short.MAX_VALUE - Short.MIN_VALUE; public abstract byte calculate(byte... values); public abstract short calculate(short... values); public abstract short calculate(boolean isUshort, short... values); public abstract int calculate(int... values); public abstract float calculate(float... values); public abstract double calculate(double... values); public abstract long calculateL(long... values); public boolean isDataTypeSupported(int dataType) { return true; } public boolean supportsMultipleValues() { return supportsMultipleValues; } public boolean isUshortSupported() { return false; } public double getNullValue() { return nullValue; } public int getType() { return type; } } public final static int OPERATION_INDEX = 0; public final static int ROI_INDEX = 1; public final static int RANGE_INDEX = 2; public final static int DEST_NODATA_INDEX = 3; /** * The resource strings that provide the general documentation and specify the parameter list for this operation. */ private static final String[][] resources = { { "GlobalName", "algebric" }, { "LocalName", "algebric" }, { "Vendor", "it.geosolutions.jaiext" }, { "Description", "This class executes the operation selected by the user on each pixel of the source images " }, { "DocURL", "Not Defined" }, { "Version", "1.0" }, { "arg0Desc", "Operation to execute" }, { "arg1Desc", "ROI object used" }, { "arg2Desc", "No Data Range used" }, { "arg3Desc", "Output value for No Data" }, }; /** * Input Parameter name */ private static final String[] paramNames = { "operation", "roi", "noData", "destinationNoData" }; /** * Input Parameter class */ private static final Class[] paramClasses = { Operator.class, javax.media.jai.ROI.class, it.geosolutions.jaiext.range.Range.class, Double.class }; /** * Input Parameter default values */ private static final Object[] paramDefaults = { null, null, null, 0d }; /** Constructor. */ public AlgebraDescriptor() { super(resources, paramClasses, paramNames, paramDefaults); } /** Returns <code>true</code> since renderable operation is supported. */ public boolean isRenderableSupported() { return true; } /** * Executes the selected operation on an image array. * * <p> * Creates a <code>ParameterBlockJAI</code> from all supplied arguments except <code>hints</code> and invokes * {@link JAI#create(String,ParameterBlock,RenderingHints)}. * * @see JAI * @see ParameterBlockJAI * @see RenderedOp * * @param op operation to execute * @param roi optional ROI object * @param optional nodata range for checking nodata * @param destinationNoData value to set for destination NoData * @param sources <code>RenderedImage</code> sources. * @param hints The <code>RenderingHints</code> to use. May be <code>null</code>. * @return The <code>RenderedOp</code> destination. * @throws IllegalArgumentException if <code>source</code> are <code>0</code>. */ public static RenderedOp create(Operator op, ROI roi, Range noData, double destinationNoData, RenderingHints hints, RenderedImage... sources) { ParameterBlockJAI pb = new ParameterBlockJAI("algebric", RenderedRegistryMode.MODE_NAME); int numSources = sources.length; for (int i = 0; i < numSources; i++) { RenderedImage img = sources[i]; if (img != null) { pb.setSource(img, i); } } if (pb.getNumSources() == 0) { throw new IllegalArgumentException("The input images are Null"); } pb.setParameter("operation", op); pb.setParameter("roi", roi); pb.setParameter("noData", noData); pb.setParameter("destinationNoData", destinationNoData); return JAI.create("algebric", pb, hints); } /** * Executes the selected operation on an image array. * * <p> * Creates a <code>ParameterBlockJAI</code> from all supplied arguments except <code>hints</code> and invokes * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}. * * @see JAI * @see ParameterBlockJAI * @see RenderableOp * * @param op operation to execute * @param roi optional ROI object * @param optional nodata range for checking nodata * @param destinationNoData value to set for destination NoData * @param sources <code>RenderableImage</code> sources. * @param hints The <code>RenderingHints</code> to use. May be <code>null</code>. * @return The <code>RenderableOp</code> destination. * @throws IllegalArgumentException if <code>source</code> are <code>0</code>. */ public static RenderableOp createRenderable(Operator op, ROI roi, Range noData, double destinationNoData, RenderingHints hints, RenderableImage... sources) { ParameterBlockJAI pb = new ParameterBlockJAI("algebric", RenderableRegistryMode.MODE_NAME); int numSources = sources.length; for (int i = 0; i < numSources; i++) { RenderableImage img = sources[i]; if (img != null) { pb.setSource(img, i); } } if (pb.getNumSources() == 0) { throw new IllegalArgumentException("The input images are Null"); } pb.setParameter("operation", op); pb.setParameter("roi", roi); pb.setParameter("noData", noData); pb.setParameter("destinationNoData", destinationNoData); return JAI.createRenderable("algebric", pb, hints); } }