001: /*
002: * @(#)ReplicateScaleFilter.java 1.12 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.awt.image;
029:
030: import java.awt.image.ImageConsumer;
031: import java.awt.image.ColorModel;
032: import java.util.Hashtable;
033: import java.awt.Rectangle;
034:
035: /**
036: * An ImageFilter class for scaling images using the simplest algorithm.
037: * This class extends the basic ImageFilter Class to scale an existing
038: * image and provide a source for a new image containing the resampled
039: * image. The pixels in the source image are sampled to produce pixels
040: * for an image of the specified size by replicating rows and columns of
041: * pixels to scale up or omitting rows and columns of pixels to scale
042: * down.
043: * It is meant to be used in conjunction with a FilteredImageSource
044: * object to produce scaled versions of existing images.
045: *
046: * @see FilteredImageSource
047: * @see ImageFilter
048: *
049: * @version 1.8 08/19/02
050: * @author Jim Graham
051: */
052:
053: public class ReplicateScaleFilter extends ImageFilter {
054: /**
055: * The width of the source image.
056: */
057: protected int srcWidth;
058: /**
059: * The height of the source image.
060: */
061: protected int srcHeight;
062: /**
063: * The target width to scale the image.
064: */
065: protected int destWidth;
066: /**
067: * The target height to scale the image.
068: */
069: protected int destHeight;
070: /**
071: * An <code>int</code> array containing information about a
072: * row of pixels.
073: */
074: protected int srcrows[];
075: /**
076: * An <code>int</code> array containing information about a
077: * column of pixels.
078: */
079: protected int srccols[];
080: /**
081: * A <code>byte</code> array initialized with a size of
082: * {@link #destWidth} and used to deliver a row of pixel
083: * data to the {@link ImageConsumer}.
084: */
085: protected Object outpixbuf;
086:
087: /**
088: * Constructs a ReplicateScaleFilter that scales the pixels from
089: * its source Image as specified by the width and height parameters.
090: * @param width the target width to scale the image
091: * @param height the target height to scale the image
092: * @throws IllegalArgumentException if <code>width</code> equals
093: * zero or <code>height</code> equals zero
094: */
095: public ReplicateScaleFilter(int width, int height) {
096: if (width == 0 || height == 0) {
097: throw new IllegalArgumentException("Width (" + width
098: + ") and height (" + height + ") must be non-zero");
099: }
100: destWidth = width;
101: destHeight = height;
102: }
103:
104: /**
105: * Passes along the properties from the source object after adding a
106: * property indicating the scale applied.
107: * <p>
108: * Note: This method is intended to be called by the
109: * <code>ImageProducer</code> of the <code>Image</code> whose pixels
110: * 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 setProperties(Hashtable props) {
116: props = (Hashtable) props.clone();
117: String key = "rescale";
118: String val = destWidth + "x" + destHeight;
119: Object o = props.get(key);
120: if (o != null && o instanceof String) {
121: val = ((String) o) + ", " + val;
122: }
123: props.put(key, val);
124: super .setProperties(props);
125: }
126:
127: /**
128: * Override the dimensions of the source image and pass the dimensions
129: * of the new scaled size to the ImageConsumer.
130: * <p>
131: * Note: This method is intended to be called by the
132: * <code>ImageProducer</code> of the <code>Image</code> whose pixels
133: * are being filtered. Developers using
134: * this class to filter pixels from an image should avoid calling
135: * this method directly since that operation could interfere
136: * with the filtering operation.
137: * @see ImageConsumer
138: */
139: public void setDimensions(int w, int h) {
140: srcWidth = w;
141: srcHeight = h;
142: if (destWidth < 0) {
143: if (destHeight < 0) {
144: destWidth = srcWidth;
145: destHeight = srcHeight;
146: } else {
147: destWidth = srcWidth * destHeight / srcHeight;
148: }
149: } else if (destHeight < 0) {
150: destHeight = srcHeight * destWidth / srcWidth;
151: }
152: consumer.setDimensions(destWidth, destHeight);
153: }
154:
155: private void calculateMaps() {
156: srcrows = new int[destHeight + 1];
157: for (int y = 0; y <= destHeight; y++) {
158: srcrows[y] = (2 * y * srcHeight + srcHeight)
159: / (2 * destHeight);
160: }
161: srccols = new int[destWidth + 1];
162: for (int x = 0; x <= destWidth; x++) {
163: srccols[x] = (2 * x * srcWidth + srcWidth)
164: / (2 * destWidth);
165: }
166: }
167:
168: /**
169: * Choose which rows and columns of the delivered byte pixels are
170: * needed for the destination scaled image and pass through just
171: * those rows and columns that are needed, replicated as necessary.
172: * <p>
173: * Note: This method is intended to be called by the
174: * <code>ImageProducer</code> of the <code>Image</code> whose pixels
175: * are being filtered. Developers using
176: * this class to filter pixels from an image should avoid calling
177: * this method directly since that operation could interfere
178: * with the filtering operation.
179: */
180: public void setPixels(int x, int y, int w, int h, ColorModel model,
181: byte pixels[], int off, int scansize) {
182: if (srcrows == null || srccols == null) {
183: calculateMaps();
184: }
185: int sx, sy;
186: int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * srcWidth);
187: int dy1 = (2 * y * destHeight + srcHeight - 1)
188: / (2 * srcHeight);
189: byte outpix[];
190: if (outpixbuf != null && outpixbuf instanceof byte[]) {
191: outpix = (byte[]) outpixbuf;
192: } else {
193: outpix = new byte[destWidth];
194: outpixbuf = outpix;
195: }
196: for (int dy = dy1; (sy = srcrows[dy]) < y + h; dy++) {
197: int srcoff = off + scansize * (sy - y);
198: int dx;
199: for (dx = dx1; (sx = srccols[dx]) < x + w; dx++) {
200: outpix[dx] = pixels[srcoff + sx];
201: }
202: if (dx > dx1) {
203: consumer.setPixels(dx1, dy, dx - dx1, 1, model, outpix,
204: dx1, destWidth);
205: }
206: }
207: }
208:
209: /**
210: * Choose which rows and columns of the delivered int pixels are
211: * needed for the destination scaled image and pass through just
212: * those rows and columns that are needed, replicated as necessary.
213: * <p>
214: * Note: This method is intended to be called by the
215: * <code>ImageProducer</code> of the <code>Image</code> whose pixels
216: * are being filtered. Developers using
217: * this class to filter pixels from an image should avoid calling
218: * this method directly since that operation could interfere
219: * with the filtering operation.
220: */
221: public void setPixels(int x, int y, int w, int h, ColorModel model,
222: int pixels[], int off, int scansize) {
223: if (srcrows == null || srccols == null) {
224: calculateMaps();
225: }
226: int sx, sy;
227: int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * srcWidth);
228: int dy1 = (2 * y * destHeight + srcHeight - 1)
229: / (2 * srcHeight);
230: int outpix[];
231: if (outpixbuf != null && outpixbuf instanceof int[]) {
232: outpix = (int[]) outpixbuf;
233: } else {
234: outpix = new int[destWidth];
235: outpixbuf = outpix;
236: }
237: for (int dy = dy1; (sy = srcrows[dy]) < y + h; dy++) {
238: int srcoff = off + scansize * (sy - y);
239: int dx;
240: for (dx = dx1; (sx = srccols[dx]) < x + w; dx++) {
241: outpix[dx] = pixels[srcoff + sx];
242: }
243: if (dx > dx1) {
244: consumer.setPixels(dx1, dy, dx - dx1, 1, model, outpix,
245: dx1, destWidth);
246: }
247: }
248: }
249: }
|