1 /* 2 * Copyright (c) 1995, 2004, 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 java.awt.image; 27 28 import java.awt.image.ImageConsumer; 29 import java.awt.image.ColorModel; 30 import java.util.Hashtable; 31 import java.awt.Rectangle; 32 33 /** 34 * An ImageFilter class for cropping images. 35 * This class extends the basic ImageFilter Class to extract a given 36 * rectangular region of an existing Image and provide a source for a 37 * new image containing just the extracted region. It is meant to 38 * be used in conjunction with a FilteredImageSource object to produce 39 * cropped versions of existing images. 40 * 41 * @see FilteredImageSource 42 * @see ImageFilter 43 * 44 * @author Jim Graham 45 */ 46 public class CropImageFilter extends ImageFilter { 47 int cropX; 48 int cropY; 49 int cropW; 50 int cropH; 51 52 /** 53 * Constructs a CropImageFilter that extracts the absolute rectangular 54 * region of pixels from its source Image as specified by the x, y, 55 * w, and h parameters. 56 * @param x the x location of the top of the rectangle to be extracted 57 * @param y the y location of the top of the rectangle to be extracted 58 * @param w the width of the rectangle to be extracted 59 * @param h the height of the rectangle to be extracted 60 */ 61 public CropImageFilter(int x, int y, int w, int h) { 62 cropX = x; 63 cropY = y; 64 cropW = w; 65 cropH = h; 66 } 67 68 /** 69 * Passes along the properties from the source object after adding a 70 * property indicating the cropped region. 71 * This method invokes <code>super.setProperties</code>, 72 * which might result in additional properties being added. 73 * <p> 74 * Note: This method is intended to be called by the 75 * <code>ImageProducer</code> of the <code>Image</code> whose pixels 76 * are being filtered. Developers using 77 * this class to filter pixels from an image should avoid calling 78 * this method directly since that operation could interfere 79 * with the filtering operation. 80 */ 81 public void setProperties(Hashtable<?,?> props) { 82 Hashtable<Object,Object> p = (Hashtable<Object,Object>)props.clone(); 83 p.put("croprect", new Rectangle(cropX, cropY, cropW, cropH)); 84 super.setProperties(p); 85 } 86 87 /** 88 * Override the source image's dimensions and pass the dimensions 89 * of the rectangular cropped region to the ImageConsumer. 90 * <p> 91 * Note: This method is intended to be called by the 92 * <code>ImageProducer</code> of the <code>Image</code> whose 93 * pixels are being filtered. Developers using 94 * this class to filter pixels from an image should avoid calling 95 * this method directly since that operation could interfere 96 * with the filtering operation. 97 * @see ImageConsumer 98 */ 99 public void setDimensions(int w, int h) { 100 consumer.setDimensions(cropW, cropH); 101 } 102 103 /** 104 * Determine whether the delivered byte pixels intersect the region to 105 * be extracted and passes through only that subset of pixels that 106 * appear in the output region. 107 * <p> 108 * Note: This method is intended to be called by the 109 * <code>ImageProducer</code> of the <code>Image</code> whose 110 * pixels are being filtered. Developers using 111 * this class to filter pixels from an image should avoid calling 112 * this method directly since that operation could interfere 113 * with the filtering operation. 114 */ 115 public void setPixels(int x, int y, int w, int h, 116 ColorModel model, byte pixels[], int off, 117 int scansize) { 118 int x1 = x; 119 if (x1 < cropX) { 120 x1 = cropX; 121 } 122 int x2 = addWithoutOverflow(x, w); 123 if (x2 > cropX + cropW) { 124 x2 = cropX + cropW; 125 } 126 int y1 = y; 127 if (y1 < cropY) { 128 y1 = cropY; 129 } 130 131 int y2 = addWithoutOverflow(y, h); 132 if (y2 > cropY + cropH) { 133 y2 = cropY + cropH; 134 } 135 if (x1 >= x2 || y1 >= y2) { 136 return; 137 } 138 consumer.setPixels(x1 - cropX, y1 - cropY, (x2 - x1), (y2 - y1), 139 model, pixels, 140 off + (y1 - y) * scansize + (x1 - x), scansize); 141 } 142 143 /** 144 * Determine if the delivered int pixels intersect the region to 145 * be extracted and pass through only that subset of pixels that 146 * appear in the output region. 147 * <p> 148 * Note: This method is intended to be called by the 149 * <code>ImageProducer</code> of the <code>Image</code> whose 150 * pixels are being filtered. Developers using 151 * this class to filter pixels from an image should avoid calling 152 * this method directly since that operation could interfere 153 * with the filtering operation. 154 */ 155 public void setPixels(int x, int y, int w, int h, 156 ColorModel model, int pixels[], int off, 157 int scansize) { 158 int x1 = x; 159 if (x1 < cropX) { 160 x1 = cropX; 161 } 162 int x2 = addWithoutOverflow(x, w); 163 if (x2 > cropX + cropW) { 164 x2 = cropX + cropW; 165 } 166 int y1 = y; 167 if (y1 < cropY) { 168 y1 = cropY; 169 } 170 171 int y2 = addWithoutOverflow(y, h); 172 if (y2 > cropY + cropH) { 173 y2 = cropY + cropH; 174 } 175 if (x1 >= x2 || y1 >= y2) { 176 return; 177 } 178 consumer.setPixels(x1 - cropX, y1 - cropY, (x2 - x1), (y2 - y1), 179 model, pixels, 180 off + (y1 - y) * scansize + (x1 - x), scansize); 181 } 182 183 //check for potential overflow (see bug 4801285) 184 private int addWithoutOverflow(int x, int w) { 185 int x2 = x + w; 186 if ( x > 0 && w > 0 && x2 < 0 ) { 187 x2 = Integer.MAX_VALUE; 188 } else if( x < 0 && w < 0 && x2 > 0 ) { 189 x2 = Integer.MIN_VALUE; 190 } 191 return x2; 192 } 193 }