/* 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.crop;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.util.Map;
import javax.media.jai.ImageLayout;
import javax.media.jai.PointOpImage;
/**
* An alternative implementation of JAI Crop that respects the tile cache and tile scheduler
* specified in the rendering hints.
*
* This is a clean room implementation (there are no others ways in which a Crop can be implemented,
* so it looks a lot like the original one)
*/
public class CropOpImage extends PointOpImage {
private static ImageLayout layoutHelper(RenderedImage source, float originX, float originY,
float width, float height) {
Rectangle bounds = new Rectangle2D.Float(originX, originY, width, height).getBounds();
return new ImageLayout(bounds.x, bounds.y, bounds.width, bounds.height, source
.getTileGridXOffset(), source.getTileGridYOffset(), source.getTileWidth(), source
.getTileHeight(), source.getSampleModel(), source.getColorModel());
}
/**
* Construct a CropOpImage.
*/
public CropOpImage(RenderedImage source, float originX, float originY, float width,
float height, Map configuration) {
super(source, layoutHelper(source, originX, originY, width, height), configuration, false);
}
/**
* We just relay the original tiles, or return null
*/
public boolean computesUniqueTiles() {
return false;
}
/**
* Make sure the tile scheduler ends up calling getTile
*/
public Raster computeTile(int tileX, int tileY) {
return getTile(tileX, tileY);
}
/**
* Returns a tile. Either it's fully inside, and thus we relay the original tile (in-tile
* cutting will be performed by the image layout), or we return null
*/
public Raster getTile(int tileX, int tileY) {
if (tileX >= getMinTileX() && tileX <= getMaxTileX()
&& tileY >= getMinTileY() && tileY <= getMaxTileY()) {
return getSourceImage(0).getTile(tileX, tileY);
} else {
return null;
}
}
}