001: /*
002: * $RCSfile: BorderExtenderCopy.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:57:04 $
010: * $State: Exp $
011: */
012: package javax.media.jai;
013:
014: import java.awt.Rectangle;
015: import java.awt.image.DataBuffer;
016: import java.awt.image.Raster;
017: import java.awt.image.WritableRaster;
018: import com.sun.media.jai.util.JDKWorkarounds;
019:
020: /**
021: * A subclass of <code>BorderExtender</code> that implements
022: * border extension by filling all pixels outside of the image
023: * bounds with copies of the edge pixels. For example, the image:
024: *
025: * <p><center>
026: * <table border=1>
027: * <tr align=center><td>A</td><td>B</td><td>C</td> </tr>
028: * <tr align=center><td>D</td><td>E</td><td>F</td> </tr>
029: * <tr align=center><td>G</td><td>H</td><td>I</td> </tr>
030: * </table></center>
031: *
032: * <br>if extended by adding two extra rows to the top and bottom and
033: * two extra columns on the left and right sides, would become:
034: *
035: * <p><center>
036: * <table border=1>
037: * <tr align=center>
038: * <td>A</td><td>A</td><td>A</td><td>B</td><td>C</td><td>C</td><td>C</td> </tr>
039: * <td>A</td><td>A</td><td>A</td><td>B</td><td>C</td><td>C</td><td>C</td> </tr>
040: * <td>A</td><td>A</td><td>A</td><td>B</td><td>C</td><td>C</td><td>C</td> </tr>
041: * <td>D</td><td>D</td><td>D</td><td>E</td><td>F</td><td>F</td><td>F</td> </tr>
042: * <td>G</td><td>G</td><td>G</td><td>H</td><td>I</td><td>I</td><td>I</td> </tr>
043: * <td>G</td><td>G</td><td>G</td><td>H</td><td>I</td><td>I</td><td>I</td> </tr>
044: * <td>G</td><td>G</td><td>G</td><td>H</td><td>I</td><td>I</td><td>I</td> </tr>
045: * </table></center>
046: *
047: * <p> Although this type of extension is not particularly
048: * visually appealing, it is very useful as a way of padding
049: * source images prior to area or geometric operations, such as
050: * convolution, scaling, or rotation.
051: *
052: * @see BorderExtender
053: */
054: public final class BorderExtenderCopy extends BorderExtender {
055:
056: BorderExtenderCopy() {
057: }
058:
059: /**
060: * Fills in the portions of a given <code>Raster</code> that lie
061: * outside the bounds of a given <code>PlanarImage</code> with
062: * copies of the edge pixels of the image.
063: *
064: * <p> The portion of <code>raster</code> that lies within
065: * <code>im.getBounds()</code> is not altered.
066: *
067: * @param raster The <code>WritableRaster</code> the border area of
068: * which is to be filled with copies of the edge pixels
069: * of the image.
070: * @param im The <code>PlanarImage</code> which will provide the
071: * edge data with which to fill the border area of the
072: * <code>WritableRaster</code>.
073: *
074: * @throws <code>IllegalArgumentException</code> if either parameter is
075: * <code>null</code>.
076: */
077: public final void extend(WritableRaster raster, PlanarImage im) {
078:
079: if (raster == null || im == null) {
080: throw new IllegalArgumentException(JaiI18N
081: .getString("Generic0"));
082: }
083:
084: int width = raster.getWidth();
085: int height = raster.getHeight();
086: int numBands = raster.getNumBands();
087:
088: int minX = raster.getMinX();
089: int maxX = minX + width;
090: int minY = raster.getMinY();
091: int maxY = minY + height;
092:
093: int validMinX = Math.max(im.getMinX(), minX);
094: int validMaxX = Math.min(im.getMaxX(), maxX);
095: int validMinY = Math.max(im.getMinY(), minY);
096: int validMaxY = Math.min(im.getMaxY(), maxY);
097:
098: if (validMinX > validMaxX || validMinY > validMaxY) {
099: // Raster does not intersect image. Determine the location
100: // and size of the smallest rectangle containing the Raster
101: // and which intersects the image.
102: if (validMinX > validMaxX) { // no intersetion in X
103: if (minX == validMinX) {
104: minX = im.getMaxX() - 1;
105: } else {
106: maxX = im.getMinX();
107: }
108: }
109: if (validMinY > validMaxY) { // no intersetion in Y
110: if (minY == validMinY) {
111: minY = im.getMaxY() - 1;
112: } else {
113: maxY = im.getMinY();
114: }
115: }
116:
117: // Create minimum Raster.
118: WritableRaster wr = raster.createCompatibleWritableRaster(
119: minX, minY, maxX - minX, maxY - minY);
120:
121: // Extend the data.
122: extend(wr, im);
123:
124: // Create a child with same bounds as the target Raster.
125: Raster child = wr.createChild(raster.getMinX(), raster
126: .getMinY(), raster.getWidth(), raster.getHeight(),
127: raster.getMinX(), raster.getMinY(), null);
128:
129: // Copy the data from the child.
130: JDKWorkarounds.setRect(raster, child, 0, 0);
131:
132: return;
133: }
134:
135: Rectangle rect = new Rectangle();
136: int size = Math.max(width, height);
137:
138: int row, col;
139: switch (raster.getSampleModel().getDataType()) {
140: case DataBuffer.TYPE_BYTE:
141: case DataBuffer.TYPE_SHORT:
142: case DataBuffer.TYPE_USHORT:
143: case DataBuffer.TYPE_INT:
144: int[] iData = new int[size * numBands];
145:
146: if (minX < validMinX) {
147: rect.x = validMinX;
148: rect.y = validMinY;
149: rect.width = 1;
150: rect.height = validMaxY - validMinY;
151:
152: if (rect.height > 0) {
153: Raster leftEdge = im.getData(rect);
154: leftEdge.getPixels(validMinX, validMinY, 1,
155: rect.height, iData);
156:
157: for (col = minX; col < validMinX; col++) {
158: raster.setPixels(col, validMinY, 1,
159: rect.height, iData);
160: }
161: }
162: }
163:
164: if (validMaxX < maxX) {
165: rect.x = validMaxX - 1;
166: rect.y = validMinY;
167: rect.width = 1;
168: rect.height = validMaxY - validMinY;
169:
170: if (rect.height > 0) {
171: Raster rightEdge = im.getData(rect);
172: rightEdge.getPixels(validMaxX - 1, validMinY, 1,
173: rect.height, iData);
174:
175: for (col = validMaxX; col < maxX; col++) {
176: raster.setPixels(col, validMinY, 1,
177: rect.height, iData);
178: }
179: }
180: }
181:
182: if (minY < validMinY) {
183: rect.x = minX;
184: rect.y = validMinY;
185: rect.width = width;
186: rect.height = 1;
187:
188: Raster topRow = im.getExtendedData(rect, this );
189: topRow.getPixels(minX, validMinY, width, 1, iData);
190: for (row = minY; row < validMinY; row++) {
191: raster.setPixels(minX, row, width, 1, iData);
192: }
193: }
194:
195: if (validMaxY < maxY) {
196: rect.x = minX;
197: rect.y = validMaxY - 1;
198: rect.width = width;
199: rect.height = 1;
200:
201: Raster bottomRow = im.getExtendedData(rect, this );
202: bottomRow.getPixels(minX, validMaxY - 1, width, 1,
203: iData);
204: for (row = validMaxY; row < maxY; row++) {
205: raster.setPixels(minX, row, width, 1, iData);
206: }
207: }
208: break;
209:
210: case DataBuffer.TYPE_FLOAT:
211: float[] fData = new float[size * numBands];
212:
213: if (minX < validMinX) {
214: rect.x = validMinX;
215: rect.y = validMinY;
216: rect.width = 1;
217: rect.height = validMaxY - validMinY;
218:
219: if (rect.height > 0) {
220: Raster leftEdge = im.getData(rect);
221: leftEdge.getPixels(validMinX, validMinY, 1,
222: rect.height, fData);
223:
224: for (col = minX; col < validMinX; col++) {
225: raster.setPixels(col, validMinY, 1,
226: rect.height, fData);
227: }
228: }
229: }
230:
231: if (validMaxX < maxX) {
232: rect.x = validMaxX - 1;
233: rect.y = validMinY;
234: rect.width = 1;
235: rect.height = validMaxY - validMinY;
236:
237: if (rect.height > 0) {
238: Raster rightEdge = im.getData(rect);
239: rightEdge.getPixels(validMaxX - 1, validMinY, 1,
240: rect.height, fData);
241:
242: for (col = validMaxX; col < maxX; col++) {
243: raster.setPixels(col, validMinY, 1,
244: rect.height, fData);
245: }
246: }
247: }
248:
249: if (minY < validMinY) {
250: rect.x = minX;
251: rect.y = validMinY;
252: rect.width = width;
253: rect.height = 1;
254:
255: Raster topRow = im.getExtendedData(rect, this );
256: topRow.getPixels(minX, validMinY, width, 1, fData);
257: for (row = minY; row < validMinY; row++) {
258: raster.setPixels(minX, row, width, 1, fData);
259: }
260: }
261:
262: if (validMaxY < maxY) {
263: rect.x = minX;
264: rect.y = validMaxY - 1;
265: rect.width = width;
266: rect.height = 1;
267:
268: Raster bottomRow = im.getExtendedData(rect, this );
269: bottomRow.getPixels(minX, validMaxY - 1, width, 1,
270: fData);
271: for (row = validMaxY; row < maxY; row++) {
272: raster.setPixels(minX, row, width, 1, fData);
273: }
274: }
275: break;
276:
277: case DataBuffer.TYPE_DOUBLE:
278: double[] dData = new double[size * numBands];
279:
280: if (minX < validMinX) {
281: rect.x = validMinX;
282: rect.y = validMinY;
283: rect.width = 1;
284: rect.height = validMaxY - validMinY;
285:
286: if (rect.height > 0) {
287: Raster leftEdge = im.getData(rect);
288: leftEdge.getPixels(validMinX, validMinY, 1,
289: rect.height, dData);
290:
291: for (col = minX; col < validMinX; col++) {
292: raster.setPixels(col, validMinY, 1,
293: rect.height, dData);
294: }
295: }
296: }
297:
298: if (validMaxX < maxX) {
299: rect.x = validMaxX - 1;
300: rect.y = validMinY;
301: rect.width = 1;
302: rect.height = validMaxY - validMinY;
303:
304: if (rect.height > 0) {
305: Raster rightEdge = im.getData(rect);
306: rightEdge.getPixels(validMaxX - 1, validMinY, 1,
307: rect.height, dData);
308:
309: for (col = validMaxX; col < maxX; col++) {
310: raster.setPixels(col, validMinY, 1,
311: rect.height, dData);
312: }
313: }
314: }
315:
316: if (minY < validMinY) {
317: rect.x = minX;
318: rect.y = validMinY;
319: rect.width = width;
320: rect.height = 1;
321:
322: Raster topRow = im.getExtendedData(rect, this );
323: topRow.getPixels(minX, validMinY, width, 1, dData);
324: for (row = minY; row < validMinY; row++) {
325: raster.setPixels(minX, row, width, 1, dData);
326: }
327: }
328:
329: if (validMaxY < maxY) {
330: rect.x = minX;
331: rect.y = validMaxY - 1;
332: rect.width = width;
333: rect.height = 1;
334:
335: Raster bottomRow = im.getExtendedData(rect, this );
336: bottomRow.getPixels(minX, validMaxY - 1, width, 1,
337: dData);
338: for (row = validMaxY; row < maxY; row++) {
339: raster.setPixels(minX, row, width, 1, dData);
340: }
341: }
342: break;
343: }
344: }
345: }
|