/*
* omeis.providers.re.quantum.QuantumFactory
*
* Copyright 2006 University of Dundee. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package omeis.providers.re.quantum;
import java.util.List;
import ome.model.core.Pixels;
import ome.model.display.QuantumDef;
import ome.model.enums.Family;
import omeis.providers.re.data.PlaneFactory;
/**
* Factory to create objects to carry out quantization for a given context. This
* class defines the constants to be used to identify a {@link QuantumMap}
* within a quantization context. It also defines the constants to be used to
* define the bit depth of the quantized output interval.
*
* @author Jean-Marie Burel <a
* href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author <br>
* Andrea Falconi <a
* href="mailto:a.falconi@dundee.ac.uk"> a.falconi@dundee.ac.uk</a>
* @since OME2.2
*/
public class QuantumFactory {
// NOTE: The bit-depth constants cannot be modified b/c they have a meaning.
/** Flag to select a 1-bit depth (<i>=2^1-1</i>) output interval. */
public static final int DEPTH_1BIT = 1;
/** Flag to select a 2-bit depth (<i>=2^2-1</i>) output interval. */
public static final int DEPTH_2BIT = 3;
/** Flag to select a 3-bit depth (<i>=2^3-1</i>) output interval. */
public static final int DEPTH_3BIT = 7;
/** Flag to select a 4-bit depth (<i>=2^4-1</i>) output interval. */
public static final int DEPTH_4BIT = 15;
/** Flag to select a 5-bit depth (<i>=2^5-1</i>) output interval. */
public static final int DEPTH_5BIT = 31;
/** Flag to select a 6-bit depth (<i>=2^6-1</i>) output interval. */
public static final int DEPTH_6BIT = 63;
/** Flag to select a 7-bit depth (<i>=2^7-1</i>) output interval. */
public static final int DEPTH_7BIT = 127;
/** Flag to select a 8-bit depth (<i>=2^8-1</i>) output interval. */
public static final int DEPTH_8BIT = 255;
/**
* Flag to select a linear map for the quantization process. The equation of
* the map is of the form <i>y = a*x + b</i>. The <i>a</i> and <i>b</i>
* coefficients depend on the input and output (codomain) interval of the
* map.
*/
public static final String LINEAR = "linear";
/**
* Flag to select a exponential map for the quantization process. The
* equation of the map is of the form <i>y = a*(exp(x^k)) + b</i>. The <i>a</i>
* and <i>b</i> coefficients depend on the input and output (codomain)
* interval of the map. The <i>k</i> coefficient is the one specified by
* the {@link QuantumDef context}.
*/
public static final String EXPONENTIAL = "exponential";
/**
* Flag to select a logarithmic map for the quantization process. The
* equation of the map is of the form <i>y = a*log(x) + b</i>. The <i>a</i>
* and <i>b</i> coefficients depend on the input and output (codomain)
* interval of the map.
*/
public static final String LOGARITHMIC = "logarithmic";
/**
* Flag to select a polynomial map for the quantization process. The
* equation of the map is of the form <i>y = a*x^k + b</i>. The <i>a</i>
* and <i>b</i> coefficients depend on the input and output (codomain)
* interval of the map. The <i>k</i> coefficient is the one specified by
* the {@link QuantumDef context}. Note that {@link #LINEAR} is a special
* case of polynomial (<i>k = 1</i>). We keep the {@link #LINEAR} constant
* for some UI reason but we apply the same algorithm.
*/
public static final String POLYNOMIAL = "polynomial";
/** Default value. */
public static final boolean NOISE_REDUCTION = true;
/** Enumerated list of all families. */
private List<Family> families;
/**
* Default constructor.
*
* @param families the enumerated list of all families.
*/
public QuantumFactory(List<Family> families)
{
this.families = families;
}
/**
* Helper method to retrieve a Family enumeration from the database.
*
* @param value
* The enumeration value.
* @return A family enumeration object.
*/
public Family getFamily(String value) {
for (Family family : families)
{
if (family.getValue().equals(value))
return family;
}
throw new IllegalArgumentException("Unknown family: " + value);
}
/**
* Verifies that <code>qd</code> is not <code>null</code> and has been
* properly defined.
*
* @param qd
* The definition to verify.
* @param type The pixels to handle.
* @throws IllegalArgumentException
* If the check fails.
*/
private void verifyDef(QuantumDef qd, Pixels pixels) {
if (qd == null) {
throw new NullPointerException("No quantum definition.");
}
verifyBitResolution(qd.getBitResolution().intValue());
}
/**
* Verifies that <code>bitResolution</code> is one of the constants
* defined by this class.
*
* @param bitResolution
* The value to verify.
* @throws IllegalArgumentException
* If the check fails.
*/
private void verifyBitResolution(int bitResolution) {
boolean b = false;
switch (bitResolution) {
case DEPTH_1BIT:
case DEPTH_2BIT:
case DEPTH_3BIT:
case DEPTH_4BIT:
case DEPTH_5BIT:
case DEPTH_6BIT:
case DEPTH_7BIT:
case DEPTH_8BIT:
b = true;
}
if (!b) {
throw new IllegalArgumentException("Unsupported bit resolution: "
+ bitResolution + ".");
}
}
/**
* Creates a {@link QuantumStrategy} object suitable for the pixels type
* specified by <code>pd</code>.
*
* @param qd
* Defines the quantization context.
* @param pixels The pixels to handle.
* @return A {@link QuantumStrategy} object suitable for the given pixels
* type.
*/
private QuantumStrategy getQuantization(QuantumDef qd, Pixels pixels) {
String typeAsString = pixels.getPixelsType().getValue();
if (PlaneFactory.INT32.equals(typeAsString) ||
PlaneFactory.UINT32.equals(typeAsString))
return new Quantization_32_bit(qd, pixels);
else if (PlaneFactory.FLOAT_TYPE.equals(typeAsString) ||
PlaneFactory.DOUBLE_TYPE.equals(typeAsString))
return new Quantization_float(qd, pixels);
return new Quantization_8_16_bit(qd, pixels);
}
/**
* Returns a strategy to carry out the quantization process whose context is
* defined by <code>pd</code>.
*
* @param qd
* Defines the quantization context. Mustn't be <code>null</code>
* and its values must have been properly specified.
* @param pixels The pixels to handle.
* @return A {@link QuantumStrategy} suitable for the specified context.
*/
public QuantumStrategy getStrategy(QuantumDef qd, Pixels pixels) {
verifyDef(qd, pixels);
QuantumStrategy strg = null;
strg = getQuantization(qd, pixels);
if (strg == null) {
throw new IllegalArgumentException("Unsupported strategy");
}
return strg;
}
}