001: /*
002: * $RCSfile: BorderOpImage.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:16 $
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.image.ColorModel;
017: import java.awt.image.DataBuffer;
018: import java.awt.image.Raster;
019: import java.awt.image.RenderedImage;
020: import java.awt.image.WritableRaster;
021: import javax.media.jai.BorderExtender;
022: import javax.media.jai.BorderExtenderConstant;
023: import javax.media.jai.ImageLayout;
024: import javax.media.jai.IntegerSequence;
025: import javax.media.jai.OpImage;
026: import javax.media.jai.PlanarImage;
027: import javax.media.jai.RasterFactory;
028: import javax.media.jai.RasterFormatTag;
029: import javax.media.jai.RasterAccessor;
030: import javax.media.jai.RasterFormatTag;
031: import java.util.Map;
032: import javax.media.jai.iterator.RandomIter;
033: import javax.media.jai.iterator.RandomIterFactory;
034: import javax.media.jai.operator.BorderDescriptor;
035: import com.sun.media.jai.util.ImageUtil;
036:
037: /**
038: * An <code>OpImage</code> implementing the "border" operation.
039: *
040: * <p>It adds a border around a source image. The size of the border
041: * is specified by the left, right, top, and bottom padding parameters.
042: * The border may be filled in a variety of ways specified by the
043: * border type parameter, defined in
044: * <code>javax.media.jai.operator.BorderDescriptor</code>:
045: * <ul>
046: * <li> it may be extended with zeros (BORDER_ZERO_FILL);
047: * <li> it may be extended with a constant set of values (BORDER_CONST_FILL);
048: * <li) it may be created by copying the edge and corner pixels
049: * (BORDER_EXTEND);
050: * <li> it may be created by reflection about the edges of the image
051: * (BORDER_REFLECT); or,
052: * <li> it may be extended by "wrapping" the image plane toroidally,
053: * that is, joining opposite edges of the image.
054: * </ul>
055: *
056: * <p>When choosing the <code>BORDER_CONST_FILL</code> option, an array
057: * of constants must be supplied. The array must have at least one element,
058: * in which case this same constant is applied to all image bands. Or,
059: * it may have a different constant entry for each cooresponding band.
060: * For all other border types, this <code>constants</code> parameter may
061: * be <code>null</code>.
062: *
063: * <p>The layout information for this image may be specified via the
064: * <code>layout</code> parameter. However, due to the nature of this
065: * operation, the <code>minX</code>, <code>minY</code>, <code>width</code>,
066: * and <code>height</code>, if specified, will be ignored. They will
067: * be calculated based on the source's dimensions and the padding values.
068: * Likewise, the <code>SampleModel</code> and </code>ColorModel</code> hints
069: * will be ignored.
070: *
071: * @see javax.media.jai.OpImage
072: * @see javax.media.jai.operator.BorderDescriptor
073: * @see BorderRIF
074: *
075: */
076: final class BorderOpImage extends OpImage {
077: /**
078: * The <code>BorderExtender</code> object used to extend the source data.
079: */
080: protected BorderExtender extender;
081:
082: /**
083: * Constructor.
084: *
085: * @param source The source image.
086: * @param layout The destination image layout.
087: * @param leftPad The amount of padding to the left of the source.
088: * @param rightPad The amount of padding to the right of the source.
089: * @param topPad The amount of padding to the top of the source.
090: * @param bottomPad The amount of padding to the bottom of the source.
091: * @param type The border type.
092: * @param constants The constants used with border type
093: * <code>BorderDescriptor.BORDER_CONST_FILL</code>,
094: * stored as reference.
095: */
096: public BorderOpImage(RenderedImage source, Map config,
097: ImageLayout layout, int leftPad, int rightPad, int topPad,
098: int bottomPad, BorderExtender extender) {
099: super (vectorize(source), layoutHelper(layout, source, leftPad,
100: rightPad, topPad, bottomPad), config, true);
101:
102: this .extender = extender;
103: }
104:
105: /**
106: * Sets up the image layout information for this Op.
107: * The minX, minY, width, and height are calculated based on
108: * the source's dimension and padding values. Any of these
109: * values specified in the layout parameter is ignored.
110: * All other variables are taken from the layout parameter or
111: * inherited from the source.
112: */
113: private static ImageLayout layoutHelper(ImageLayout layout,
114: RenderedImage source, int leftPad, int rightPad,
115: int topPad, int bottomPad) {
116: ImageLayout il = layout == null ? new ImageLayout()
117: : (ImageLayout) layout.clone();
118:
119: // Set the image bounds according to the padding.
120: il.setMinX(source.getMinX() - leftPad);
121: il.setMinY(source.getMinY() - topPad);
122: il.setWidth(source.getWidth() + leftPad + rightPad);
123: il.setHeight(source.getHeight() + topPad + bottomPad);
124:
125: // Set tile grid offset to minimize the probability that a
126: // tile's bounds does not intersect the source image bounds.
127: if (!il.isValid(ImageLayout.TILE_GRID_X_OFFSET_MASK)) {
128: il.setTileGridXOffset(il.getMinX(null));
129: }
130:
131: if (!il.isValid(ImageLayout.TILE_GRID_Y_OFFSET_MASK)) {
132: il.setTileGridYOffset(il.getMinY(null));
133: }
134:
135: // Force inheritance of source image SampleModel and ColorModel.
136: il.setSampleModel(source.getSampleModel());
137: il.setColorModel(source.getColorModel());
138:
139: return il;
140: }
141:
142: /**
143: * Returns a conservative estimate of the destination region that
144: * can potentially be affected by the pixels of a rectangle of a
145: * given source.
146: *
147: * @param sourceRect the Rectangle in source coordinates.
148: * @param sourceIndex the index of the source image.
149: * @return a Rectangle indicating the potentially affected
150: * destination region. or null if the region is unknown.
151: * @throws IllegalArgumentException if the source index is
152: * negative or greater than that of the last source.
153: * @throws IllegalArgumentException if sourceRect is null.
154: */
155: public Rectangle mapSourceRect(Rectangle sourceRect, int sourceIndex) {
156:
157: if (sourceRect == null) {
158: throw new IllegalArgumentException(JaiI18N
159: .getString("Generic0"));
160: }
161:
162: if (sourceIndex < 0 || sourceIndex >= getNumSources()) {
163: throw new IllegalArgumentException(JaiI18N
164: .getString("BorderOpImage0"));
165: }
166:
167: return new Rectangle(sourceRect);
168: }
169:
170: /**
171: * Returns a conservative estimate of the region of a specified
172: * source that is required in order to compute the pixels of a
173: * given destination rectangle.
174: *
175: * @param destRect the Rectangle in destination coordinates.
176: * @param sourceIndex the index of the source image.
177: * @return a Rectangle indicating the required source region.
178: * @throws IllegalArgumentException if the source index is
179: * negative or greater than that of the last source.
180: * @throws IllegalArgumentException if destRect is null.
181: */
182: public Rectangle mapDestRect(Rectangle destRect, int sourceIndex) {
183:
184: if (destRect == null) {
185: throw new IllegalArgumentException(JaiI18N
186: .getString("Generic0"));
187: }
188:
189: if (sourceIndex < 0 || sourceIndex >= getNumSources()) {
190: throw new IllegalArgumentException(JaiI18N
191: .getString("BorderOpImage2"));
192: }
193:
194: Rectangle srcBounds = getSourceImage(0).getBounds();
195: return destRect.intersection(srcBounds);
196: }
197:
198: /** Computes the pixel values for the specified tile. */
199: public Raster computeTile(int tileX, int tileY) {
200: // Create a new Raster.
201: WritableRaster dest = createTile(tileX, tileY);
202:
203: // Extend the data.
204: getSourceImage(0).copyExtendedData(dest, extender);
205:
206: return dest;
207: }
208: }
|