KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > image > BandCombineOp


1 /*
2  * @(#)BandCombineOp.java 1.39 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.image;
9
10 import java.awt.GraphicsEnvironment JavaDoc;
11 import java.awt.color.ICC_Profile JavaDoc;
12 import java.awt.geom.Rectangle2D JavaDoc;
13 import java.awt.Rectangle JavaDoc;
14 import java.awt.geom.Point2D JavaDoc;
15 import java.awt.RenderingHints JavaDoc;
16 import sun.awt.image.ImagingLib;
17
18 /**
19  * This class performs an arbitrary linear combination of the bands
20  * in a <CODE>Raster</CODE>, using a specified matrix.
21  * <p>
22  * The width of the matrix must be equal to the number of bands in the
23  * source <CODE>Raster</CODE>, optionally plus one. If there is one more
24  * column in the matrix than the number of bands, there is an implied 1 at the
25  * end of the vector of band samples representing a pixel. The height
26  * of the matrix must be equal to the number of bands in the destination.
27  * <p>
28  * For example, a 3-banded <CODE>Raster</CODE> might have the following
29  * transformation applied to each pixel in order to invert the second band of
30  * the <CODE>Raster</CODE>.
31  * <pre>
32  * [ 1.0 0.0 0.0 0.0 ] [ b1 ]
33  * [ 0.0 -1.0 0.0 255.0 ] x [ b2 ]
34  * [ 0.0 0.0 1.0 0.0 ] [ b3 ]
35  * [ 1 ]
36  * </pre>
37  *
38  * <p>
39  * Note that the source and destination can be the same object.
40  * @version 10 Feb 1997
41  */

42 public class BandCombineOp implements RasterOp JavaDoc {
43     float[][] matrix;
44     int nrows = 0;
45     int ncols = 0;
46     RenderingHints JavaDoc hints;
47     
48     /**
49      * Constructs a <CODE>BandCombineOp</CODE> with the specified matrix.
50      * The width of the matrix must be equal to the number of bands in
51      * the source <CODE>Raster</CODE>, optionally plus one. If there is one
52      * more column in the matrix than the number of bands, there is an implied
53      * 1 at the end of the vector of band samples representing a pixel. The
54      * height of the matrix must be equal to the number of bands in the
55      * destination.
56      * <p>
57      * The first subscript is the row index and the second
58      * is the column index. This operation uses none of the currently
59      * defined rendering hints; the <CODE>RenderingHints</CODE> argument can be
60      * null.
61      *
62      * @param matrix The matrix to use for the band combine operation.
63      * @param hints The <CODE>RenderingHints</CODE> object for this operation.
64      * Not currently used so it can be null.
65      */

66     public BandCombineOp (float[][] matrix, RenderingHints JavaDoc hints) {
67         nrows = matrix.length;
68         ncols = matrix[0].length;
69         this.matrix = new float[nrows][ncols+1];
70         for (int i=0; i < nrows; i++) {
71             System.arraycopy(matrix[i], 0, this.matrix[i], 0, ncols);
72         }
73         this.hints = hints;
74     }
75
76     /**
77      * Returns the matrix.
78      *
79      * @return The matrix associated with this band combine operation.
80      */

81     public final float[][] getMatrix() {
82         return (float[][]) matrix.clone();
83     }
84     
85     /**
86      * Transforms the <CODE>Raster</CODE> using the matrix specified in the
87      * constructor. An <CODE>IllegalArgumentException</CODE> may be thrown if
88      * the number of bands in the source or destination is incompatible with
89      * the matrix. See the class comments for more details.
90      * <p>
91      * If the destination is null, it will be created with a number of bands
92      * equalling the number of rows in the matrix. No exception is thrown
93      * if the operation causes a data overflow.
94      *
95      * @param src The <CODE>Raster</CODE> to be filtered.
96      * @param dst The <CODE>Raster</CODE> in which to store the results
97      * of the filter operation.
98      *
99      * @return The filtered <CODE>Raster</CODE>.
100      *
101      * @throws IllegalArgumentException If the number of bands in the
102      * source or destination is incompatible with the matrix.
103      */

104     public WritableRaster JavaDoc filter(Raster JavaDoc src, WritableRaster JavaDoc dst) {
105         int nBands = src.getNumBands();
106         if (ncols != nBands && ncols != (nBands+1)) {
107             throw new IllegalArgumentException JavaDoc("Number of columns in the "+
108                                                "matrix ("+ncols+
109                                                ") must be equal to the number"+
110                                                " of bands ([+1]) in src ("+
111                                                nBands+").");
112         }
113         if (dst == null) {
114             dst = createCompatibleDestRaster(src);
115         }
116         else if (nrows != dst.getNumBands()) {
117             throw new IllegalArgumentException JavaDoc("Number of rows in the "+
118                                                "matrix ("+nrows+
119                                                ") must be equal to the number"+
120                                                " of bands ([+1]) in dst ("+
121                                                nBands+").");
122         }
123
124         if (ImagingLib.filter(this, src, dst) != null) {
125             return dst;
126         }
127
128         int[] pixel = null;
129         int[] dstPixel = new int[dst.getNumBands()];
130         float accum;
131         int sminX = src.getMinX();
132         int sY = src.getMinY();
133         int dminX = dst.getMinX();
134         int dY = dst.getMinY();
135         int sX;
136         int dX;
137         if (ncols == nBands) {
138             for (int y=0; y < src.getHeight(); y++, sY++, dY++) {
139                 dX = dminX;
140                 sX = sminX;
141                 for (int x=0; x < src.getWidth(); x++, sX++, dX++) {
142                     pixel = src.getPixel(sX, sY, pixel);
143                     for (int r=0; r < nrows; r++) {
144                         accum = 0.f;
145                         for (int c=0; c < ncols; c++) {
146                             accum += matrix[r][c]*pixel[c];
147                         }
148                         dstPixel[r] = (int) accum;
149                     }
150                     dst.setPixel(dX, dY, dstPixel);
151                 }
152             }
153         }
154         else {
155             // Need to add constant
156
for (int y=0; y < src.getHeight(); y++, sY++, dY++) {
157                 dX = dminX;
158                 sX = sminX;
159                 for (int x=0; x < src.getWidth(); x++, sX++, dX++) {
160                     pixel = src.getPixel(sX, sY, pixel);
161                     for (int r=0; r < nrows; r++) {
162                         accum = 0.f;
163                         for (int c=0; c < nBands; c++) {
164                             accum += matrix[r][c]*pixel[c];
165                         }
166                         dstPixel[r] = (int) (accum+matrix[r][nBands]);
167                     }
168                     dst.setPixel(dX, dY, dstPixel);
169                 }
170             }
171         }
172
173         return dst;
174     }
175
176     /**
177      * Returns the bounding box of the transformed destination. Since
178      * this is not a geometric operation, the bounding box is the same for
179      * the source and destination.
180      * An <CODE>IllegalArgumentException</CODE> may be thrown if the number of
181      * bands in the source is incompatible with the matrix. See
182      * the class comments for more details.
183      *
184      * @param src The <CODE>Raster</CODE> to be filtered.
185      *
186      * @return The <CODE>Rectangle2D</CODE> representing the destination
187      * image's bounding box.
188      *
189      * @throws IllegalArgumentException If the number of bands in the source
190      * is incompatible with the matrix.
191      */

192     public final Rectangle2D JavaDoc getBounds2D (Raster JavaDoc src) {
193     return src.getBounds();
194     }
195
196     
197     /**
198      * Creates a zeroed destination <CODE>Raster</CODE> with the correct size
199      * and number of bands.
200      * An <CODE>IllegalArgumentException</CODE> may be thrown if the number of
201      * bands in the source is incompatible with the matrix. See
202      * the class comments for more details.
203      *
204      * @param src The <CODE>Raster</CODE> to be filtered.
205      *
206      * @return The zeroed destination <CODE>Raster</CODE>.
207      */

208     public WritableRaster JavaDoc createCompatibleDestRaster (Raster JavaDoc src) {
209         int nBands = src.getNumBands();
210         if ((ncols != nBands) && (ncols != (nBands+1))) {
211             throw new IllegalArgumentException JavaDoc("Number of columns in the "+
212                                                "matrix ("+ncols+
213                                                ") must be equal to the number"+
214                                                " of bands ([+1]) in src ("+
215                                                nBands+").");
216         }
217         if (src.getNumBands() == nrows) {
218             return src.createCompatibleWritableRaster();
219         }
220         else {
221             throw new IllegalArgumentException JavaDoc("Don't know how to create a "+
222                                                " compatible Raster with "+
223                                                nrows+" bands.");
224         }
225     }
226
227     /**
228      * Returns the location of the corresponding destination point given a
229      * point in the source <CODE>Raster</CODE>. If <CODE>dstPt</CODE> is
230      * specified, it is used to hold the return value.
231      * Since this is not a geometric operation, the point returned
232      * is the same as the specified <CODE>srcPt</CODE>.
233      *
234      * @param srcPt The <code>Point2D</code> that represents the point in
235      * the source <code>Raster</code>
236      * @param dstPt The <CODE>Point2D</CODE> in which to store the result.
237      *
238      * @return The <CODE>Point2D</CODE> in the destination image that
239      * corresponds to the specified point in the source image.
240      */

241     public final Point2D JavaDoc getPoint2D (Point2D JavaDoc srcPt, Point2D JavaDoc dstPt) {
242         if (dstPt == null) {
243             dstPt = new Point2D.Float JavaDoc();
244         }
245     dstPt.setLocation(srcPt.getX(), srcPt.getY());
246
247         return dstPt;
248     }
249     
250     /**
251      * Returns the rendering hints for this operation.
252      *
253      * @return The <CODE>RenderingHints</CODE> object associated with this
254      * operation. Returns null if no hints have been set.
255      */

256     public final RenderingHints JavaDoc getRenderingHints() {
257         return hints;
258     }
259 }
260
Popular Tags