1 /* 2 * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.image; 27 28 import java.awt.geom.AffineTransform; 29 import java.awt.image.AffineTransformOp; 30 import java.awt.image.BufferedImage; 31 import java.awt.image.BufferedImageOp; 32 import java.awt.image.ByteLookupTable; 33 import java.awt.image.ConvolveOp; 34 import java.awt.image.Kernel; 35 import java.awt.image.LookupOp; 36 import java.awt.image.LookupTable; 37 import java.awt.image.RasterOp; 38 import java.awt.image.Raster; 39 import java.awt.image.WritableRaster; 40 import java.security.AccessController; 41 import java.security.PrivilegedAction; 42 43 /** 44 * This class provides a hook to access platform-specific 45 * imaging code. 46 * 47 * If the implementing class cannot handle the op, tile format or 48 * image format, the method will return null; 49 * If there is an error when processing the 50 * data, the implementing class may either return null 51 * (in which case our java code will be executed) or may throw 52 * an exception. 53 */ 54 public class ImagingLib { 55 56 static boolean useLib = true; 57 static boolean verbose = false; 58 59 private static final int NUM_NATIVE_OPS = 3; 60 private static final int LOOKUP_OP = 0; 61 private static final int AFFINE_OP = 1; 62 private static final int CONVOLVE_OP = 2; 63 64 private static Class<?>[] nativeOpClass = new Class<?>[NUM_NATIVE_OPS]; 65 66 /** 67 * Returned value indicates whether the library initailization was 68 * succeded. 69 * 70 * There could be number of reasons to failure: 71 * - failed to load library. 72 * - failed to get all required entry points. 73 */ 74 private static native boolean init(); 75 76 public static native int transformBI(BufferedImage src, BufferedImage dst, 77 double[] matrix, int interpType); 78 public static native int transformRaster(Raster src, Raster dst, 79 double[] matrix, 80 int interpType); 81 public static native int convolveBI(BufferedImage src, BufferedImage dst, 82 Kernel kernel, int edgeHint); 83 public static native int convolveRaster(Raster src, Raster dst, 84 Kernel kernel, int edgeHint); 85 public static native int lookupByteBI(BufferedImage src, BufferedImage dst, 86 byte[][] table); 87 public static native int lookupByteRaster(Raster src, Raster dst, 88 byte[][] table); 89 90 static { 91 92 PrivilegedAction<Boolean> doMlibInitialization = 93 new PrivilegedAction<Boolean>() { 94 public Boolean run() { 95 String arch = System.getProperty("os.arch"); 96 97 try { 98 System.loadLibrary("mlib_image"); 99 } catch (UnsatisfiedLinkError e) { 100 return Boolean.FALSE; 101 } 102 boolean success = init(); 103 return Boolean.valueOf(success); 104 } 105 }; 106 107 useLib = AccessController.doPrivileged(doMlibInitialization); 108 109 // 110 // Cache the class references of the operations we know about 111 // at the time this class is initially loaded. 112 // 113 try { 114 nativeOpClass[LOOKUP_OP] = 115 Class.forName("java.awt.image.LookupOp"); 116 } catch (ClassNotFoundException e) { 117 System.err.println("Could not find class: "+e); 118 } 119 try { 120 nativeOpClass[AFFINE_OP] = 121 Class.forName("java.awt.image.AffineTransformOp"); 122 } catch (ClassNotFoundException e) { 123 System.err.println("Could not find class: "+e); 124 } 125 try { 126 nativeOpClass[CONVOLVE_OP] = 127 Class.forName("java.awt.image.ConvolveOp"); 128 } catch (ClassNotFoundException e) { 129 System.err.println("Could not find class: "+e); 130 } 131 132 } 133 134 private static int getNativeOpIndex(Class<?> opClass) { 135 // 136 // Search for this class in cached list of 137 // classes supplying native acceleration 138 // 139 int opIndex = -1; 140 for (int i=0; i<NUM_NATIVE_OPS; i++) { 141 if (opClass == nativeOpClass[i]) { 142 opIndex = i; 143 break; 144 } 145 } 146 return opIndex; 147 } 148 149 150 public static WritableRaster filter(RasterOp op, Raster src, 151 WritableRaster dst) { 152 if (useLib == false) { 153 return null; 154 } 155 156 // Create the destination tile 157 if (dst == null) { 158 dst = op.createCompatibleDestRaster(src); 159 } 160 161 162 WritableRaster retRaster = null; 163 switch (getNativeOpIndex(op.getClass())) { 164 165 case LOOKUP_OP: 166 // REMIND: Fix this! 167 LookupTable table = ((LookupOp)op).getTable(); 168 if (table.getOffset() != 0) { 169 // Right now the native code doesn't support offsets 170 return null; 171 } 172 if (table instanceof ByteLookupTable) { 173 ByteLookupTable bt = (ByteLookupTable) table; 174 if (lookupByteRaster(src, dst, bt.getTable()) > 0) { 175 retRaster = dst; 176 } 177 } 178 break; 179 180 case AFFINE_OP: 181 AffineTransformOp bOp = (AffineTransformOp) op; 182 double[] matrix = new double[6]; 183 bOp.getTransform().getMatrix(matrix); 184 if (transformRaster(src, dst, matrix, 185 bOp.getInterpolationType()) > 0) { 186 retRaster = dst; 187 } 188 break; 189 190 case CONVOLVE_OP: 191 ConvolveOp cOp = (ConvolveOp) op; 192 if (convolveRaster(src, dst, 193 cOp.getKernel(), cOp.getEdgeCondition()) > 0) { 194 retRaster = dst; 195 } 196 break; 197 198 default: 199 break; 200 } 201 202 if (retRaster != null) { 203 SunWritableRaster.markDirty(retRaster); 204 } 205 206 return retRaster; 207 } 208 209 210 public static BufferedImage filter(BufferedImageOp op, BufferedImage src, 211 BufferedImage dst) 212 { 213 if (verbose) { 214 System.out.println("in filter and op is "+op 215 + "bufimage is "+src+" and "+dst); 216 } 217 218 if (useLib == false) { 219 return null; 220 } 221 222 // Create the destination image 223 if (dst == null) { 224 dst = op.createCompatibleDestImage(src, null); 225 } 226 227 BufferedImage retBI = null; 228 switch (getNativeOpIndex(op.getClass())) { 229 230 case LOOKUP_OP: 231 // REMIND: Fix this! 232 LookupTable table = ((LookupOp)op).getTable(); 233 if (table.getOffset() != 0) { 234 // Right now the native code doesn't support offsets 235 return null; 236 } 237 if (table instanceof ByteLookupTable) { 238 ByteLookupTable bt = (ByteLookupTable) table; 239 if (lookupByteBI(src, dst, bt.getTable()) > 0) { 240 retBI = dst; 241 } 242 } 243 break; 244 245 case AFFINE_OP: 246 AffineTransformOp bOp = (AffineTransformOp) op; 247 double[] matrix = new double[6]; 248 AffineTransform xform = bOp.getTransform(); 249 bOp.getTransform().getMatrix(matrix); 250 251 if (transformBI(src, dst, matrix, 252 bOp.getInterpolationType())>0) { 253 retBI = dst; 254 } 255 break; 256 257 case CONVOLVE_OP: 258 ConvolveOp cOp = (ConvolveOp) op; 259 if (convolveBI(src, dst, cOp.getKernel(), 260 cOp.getEdgeCondition()) > 0) { 261 retBI = dst; 262 } 263 break; 264 265 default: 266 break; 267 } 268 269 if (retBI != null) { 270 SunWritableRaster.markDirty(retBI); 271 } 272 273 return retBI; 274 } 275 }