/* 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.translate; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.util.Map; import javax.media.jai.ImageLayout; import javax.media.jai.JAI; import javax.media.jai.OpImage; /** * An OpImage to translate an image by in integral number of pixels. */ public final class TranslateIntOpImage extends OpImage { private int transX; private int transY; private static ImageLayout layoutHelper(RenderedImage source, int transX, int transY) { ImageLayout layout = new ImageLayout(source.getMinX() + transX, source.getMinY() + transY, source.getWidth(), source.getHeight(), source.getTileGridXOffset() + transX, source.getTileGridYOffset() + transY, source.getTileWidth(), source.getTileHeight(), source.getSampleModel(), source.getColorModel()); return layout; } // Since this operation does not touch the data at all, we do not need // to expand the IndexColorModel private static Map configHelper(Map configuration) { Map config; if (configuration == null) { config = new RenderingHints(JAI.KEY_REPLACE_INDEX_COLOR_MODEL, Boolean.FALSE); } else { config = configuration; if (!(config.containsKey(JAI.KEY_REPLACE_INDEX_COLOR_MODEL))) { RenderingHints hints = (RenderingHints)configuration; config = (RenderingHints)hints.clone(); config.put(JAI.KEY_REPLACE_INDEX_COLOR_MODEL, Boolean.FALSE); config.remove(JAI.KEY_TILE_CACHE); } else if (config.containsKey(JAI.KEY_TILE_CACHE)) { RenderingHints hints = (RenderingHints)configuration; config = (RenderingHints)hints.clone(); config.remove(JAI.KEY_TILE_CACHE); } } return config; } /** * Construct an TranslateIntOpImage. * * @param source a RenderedImage. * @param config Configurable attributes of the image including * configuration variables indexed by * <code>RenderingHints.Key</code>s and image properties indexed * by <code>String</code>s or <code>CaselessStringKey</code>s. * This is simply forwarded to the superclass constructor. * @param transX the number of pixels of horizontal translation. * @param transY the number of pixels of vertical translation. */ public TranslateIntOpImage(RenderedImage source, Map config, int transX, int transY) { super(vectorize(source), layoutHelper(source, transX, transY), configHelper(config), false); this.transX = transX; this.transY = transY; } /** * Returns <code>false</code> as <code>computeTile()</code> invocations * return child <code>Raster</code>s of the <code>RenderedImage</code> * source and are therefore not unique objects in the global sense. */ public boolean computesUniqueTiles() { return false; } /** * Override computeTile() simply to invoke getTile(). Required * so that the TileScheduler may invoke computeTile(). This appens * because the computation of the tile is inside the getTile() method. */ public Raster computeTile(int tileX, int tileY) { return getTile(tileX, tileY); } /** * Get a tile. * * @param tileX The X index of the tile. * @param tileY The Y index of the tile. */ public Raster getTile(int tileX, int tileY) { Raster tile = getSource(0).getTile(tileX, tileY); if (tile == null) return null; return tile.createTranslatedChild(tileXToX(tileX), tileYToY(tileY)); } /** * Returns a conservative estimate of the destination region that * can potentially be affected by the pixels of a rectangle of a * given source. * * @param sourceRect the Rectangle in source coordinates. * @param sourceIndex the index of the source image. * @return a Rectangle indicating the potentially affected * destination region. or null if the region is unknown. * @throws IllegalArgumentException if the source index is * negative or greater than that of the last source. * @throws IllegalArgumentException if sourceRect is null. */ public Rectangle mapSourceRect(Rectangle sourceRect, int sourceIndex) { if ( sourceRect == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } if (sourceIndex < 0 || sourceIndex >= getNumSources()) { throw new IllegalArgumentException(JaiI18N.getString("TranslateIntOpImage0")); } Rectangle r = new Rectangle(sourceRect); r.translate(transX, transY); return r; } /** * Returns a conservative estimate of the region of a specified * source that is required in order to compute the pixels of a * given destination rectangle. * * @param destRect the Rectangle in destination coordinates. * @param sourceIndex the index of the source image. * @return a Rectangle indicating the required source region. * @throws IllegalArgumentException if the source index is * negative or greater than that of the last source. * @throws IllegalArgumentException if destRect is null. */ public Rectangle mapDestRect(Rectangle destRect, int sourceIndex) { if ( destRect == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } if (sourceIndex < 0 || sourceIndex >= getNumSources()) { throw new IllegalArgumentException(JaiI18N.getString("TranslateIntOpImage0")); } Rectangle r = new Rectangle(destRect); r.translate(-transX, -transY); return r; } }