001: /*
002: * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.image;
027:
028: import java.awt.geom.AffineTransform;
029: import java.awt.image.AffineTransformOp;
030: import java.awt.image.BufferedImage;
031: import java.awt.image.BufferedImageOp;
032: import java.awt.image.ByteLookupTable;
033: import java.awt.image.ConvolveOp;
034: import java.awt.image.Kernel;
035: import java.awt.image.LookupOp;
036: import java.awt.image.LookupTable;
037: import java.awt.image.RasterOp;
038: import java.awt.image.Raster;
039: import java.awt.image.WritableRaster;
040: import java.security.AccessController;
041: import java.security.PrivilegedAction;
042:
043: /**
044: * This class provides a hook to access platform-specific
045: * imaging code.
046: *
047: * If the implementing class cannot handle the op, tile format or
048: * image format, the method will return null;
049: * If there is an error when processing the
050: * data, the implementing class may either return null
051: * (in which case our java code will be executed) or may throw
052: * an exception.
053: */
054: public class ImagingLib {
055:
056: static boolean useLib = true;
057: static boolean verbose = false;
058:
059: private static final int NUM_NATIVE_OPS = 3;
060: private static final int LOOKUP_OP = 0;
061: private static final int AFFINE_OP = 1;
062: private static final int CONVOLVE_OP = 2;
063:
064: private static Class[] nativeOpClass = new Class[NUM_NATIVE_OPS];
065:
066: /**
067: * Returned value indicates whether the library initailization was
068: * succeded.
069: *
070: * There could be number of reasons to failure:
071: * - failed to load library.
072: * - failed to get all required entry points.
073: */
074: private static native boolean init();
075:
076: static public native int transformBI(BufferedImage src,
077: BufferedImage dst, double[] matrix, int interpType);
078:
079: static public native int transformRaster(Raster src, Raster dst,
080: double[] matrix, int interpType);
081:
082: static public native int convolveBI(BufferedImage src,
083: BufferedImage dst, Kernel kernel, int edgeHint);
084:
085: static public native int convolveRaster(Raster src, Raster dst,
086: Kernel kernel, int edgeHint);
087:
088: static public native int lookupByteBI(BufferedImage src,
089: BufferedImage dst, byte[][] table);
090:
091: static public native int lookupByteRaster(Raster src, Raster dst,
092: byte[][] table);
093:
094: static {
095:
096: PrivilegedAction<Boolean> doMlibInitialization = new PrivilegedAction<Boolean>() {
097: public Boolean run() {
098: String arch = System.getProperty("os.arch");
099:
100: if (arch == null || !arch.startsWith("sparc")) {
101: try {
102: System.loadLibrary("mlib_image");
103: } catch (UnsatisfiedLinkError e) {
104: return Boolean.FALSE;
105: }
106:
107: }
108: boolean success = init();
109: return Boolean.valueOf(success);
110: }
111: };
112:
113: useLib = AccessController.doPrivileged(doMlibInitialization);
114:
115: //
116: // Cache the class references of the operations we know about
117: // at the time this class is initially loaded.
118: //
119: try {
120: nativeOpClass[LOOKUP_OP] = Class
121: .forName("java.awt.image.LookupOp");
122: } catch (ClassNotFoundException e) {
123: System.err.println("Could not find class: " + e);
124: }
125: try {
126: nativeOpClass[AFFINE_OP] = Class
127: .forName("java.awt.image.AffineTransformOp");
128: } catch (ClassNotFoundException e) {
129: System.err.println("Could not find class: " + e);
130: }
131: try {
132: nativeOpClass[CONVOLVE_OP] = Class
133: .forName("java.awt.image.ConvolveOp");
134: } catch (ClassNotFoundException e) {
135: System.err.println("Could not find class: " + e);
136: }
137:
138: }
139:
140: private static int getNativeOpIndex(Class opClass) {
141: //
142: // Search for this class in cached list of
143: // classes supplying native acceleration
144: //
145: int opIndex = -1;
146: for (int i = 0; i < NUM_NATIVE_OPS; i++) {
147: if (opClass == nativeOpClass[i]) {
148: opIndex = i;
149: break;
150: }
151: }
152: return opIndex;
153: }
154:
155: public static WritableRaster filter(RasterOp op, Raster src,
156: WritableRaster dst) {
157: if (useLib == false) {
158: return null;
159: }
160:
161: // Create the destination tile
162: if (dst == null) {
163: dst = op.createCompatibleDestRaster(src);
164: }
165:
166: WritableRaster retRaster = null;
167: switch (getNativeOpIndex(op.getClass())) {
168:
169: case LOOKUP_OP:
170: // REMIND: Fix this!
171: LookupTable table = ((LookupOp) op).getTable();
172: if (table.getOffset() != 0) {
173: // Right now the native code doesn't support offsets
174: return null;
175: }
176: if (table instanceof ByteLookupTable) {
177: ByteLookupTable bt = (ByteLookupTable) table;
178: if (lookupByteRaster(src, dst, bt.getTable()) > 0) {
179: retRaster = dst;
180: }
181: }
182: break;
183:
184: case AFFINE_OP:
185: AffineTransformOp bOp = (AffineTransformOp) op;
186: double[] matrix = new double[6];
187: bOp.getTransform().getMatrix(matrix);
188: if (transformRaster(src, dst, matrix, bOp
189: .getInterpolationType()) > 0) {
190: retRaster = dst;
191: }
192: break;
193:
194: case CONVOLVE_OP:
195: ConvolveOp cOp = (ConvolveOp) op;
196: if (convolveRaster(src, dst, cOp.getKernel(), cOp
197: .getEdgeCondition()) > 0) {
198: retRaster = dst;
199: }
200: break;
201:
202: default:
203: break;
204: }
205:
206: if (retRaster != null) {
207: SunWritableRaster.markDirty(retRaster);
208: }
209:
210: return retRaster;
211: }
212:
213: public static BufferedImage filter(BufferedImageOp op,
214: BufferedImage src, BufferedImage dst) {
215: if (verbose) {
216: System.out.println("in filter and op is " + op
217: + "bufimage is " + src + " and " + dst);
218: }
219:
220: if (useLib == false) {
221: return null;
222: }
223:
224: // Create the destination image
225: if (dst == null) {
226: dst = op.createCompatibleDestImage(src, null);
227: }
228:
229: BufferedImage retBI = null;
230: switch (getNativeOpIndex(op.getClass())) {
231:
232: case LOOKUP_OP:
233: // REMIND: Fix this!
234: LookupTable table = ((LookupOp) op).getTable();
235: if (table.getOffset() != 0) {
236: // Right now the native code doesn't support offsets
237: return null;
238: }
239: if (table instanceof ByteLookupTable) {
240: ByteLookupTable bt = (ByteLookupTable) table;
241: if (lookupByteBI(src, dst, bt.getTable()) > 0) {
242: retBI = dst;
243: }
244: }
245: break;
246:
247: case AFFINE_OP:
248: AffineTransformOp bOp = (AffineTransformOp) op;
249: double[] matrix = new double[6];
250: AffineTransform xform = bOp.getTransform();
251: bOp.getTransform().getMatrix(matrix);
252:
253: if (transformBI(src, dst, matrix, bOp
254: .getInterpolationType()) > 0) {
255: retBI = dst;
256: }
257: break;
258:
259: case CONVOLVE_OP:
260: ConvolveOp cOp = (ConvolveOp) op;
261: if (convolveBI(src, dst, cOp.getKernel(), cOp
262: .getEdgeCondition()) > 0) {
263: retBI = dst;
264: }
265: break;
266:
267: default:
268: break;
269: }
270:
271: if (retBI != null) {
272: SunWritableRaster.markDirty(retBI);
273: }
274:
275: return retBI;
276: }
277: }
|