/*******************************************************************************
* Copyright 2012 Geoscience Australia
*
* 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 au.gov.ga.earthsci.worldwind.common.layers.delegate.transformer;
import gov.nasa.worldwind.avlist.AVList;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.util.ArrayList;
import java.util.List;
import javax.xml.xpath.XPath;
import org.w3c.dom.Element;
import au.gov.ga.earthsci.worldwind.common.layers.delegate.IDelegate;
import au.gov.ga.earthsci.worldwind.common.layers.delegate.IDelegatorTile;
import au.gov.ga.earthsci.worldwind.common.layers.delegate.IImageTransformerDelegate;
import au.gov.ga.earthsci.worldwind.common.layers.delegate.filters.TransparentMinimumFilter;
import au.gov.ga.earthsci.worldwind.common.layers.styled.PropertySetter;
import au.gov.ga.earthsci.worldwind.common.layers.styled.StyleAndAttributeFactory;
import au.gov.ga.earthsci.worldwind.common.util.XMLUtil;
import com.jhlabs.image.AbstractBufferedImageOp;
/**
* {@link IImageTransformerDelegate} implementation that uses implementations of
* the {@link BufferedImageOp} interface to filter images. There are many such
* implementations in the jhlabs filters library, which is included with this
* project.
* <p/>
* <code><Delegate>FilterTransformer</Delegate></code>
* <p/>
* When parsing from a layer definition file, the filter list must be provided
* in the layer xml, as follows:
*
* <pre>
* <Filters>
* <Filter name="classname">
* <Property name="" value="" />
* <Property name="" value="" type="" />
* </Filter>
* <Filter name="classname" />
* ...
* </Filters>
* </pre>
*
* Where:
* <ul>
* <li>classname = Class name of the {@link BufferedImageOp} implementation. If
* the class is in the com.jhlabs.image package, the package prefix can be
* optionally omitted.
* <li>Property = Values to set on the instanciated class. The name attribute is
* the name of the setter, and the value attribute is the value to set. If the
* type attribute is included, the value is converted to type before setting,
* otherwise the type of the setter is used.
* </ul>
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
public class FilterTransformerDelegate implements IImageTransformerDelegate
{
private final static String DEFINITION_STRING = "FilterTransformer";
private final List<BufferedImageOp> filters;
public FilterTransformerDelegate()
{
this(new ArrayList<BufferedImageOp>());
}
public FilterTransformerDelegate(List<BufferedImageOp> filters)
{
this.filters = filters;
}
@Override
public IDelegate fromDefinition(String definition, Element layerElement, AVList params)
{
if (definition.toLowerCase().equals(DEFINITION_STRING.toLowerCase()))
{
List<BufferedImageOp> filters = new ArrayList<BufferedImageOp>();
XPath xpath = XMLUtil.makeXPath();
Element[] filterElements = XMLUtil.getElements(layerElement, "Filters/Filter", xpath);
if (filterElements != null)
{
for (Element filterElement : filterElements)
{
String name = XMLUtil.getText(filterElement, "@name", xpath);
try
{
Class<?> filterClass = null;
try
{
//first try class name with the local .filter package prefix
filterClass =
Class.forName(TransparentMinimumFilter.class.getPackage().getName() + "." + name);
}
catch (ClassNotFoundException e)
{
}
if (filterClass == null)
{
try
{
//next try class name with the com.jhlabs.image package prefix
filterClass =
Class.forName(AbstractBufferedImageOp.class.getPackage().getName() + "." + name);
}
catch (ClassNotFoundException e)
{
}
}
if (filterClass == null)
{
try
{
//if not found, simply try the name as the full class name
filterClass = Class.forName(name);
}
catch (ClassNotFoundException e)
{
throw new Exception("Filter not found: " + name, e);
}
}
Object filterObject = filterClass.newInstance();
if (filterObject instanceof BufferedImageOp)
{
BufferedImageOp filter = (BufferedImageOp) filterObject;
filters.add(filter);
PropertySetter setter = new PropertySetter();
StyleAndAttributeFactory.addProperties(filterElement, xpath, setter);
setter.setPropertiesFromAttributes(null, null, filter);
}
}
catch (Exception e)
{
//log exception
e.printStackTrace();
}
}
}
return new FilterTransformerDelegate(filters);
}
return null;
}
@Override
public String toDefinition(Element layerElement)
{
return DEFINITION_STRING;
}
@Override
public BufferedImage transformImage(BufferedImage image, IDelegatorTile tile)
{
if (filters != null)
{
for (BufferedImageOp filter : filters)
{
image = filter.filter(image, null);
}
}
return image;
}
}