package mil.nga.giat.geowave.adapter.raster.adapter.warp;
import java.awt.Rectangle;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.util.Map;
import javax.media.jai.BorderExtender;
import javax.media.jai.ImageLayout;
import javax.media.jai.Interpolation;
import javax.media.jai.PlanarImage;
import javax.media.jai.ROI;
import javax.media.jai.ROIShape;
import javax.media.jai.RasterAccessor;
import javax.media.jai.RasterFormatTag;
import javax.media.jai.Warp;
import javax.media.jai.iterator.RandomIter;
import com.sun.media.jai.util.ImageUtil;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import it.geosolutions.jaiext.iterators.RandomIterFactory;
import it.geosolutions.jaiext.range.Range;
/**
*
* This is code entirely intended to get around an issue on line 265 of
* WarpOpImage in jai-ext. The following code does not work if the source is
* significant lower resolution than the destination and seems unnecessary in
* general:
*
* roiTile = roi.intersect(new ROIShape(srcRectExpanded));
*
*/
@SuppressFBWarnings
abstract public class WarpOpImage extends
it.geosolutions.jaiext.warp.WarpOpImage
{
public WarpOpImage(
RenderedImage source,
ImageLayout layout,
Map<?, ?> configuration,
boolean cobbleSources,
BorderExtender extender,
Interpolation interp,
Warp warp,
double[] backgroundValues,
ROI roi,
Range noData ) {
super(
source,
layout,
configuration,
cobbleSources,
extender,
interp,
warp,
backgroundValues,
roi,
noData);
}
/**
* Warps a rectangle. If ROI is present, the intersection between ROI and
* tile bounds is calculated; The result ROI will be used for calculations
* inside the computeRect() method.
*/
protected void computeRect(
final PlanarImage[] sources,
final WritableRaster dest,
final Rectangle destRect ) {
// Retrieve format tags.
final RasterFormatTag[] formatTags = getFormatTags();
final RasterAccessor dst = new RasterAccessor(
dest,
destRect,
formatTags[1],
getColorModel());
RandomIter roiIter = null;
boolean roiContainsTile = false;
boolean roiDisjointTile = false;
// If a ROI is present, then only the part contained inside the current
// tile bounds is taken.
if (hasROI) {
Rectangle srcRectExpanded = mapDestRect(
destRect,
0);
// The tile dimension is extended for avoiding border errors
srcRectExpanded.setRect(
srcRectExpanded.getMinX() - leftPad,
srcRectExpanded.getMinY() - topPad,
srcRectExpanded.getWidth() + rightPad + leftPad,
srcRectExpanded.getHeight() + bottomPad + topPad);
if (!roiBounds.intersects(srcRectExpanded)) {
roiDisjointTile = true;
}
else {
roiContainsTile = roi.contains(srcRectExpanded);
if (!roiContainsTile) {
if (!roi.intersects(srcRectExpanded)) {
roiDisjointTile = true;
}
else {
PlanarImage roiIMG = getImage();
roiIter = RandomIterFactory.create(
roiIMG,
null,
TILE_CACHED,
ARRAY_CALC);
}
}
}
}
if (!hasROI || !roiDisjointTile) {
switch (dst.getDataType()) {
case DataBuffer.TYPE_BYTE:
computeRectByte(
sources[0],
dst,
roiIter,
roiContainsTile);
break;
case DataBuffer.TYPE_USHORT:
computeRectUShort(
sources[0],
dst,
roiIter,
roiContainsTile);
break;
case DataBuffer.TYPE_SHORT:
computeRectShort(
sources[0],
dst,
roiIter,
roiContainsTile);
break;
case DataBuffer.TYPE_INT:
computeRectInt(
sources[0],
dst,
roiIter,
roiContainsTile);
break;
case DataBuffer.TYPE_FLOAT:
computeRectFloat(
sources[0],
dst,
roiIter,
roiContainsTile);
break;
case DataBuffer.TYPE_DOUBLE:
computeRectDouble(
sources[0],
dst,
roiIter,
roiContainsTile);
break;
}
// After the calculations, the output data are copied into the
// WritableRaster
if (dst.isDataCopy()) {
dst.clampDataArrays();
dst.copyDataToRaster();
}
}
else {
// If the tile is outside the ROI, then the destination Raster is
// set to backgroundValues
if (setBackground) {
ImageUtil.fillBackground(
dest,
destRect,
backgroundValues);
}
}
}
/**
* This method provides a lazy initialization of the image associated to the
* ROI. The method uses the Double-checked locking in order to maintain
* thread-safety
*
* @return
*/
private PlanarImage getImage() {
PlanarImage img = roiImage;
if (img == null) {
synchronized (this) {
img = roiImage;
if (img == null) {
roiImage = img = roi.getAsImage();
}
}
}
return img;
}
}