001: /*
002: * $RCSfile: CropOpImage.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:56:21 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.Point;
015: import java.awt.Rectangle;
016: import java.awt.geom.Rectangle2D;
017: import java.awt.image.Raster;
018: import java.awt.image.RenderedImage;
019: import java.awt.image.WritableRaster;
020: import java.util.Vector;
021: import javax.media.jai.ImageLayout;
022: import javax.media.jai.PointOpImage;
023: import javax.media.jai.RasterFactory;
024:
025: /**
026: * An OpImage to crop an image by a rectangular region.
027: *
028: * <p> Tiles that are completely inside or intersect the cropped region
029: * (this image's bounds) are simply forwarded from the source. Do NOT
030: * create a child raster even if a tile is not contained in this image's
031: * bounds. Tiles that are outside the croppped region result in a
032: * <code>null</code> return.
033: *
034: * <p> This operator maintains the source image's tile grid setting and
035: * sample and color models.
036: *
037: *
038: * @since EA4
039: */
040: final class CropOpImage extends PointOpImage {
041:
042: private static ImageLayout layoutHelper(RenderedImage source,
043: float originX, float originY, float width, float height) {
044: // Get minimum bounding box.
045: Rectangle bounds = new Rectangle2D.Float(originX, originY,
046: width, height).getBounds();
047:
048: return new ImageLayout(bounds.x, bounds.y, bounds.width,
049: bounds.height, source.getTileGridXOffset(), source
050: .getTileGridYOffset(), source.getTileWidth(),
051: source.getTileHeight(), source.getSampleModel(), source
052: .getColorModel());
053:
054: }
055:
056: /**
057: * Construct an CropOpImage.
058: *
059: * @param source a RenderedImage.
060: * @param originX the new cropping rectangle x origin.
061: * @param originY the new cropping rectangle y origin.
062: * @param width the width of the cropping rectangle.
063: * @param height the width of the cropping rectangle.
064: */
065: public CropOpImage(RenderedImage source, float originX,
066: float originY, float width, float height) {
067: super (source, layoutHelper(source, originX, originY, width,
068: height), null, false);
069: }
070:
071: /**
072: * Returns <code>false</code> as <code>computeTile()</code> invocations
073: * are forwarded to the <code>RenderedImage</code> source and are
074: * therefore not unique objects in the global sense.
075: */
076: public boolean computesUniqueTiles() {
077: return false;
078: }
079:
080: /**
081: * Override computeTile() simply to invoke getTile(). Required
082: * so that the TileScheduler may invoke computeTile().
083: */
084: public Raster computeTile(int tileX, int tileY) {
085: return getTile(tileX, tileY);
086: }
087:
088: /**
089: * Returns a tile.
090: *
091: * <p> For those tiles that are completely contained in or intersect
092: * with this image's bounds (the cropped region), simply returns the
093: * source tile. Tiles that are outside this image's bound result in
094: * <code>null</code> return.
095: *
096: * @param tileX The X index of the tile.
097: * @param tileY The Y index of the tile.
098: */
099: public Raster getTile(int tileX, int tileY) {
100: Raster tile = null; // the requested tile, to be returned
101:
102: /* Make sure the requested tile is inside this image's boundary. */
103: if (tileX >= getMinTileX() && tileX <= getMaxTileX()
104: && tileY >= getMinTileY() && tileY <= getMaxTileY()) {
105: /*
106: * Get the source tile.
107: * Do NOT create a child Raster even if the tile is not contained
108: * but merely intersects this image's bounds.
109: */
110: tile = getSourceImage(0).getTile(tileX, tileY);
111: }
112:
113: return tile;
114: }
115: }
|