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 java.awt.image; 27 28 import java.util.Hashtable; 29 import java.awt.image.ImageConsumer; 30 import java.awt.image.ImageFilter; 31 32 /** 33 * The <code>BufferedImageFilter</code> class subclasses an 34 * <code>ImageFilter</code> to provide a simple means of 35 * using a single-source/single-destination image operator 36 * ({@link BufferedImageOp}) to filter a <code>BufferedImage</code> 37 * in the Image Producer/Consumer/Observer 38 * paradigm. Examples of these image operators are: {@link ConvolveOp}, 39 * {@link AffineTransformOp} and {@link LookupOp}. 40 * 41 * @see ImageFilter 42 * @see BufferedImage 43 * @see BufferedImageOp 44 */ 45 46 public class BufferedImageFilter extends ImageFilter implements Cloneable { 47 BufferedImageOp bufferedImageOp; 48 ColorModel model; 49 int width; 50 int height; 51 byte[] bytePixels; 52 int[] intPixels; 53 54 /** 55 * Constructs a <code>BufferedImageFilter</code> with the 56 * specified single-source/single-destination operator. 57 * @param op the specified <code>BufferedImageOp</code> to 58 * use to filter a <code>BufferedImage</code> 59 * @throws NullPointerException if op is null 60 */ 61 public BufferedImageFilter (BufferedImageOp op) { 62 super(); 63 if (op == null) { 64 throw new NullPointerException("Operation cannot be null"); 65 } 66 bufferedImageOp = op; 67 } 68 69 /** 70 * Returns the <code>BufferedImageOp</code>. 71 * @return the operator of this <code>BufferedImageFilter</code>. 72 */ 73 public BufferedImageOp getBufferedImageOp() { 74 return bufferedImageOp; 75 } 76 77 /** 78 * Filters the information provided in the 79 * {@link ImageConsumer#setDimensions(int, int) setDimensions } method 80 * of the {@link ImageConsumer} interface. 81 * <p> 82 * Note: This method is intended to be called by the 83 * {@link ImageProducer} of the <code>Image</code> whose pixels are 84 * being filtered. Developers using this class to retrieve pixels from 85 * an image should avoid calling this method directly since that 86 * operation could result in problems with retrieving the requested 87 * pixels. 88 * 89 * @param width the width to which to set the width of this 90 * <code>BufferedImageFilter</code> 91 * @param height the height to which to set the height of this 92 * <code>BufferedImageFilter</code> 93 * @see ImageConsumer#setDimensions 94 */ 95 public void setDimensions(int width, int height) { 96 if (width <= 0 || height <= 0) { 97 imageComplete(STATICIMAGEDONE); 98 return; 99 } 100 this.width = width; 101 this.height = height; 102 } 103 104 /** 105 * Filters the information provided in the 106 * {@link ImageConsumer#setColorModel(ColorModel) setColorModel} method 107 * of the <code>ImageConsumer</code> interface. 108 * <p> 109 * If <code>model</code> is <code>null</code>, this 110 * method clears the current <code>ColorModel</code> of this 111 * <code>BufferedImageFilter</code>. 112 * <p> 113 * Note: This method is intended to be called by the 114 * <code>ImageProducer</code> of the <code>Image</code> 115 * whose pixels are being filtered. Developers using this 116 * class to retrieve pixels from an image 117 * should avoid calling this method directly since that 118 * operation could result in problems with retrieving the 119 * requested pixels. 120 * @param model the {@link ColorModel} to which to set the 121 * <code>ColorModel</code> of this <code>BufferedImageFilter</code> 122 * @see ImageConsumer#setColorModel 123 */ 124 public void setColorModel(ColorModel model) { 125 this.model = model; 126 } 127 128 private void convertToRGB() { 129 int size = width * height; 130 int newpixels[] = new int[size]; 131 if (bytePixels != null) { 132 for (int i = 0; i < size; i++) { 133 newpixels[i] = this.model.getRGB(bytePixels[i] & 0xff); 134 } 135 } else if (intPixels != null) { 136 for (int i = 0; i < size; i++) { 137 newpixels[i] = this.model.getRGB(intPixels[i]); 138 } 139 } 140 bytePixels = null; 141 intPixels = newpixels; 142 this.model = ColorModel.getRGBdefault(); 143 } 144 145 /** 146 * Filters the information provided in the <code>setPixels</code> 147 * method of the <code>ImageConsumer</code> interface which takes 148 * an array of bytes. 149 * <p> 150 * Note: This method is intended to be called by the 151 * <code>ImageProducer</code> of the <code>Image</code> whose pixels 152 * are being filtered. Developers using 153 * this class to retrieve pixels from an image should avoid calling 154 * this method directly since that operation could result in problems 155 * with retrieving the requested pixels. 156 * @throws IllegalArgumentException if width or height are less than 157 * zero. 158 * @see ImageConsumer#setPixels(int, int, int, int, ColorModel, byte[], 159 int, int) 160 */ 161 public void setPixels(int x, int y, int w, int h, 162 ColorModel model, byte pixels[], int off, 163 int scansize) { 164 // Fix 4184230 165 if (w < 0 || h < 0) { 166 throw new IllegalArgumentException("Width ("+w+ 167 ") and height ("+h+ 168 ") must be > 0"); 169 } 170 // Nothing to do 171 if (w == 0 || h == 0) { 213 for (int sh = h; sh > 0; sh--) { 214 System.arraycopy(pixels, off, bytePixels, dstPtr, w); 215 off += scansize; 216 dstPtr += width; 217 } 218 } 219 } 220 if (intPixels != null) { 221 int dstRem = width - w; 222 int srcRem = scansize - w; 223 for (int sh = h; sh > 0; sh--) { 224 for (int sw = w; sw > 0; sw--) { 225 intPixels[dstPtr++] = model.getRGB(pixels[off++]&0xff); 226 } 227 off += srcRem; 228 dstPtr += dstRem; 229 } 230 } 231 } 232 /** 233 * Filters the information provided in the <code>setPixels</code> 234 * method of the <code>ImageConsumer</code> interface which takes 235 * an array of integers. 236 * <p> 237 * Note: This method is intended to be called by the 238 * <code>ImageProducer</code> of the <code>Image</code> whose 239 * pixels are being filtered. Developers using this class to 240 * retrieve pixels from an image should avoid calling this method 241 * directly since that operation could result in problems 242 * with retrieving the requested pixels. 243 * @throws IllegalArgumentException if width or height are less than 244 * zero. 245 * @see ImageConsumer#setPixels(int, int, int, int, ColorModel, int[], 246 int, int) 247 */ 248 public void setPixels(int x, int y, int w, int h, 249 ColorModel model, int pixels[], int off, 250 int scansize) { 251 // Fix 4184230 252 if (w < 0 || h < 0) { 253 throw new IllegalArgumentException("Width ("+w+ 254 ") and height ("+h+ 255 ") must be > 0"); 256 } 257 // Nothing to do 258 if (w == 0 || h == 0) { 304 off += scansize; 305 dstPtr += width; 306 } 307 } else { 308 if (this.model != ColorModel.getRGBdefault()) { 309 convertToRGB(); 310 } 311 int dstRem = width - w; 312 int srcRem = scansize - w; 313 for (int sh = h; sh > 0; sh--) { 314 for (int sw = w; sw > 0; sw--) { 315 intPixels[dstPtr++] = model.getRGB(pixels[off++]); 316 } 317 off += srcRem; 318 dstPtr += dstRem; 319 } 320 } 321 } 322 323 /** 324 * Filters the information provided in the <code>imageComplete</code> 325 * method of the <code>ImageConsumer</code> interface. 326 * <p> 327 * Note: This method is intended to be called by the 328 * <code>ImageProducer</code> of the <code>Image</code> whose pixels 329 * are being filtered. Developers using 330 * this class to retrieve pixels from an image should avoid calling 331 * this method directly since that operation could result in problems 332 * with retrieving the requested pixels. 333 * @param status the status of image loading 334 * @throws ImagingOpException if there was a problem calling the filter 335 * method of the <code>BufferedImageOp</code> associated with this 336 * instance. 337 * @see ImageConsumer#imageComplete 338 */ 339 public void imageComplete(int status) { 340 WritableRaster wr; 341 switch(status) { 342 case IMAGEERROR: 343 case IMAGEABORTED: 344 // reinitialize the params 345 model = null; 346 width = -1; 347 height = -1; 348 intPixels = null; 349 bytePixels = null; 350 break; 351 352 case SINGLEFRAMEDONE: 353 case STATICIMAGEDONE: 354 if (width <= 0 || height <= 0) break; 355 if (model instanceof DirectColorModel) { | 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 java.awt.image; 27 28 import java.util.Hashtable; 29 import java.awt.image.ImageConsumer; 30 import java.awt.image.ImageFilter; 31 32 /** 33 * The {@code BufferedImageFilter} class subclasses an 34 * {@code ImageFilter} to provide a simple means of 35 * using a single-source/single-destination image operator 36 * ({@link BufferedImageOp}) to filter a {@code BufferedImage} 37 * in the Image Producer/Consumer/Observer 38 * paradigm. Examples of these image operators are: {@link ConvolveOp}, 39 * {@link AffineTransformOp} and {@link LookupOp}. 40 * 41 * @see ImageFilter 42 * @see BufferedImage 43 * @see BufferedImageOp 44 */ 45 46 public class BufferedImageFilter extends ImageFilter implements Cloneable { 47 BufferedImageOp bufferedImageOp; 48 ColorModel model; 49 int width; 50 int height; 51 byte[] bytePixels; 52 int[] intPixels; 53 54 /** 55 * Constructs a {@code BufferedImageFilter} with the 56 * specified single-source/single-destination operator. 57 * @param op the specified {@code BufferedImageOp} to 58 * use to filter a {@code BufferedImage} 59 * @throws NullPointerException if op is null 60 */ 61 public BufferedImageFilter (BufferedImageOp op) { 62 super(); 63 if (op == null) { 64 throw new NullPointerException("Operation cannot be null"); 65 } 66 bufferedImageOp = op; 67 } 68 69 /** 70 * Returns the {@code BufferedImageOp}. 71 * @return the operator of this {@code BufferedImageFilter}. 72 */ 73 public BufferedImageOp getBufferedImageOp() { 74 return bufferedImageOp; 75 } 76 77 /** 78 * Filters the information provided in the 79 * {@link ImageConsumer#setDimensions(int, int) setDimensions } method 80 * of the {@link ImageConsumer} interface. 81 * <p> 82 * Note: This method is intended to be called by the 83 * {@link ImageProducer} of the {@code Image} whose pixels are 84 * being filtered. Developers using this class to retrieve pixels from 85 * an image should avoid calling this method directly since that 86 * operation could result in problems with retrieving the requested 87 * pixels. 88 * 89 * @param width the width to which to set the width of this 90 * {@code BufferedImageFilter} 91 * @param height the height to which to set the height of this 92 * {@code BufferedImageFilter} 93 * @see ImageConsumer#setDimensions 94 */ 95 public void setDimensions(int width, int height) { 96 if (width <= 0 || height <= 0) { 97 imageComplete(STATICIMAGEDONE); 98 return; 99 } 100 this.width = width; 101 this.height = height; 102 } 103 104 /** 105 * Filters the information provided in the 106 * {@link ImageConsumer#setColorModel(ColorModel) setColorModel} method 107 * of the {@code ImageConsumer} interface. 108 * <p> 109 * If {@code model} is {@code null}, this 110 * method clears the current {@code ColorModel} of this 111 * {@code BufferedImageFilter}. 112 * <p> 113 * Note: This method is intended to be called by the 114 * {@code ImageProducer} of the {@code Image} 115 * whose pixels are being filtered. Developers using this 116 * class to retrieve pixels from an image 117 * should avoid calling this method directly since that 118 * operation could result in problems with retrieving the 119 * requested pixels. 120 * @param model the {@link ColorModel} to which to set the 121 * {@code ColorModel} of this {@code BufferedImageFilter} 122 * @see ImageConsumer#setColorModel 123 */ 124 public void setColorModel(ColorModel model) { 125 this.model = model; 126 } 127 128 private void convertToRGB() { 129 int size = width * height; 130 int newpixels[] = new int[size]; 131 if (bytePixels != null) { 132 for (int i = 0; i < size; i++) { 133 newpixels[i] = this.model.getRGB(bytePixels[i] & 0xff); 134 } 135 } else if (intPixels != null) { 136 for (int i = 0; i < size; i++) { 137 newpixels[i] = this.model.getRGB(intPixels[i]); 138 } 139 } 140 bytePixels = null; 141 intPixels = newpixels; 142 this.model = ColorModel.getRGBdefault(); 143 } 144 145 /** 146 * Filters the information provided in the {@code setPixels} 147 * method of the {@code ImageConsumer} interface which takes 148 * an array of bytes. 149 * <p> 150 * Note: This method is intended to be called by the 151 * {@code ImageProducer} of the {@code Image} whose pixels 152 * are being filtered. Developers using 153 * this class to retrieve pixels from an image should avoid calling 154 * this method directly since that operation could result in problems 155 * with retrieving the requested pixels. 156 * @throws IllegalArgumentException if width or height are less than 157 * zero. 158 * @see ImageConsumer#setPixels(int, int, int, int, ColorModel, byte[], 159 int, int) 160 */ 161 public void setPixels(int x, int y, int w, int h, 162 ColorModel model, byte pixels[], int off, 163 int scansize) { 164 // Fix 4184230 165 if (w < 0 || h < 0) { 166 throw new IllegalArgumentException("Width ("+w+ 167 ") and height ("+h+ 168 ") must be > 0"); 169 } 170 // Nothing to do 171 if (w == 0 || h == 0) { 213 for (int sh = h; sh > 0; sh--) { 214 System.arraycopy(pixels, off, bytePixels, dstPtr, w); 215 off += scansize; 216 dstPtr += width; 217 } 218 } 219 } 220 if (intPixels != null) { 221 int dstRem = width - w; 222 int srcRem = scansize - w; 223 for (int sh = h; sh > 0; sh--) { 224 for (int sw = w; sw > 0; sw--) { 225 intPixels[dstPtr++] = model.getRGB(pixels[off++]&0xff); 226 } 227 off += srcRem; 228 dstPtr += dstRem; 229 } 230 } 231 } 232 /** 233 * Filters the information provided in the {@code setPixels} 234 * method of the {@code ImageConsumer} interface which takes 235 * an array of integers. 236 * <p> 237 * Note: This method is intended to be called by the 238 * {@code ImageProducer} of the {@code Image} whose 239 * pixels are being filtered. Developers using this class to 240 * retrieve pixels from an image should avoid calling this method 241 * directly since that operation could result in problems 242 * with retrieving the requested pixels. 243 * @throws IllegalArgumentException if width or height are less than 244 * zero. 245 * @see ImageConsumer#setPixels(int, int, int, int, ColorModel, int[], 246 int, int) 247 */ 248 public void setPixels(int x, int y, int w, int h, 249 ColorModel model, int pixels[], int off, 250 int scansize) { 251 // Fix 4184230 252 if (w < 0 || h < 0) { 253 throw new IllegalArgumentException("Width ("+w+ 254 ") and height ("+h+ 255 ") must be > 0"); 256 } 257 // Nothing to do 258 if (w == 0 || h == 0) { 304 off += scansize; 305 dstPtr += width; 306 } 307 } else { 308 if (this.model != ColorModel.getRGBdefault()) { 309 convertToRGB(); 310 } 311 int dstRem = width - w; 312 int srcRem = scansize - w; 313 for (int sh = h; sh > 0; sh--) { 314 for (int sw = w; sw > 0; sw--) { 315 intPixels[dstPtr++] = model.getRGB(pixels[off++]); 316 } 317 off += srcRem; 318 dstPtr += dstRem; 319 } 320 } 321 } 322 323 /** 324 * Filters the information provided in the {@code imageComplete} 325 * method of the {@code ImageConsumer} interface. 326 * <p> 327 * Note: This method is intended to be called by the 328 * {@code ImageProducer} of the {@code Image} whose pixels 329 * are being filtered. Developers using 330 * this class to retrieve pixels from an image should avoid calling 331 * this method directly since that operation could result in problems 332 * with retrieving the requested pixels. 333 * @param status the status of image loading 334 * @throws ImagingOpException if there was a problem calling the filter 335 * method of the {@code BufferedImageOp} associated with this 336 * instance. 337 * @see ImageConsumer#imageComplete 338 */ 339 public void imageComplete(int status) { 340 WritableRaster wr; 341 switch(status) { 342 case IMAGEERROR: 343 case IMAGEABORTED: 344 // reinitialize the params 345 model = null; 346 width = -1; 347 height = -1; 348 intPixels = null; 349 bytePixels = null; 350 break; 351 352 case SINGLEFRAMEDONE: 353 case STATICIMAGEDONE: 354 if (width <= 0 || height <= 0) break; 355 if (model instanceof DirectColorModel) { |