blob: 7ea73b710a463d43c25ff216b064254d2ba60fad [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1995-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.awt.image;
27
28import java.awt.image.ImageConsumer;
29import java.awt.image.ColorModel;
30import java.util.Hashtable;
31import 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 */
46public 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}