KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > image > AreaAveragingScaleFilter


1 /*
2  * @(#)AreaAveragingScaleFilter.java 1.15 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.image;
9
10 import java.awt.image.ImageConsumer JavaDoc;
11 import java.awt.image.ColorModel JavaDoc;
12 import java.util.Hashtable JavaDoc;
13 import java.awt.Rectangle JavaDoc;
14
15 /**
16  * An ImageFilter class for scaling images using a simple area averaging
17  * algorithm that produces smoother results than the nearest neighbor
18  * algorithm.
19  * <p>This class extends the basic ImageFilter Class to scale an existing
20  * image and provide a source for a new image containing the resampled
21  * image. The pixels in the source image are blended to produce pixels
22  * for an image of the specified size. The blending process is analogous
23  * to scaling up the source image to a multiple of the destination size
24  * using pixel replication and then scaling it back down to the destination
25  * size by simply averaging all the pixels in the supersized image that
26  * fall within a given pixel of the destination image. If the data from
27  * the source is not delivered in TopDownLeftRight order then the filter
28  * will back off to a simple pixel replication behavior and utilize the
29  * requestTopDownLeftRightResend() method to refilter the pixels in a
30  * better way at the end.
31  * <p>It is meant to be used in conjunction with a FilteredImageSource
32  * object to produce scaled versions of existing images. Due to
33  * implementation dependencies, there may be differences in pixel values
34  * of an image filtered on different platforms.
35  *
36  * @see FilteredImageSource
37  * @see ReplicateScaleFilter
38  * @see ImageFilter
39  *
40  * @version 1.15 12/19/03
41  * @author Jim Graham
42  */

43 public class AreaAveragingScaleFilter extends ReplicateScaleFilter JavaDoc {
44     private static final ColorModel JavaDoc rgbmodel = ColorModel.getRGBdefault();
45     private static final int neededHints = (TOPDOWNLEFTRIGHT
46                         | COMPLETESCANLINES);
47
48     private boolean passthrough;
49     private float reds[], greens[], blues[], alphas[];
50     private int savedy;
51     private int savedyrem;
52
53     /**
54      * Constructs an AreaAveragingScaleFilter that scales the pixels from
55      * its source Image as specified by the width and height parameters.
56      * @param width the target width to scale the image
57      * @param height the target height to scale the image
58      */

59     public AreaAveragingScaleFilter(int width, int height) {
60     super(width, height);
61     }
62
63     /**
64      * Detect if the data is being delivered with the necessary hints
65      * to allow the averaging algorithm to do its work.
66      * <p>
67      * Note: This method is intended to be called by the
68      * <code>ImageProducer</code> of the <code>Image</code> whose
69      * pixels are being filtered. Developers using
70      * this class to filter pixels from an image should avoid calling
71      * this method directly since that operation could interfere
72      * with the filtering operation.
73      * @see ImageConsumer#setHints
74      */

75     public void setHints(int hints) {
76     passthrough = ((hints & neededHints) != neededHints);
77     super.setHints(hints);
78     }
79
80     private void makeAccumBuffers() {
81     reds = new float[destWidth];
82     greens = new float[destWidth];
83     blues = new float[destWidth];
84     alphas = new float[destWidth];
85     }
86
87     private int[] calcRow() {
88     float origmult = ((float) srcWidth) * srcHeight;
89     if (outpixbuf == null || !(outpixbuf instanceof int[])) {
90         outpixbuf = new int[destWidth];
91     }
92     int[] outpix = (int[]) outpixbuf;
93     for (int x = 0; x < destWidth; x++) {
94             float mult = origmult;
95         int a = Math.round(alphas[x] / mult);
96             if (a <= 0) {
97                 a = 0;
98             } else if (a >= 255) {
99                 a = 255;
100             } else {
101                 // un-premultiply the components (by modifying mult here, we
102
// are effectively doing the divide by mult and divide by
103
// alpha in the same step)
104
mult = alphas[x] / 255;
105             }
106         int r = Math.round(reds[x] / mult);
107         int g = Math.round(greens[x] / mult);
108         int b = Math.round(blues[x] / mult);
109         if (r < 0) {r = 0;} else if (r > 255) {r = 255;}
110         if (g < 0) {g = 0;} else if (g > 255) {g = 255;}
111         if (b < 0) {b = 0;} else if (b > 255) {b = 255;}
112         outpix[x] = (a << 24 | r << 16 | g << 8 | b);
113     }
114     return outpix;
115     }
116
117     private void accumPixels(int x, int y, int w, int h,
118                  ColorModel JavaDoc model, Object JavaDoc pixels, int off,
119                  int scansize) {
120     if (reds == null) {
121         makeAccumBuffers();
122     }
123     int sy = y;
124     int syrem = destHeight;
125     int dy, dyrem;
126     if (sy == 0) {
127         dy = 0;
128         dyrem = 0;
129     } else {
130         dy = savedy;
131         dyrem = savedyrem;
132     }
133     while (sy < y + h) {
134         int amty;
135         if (dyrem == 0) {
136         for (int i = 0; i < destWidth; i++) {
137             alphas[i] = reds[i] = greens[i] = blues[i] = 0f;
138         }
139         dyrem = srcHeight;
140         }
141         if (syrem < dyrem) {
142         amty = syrem;
143         } else {
144         amty = dyrem;
145         }
146         int sx = 0;
147         int dx = 0;
148         int sxrem = 0;
149         int dxrem = srcWidth;
150         float a = 0f, r = 0f, g = 0f, b = 0f;
151         while (sx < w) {
152         if (sxrem == 0) {
153             sxrem = destWidth;
154             int rgb;
155             if (pixels instanceof byte[]) {
156             rgb = ((byte[]) pixels)[off + sx] & 0xff;
157             } else {
158             rgb = ((int[]) pixels)[off + sx];
159             }
160                     // getRGB() always returns non-premultiplied components
161
rgb = model.getRGB(rgb);
162             a = rgb >>> 24;
163             r = (rgb >> 16) & 0xff;
164             g = (rgb >> 8) & 0xff;
165                     b = rgb & 0xff;
166                     // premultiply the components if necessary
167
if (a != 255.0f) {
168                         float ascale = a / 255.0f;
169                         r *= ascale;
170                         g *= ascale;
171                         b *= ascale;
172                     }
173         }
174         int amtx;
175         if (sxrem < dxrem) {
176             amtx = sxrem;
177         } else {
178             amtx = dxrem;
179         }
180         float mult = ((float) amtx) * amty;
181         alphas[dx] += mult * a;
182         reds[dx] += mult * r;
183         greens[dx] += mult * g;
184         blues[dx] += mult * b;
185         if ((sxrem -= amtx) == 0) {
186             sx++;
187         }
188         if ((dxrem -= amtx) == 0) {
189             dx++;
190             dxrem = srcWidth;
191         }
192         }
193         if ((dyrem -= amty) == 0) {
194         int outpix[] = calcRow();
195         do {
196             consumer.setPixels(0, dy, destWidth, 1,
197                        rgbmodel, outpix, 0, destWidth);
198             dy++;
199         } while ((syrem -= amty) >= amty && amty == srcHeight);
200         } else {
201         syrem -= amty;
202         }
203         if (syrem == 0) {
204         syrem = destHeight;
205         sy++;
206         off += scansize;
207         }
208     }
209     savedyrem = dyrem;
210     savedy = dy;
211     }
212
213     /**
214      * Combine the components for the delivered byte pixels into the
215      * accumulation arrays and send on any averaged data for rows of
216      * pixels that are complete. If the correct hints were not
217      * specified in the setHints call then relay the work to our
218      * superclass which is capable of scaling pixels regardless of
219      * the delivery hints.
220      * <p>
221      * Note: This method is intended to be called by the
222      * <code>ImageProducer</code> of the <code>Image</code>
223      * whose pixels are being filtered. Developers using
224      * this class to filter pixels from an image should avoid calling
225      * this method directly since that operation could interfere
226      * with the filtering operation.
227      * @see ReplicateScaleFilter
228      */

229     public void setPixels(int x, int y, int w, int h,
230               ColorModel JavaDoc model, byte pixels[], int off,
231               int scansize) {
232     if (passthrough) {
233         super.setPixels(x, y, w, h, model, pixels, off, scansize);
234     } else {
235         accumPixels(x, y, w, h, model, pixels, off, scansize);
236     }
237     }
238
239     /**
240      * Combine the components for the delivered int pixels into the
241      * accumulation arrays and send on any averaged data for rows of
242      * pixels that are complete. If the correct hints were not
243      * specified in the setHints call then relay the work to our
244      * superclass which is capable of scaling pixels regardless of
245      * the delivery hints.
246      * <p>
247      * Note: This method is intended to be called by the
248      * <code>ImageProducer</code> of the <code>Image</code>
249      * whose pixels are being filtered. Developers using
250      * this class to filter pixels from an image should avoid calling
251      * this method directly since that operation could interfere
252      * with the filtering operation.
253      * @see ReplicateScaleFilter
254      */

255     public void setPixels(int x, int y, int w, int h,
256               ColorModel JavaDoc model, int pixels[], int off,
257               int scansize) {
258     if (passthrough) {
259         super.setPixels(x, y, w, h, model, pixels, off, scansize);
260     } else {
261         accumPixels(x, y, w, h, model, pixels, off, scansize);
262     }
263     }
264 }
265
Popular Tags