1/*
2 * Copyright (c) 1995, 2014, 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
26package java.awt.image;
27
28import java.util.Hashtable;
29
30/**
31 * This class implements a filter for the set of interface methods that
32 * are used to deliver data from an ImageProducer to an ImageConsumer.
33 * It is meant to be used in conjunction with a FilteredImageSource
34 * object to produce filtered versions of existing images.  It is a
35 * base class that provides the calls needed to implement a "Null filter"
36 * which has no effect on the data being passed through.  Filters should
37 * subclass this class and override the methods which deal with the
38 * data that needs to be filtered and modify it as necessary.
39 *
40 * @see FilteredImageSource
41 * @see ImageConsumer
42 *
43 * @author      Jim Graham
44 */
45public class ImageFilter implements ImageConsumer, Cloneable {
46    /**
47     * The consumer of the particular image data stream for which this
48     * instance of the ImageFilter is filtering data.  It is not
49     * initialized during the constructor, but rather during the
50     * getFilterInstance() method call when the FilteredImageSource
51     * is creating a unique instance of this object for a particular
52     * image data stream.
53     * @see #getFilterInstance
54     * @see ImageConsumer
55     */
56    protected ImageConsumer consumer;
57
58    /**
59     * Returns a unique instance of an ImageFilter object which will
60     * actually perform the filtering for the specified ImageConsumer.
61     * The default implementation just clones this object.
62     * <p>
63     * Note: This method is intended to be called by the ImageProducer
64     * of the Image whose pixels are being filtered.  Developers using
65     * this class to filter pixels from an image should avoid calling
66     * this method directly since that operation could interfere
67     * with the filtering operation.
68     * @param ic the specified {@code ImageConsumer}
69     * @return an {@code ImageFilter} used to perform the
70     *         filtering for the specified {@code ImageConsumer}.
71     */
72    public ImageFilter getFilterInstance(ImageConsumer ic) {
73        ImageFilter instance = (ImageFilter) clone();
74        instance.consumer = ic;
75        return instance;
76    }
77
78    /**
79     * Filters the information provided in the setDimensions method
80     * of the ImageConsumer interface.
81     * <p>
82     * Note: This method is intended to be called by the ImageProducer
83     * of the Image whose pixels are being filtered.  Developers using
84     * this class to filter pixels from an image should avoid calling
85     * this method directly since that operation could interfere
86     * with the filtering operation.
87     * @see ImageConsumer#setDimensions
88     */
89    public void setDimensions(int width, int height) {
90        consumer.setDimensions(width, height);
91    }
92
93    /**
94     * Passes the properties from the source object along after adding a
95     * property indicating the stream of filters it has been run through.
96     * <p>
97     * Note: This method is intended to be called by the ImageProducer
98     * of the Image whose pixels are being filtered.  Developers using
99     * this class to filter pixels from an image should avoid calling
100     * this method directly since that operation could interfere
101     * with the filtering operation.
102     *
103     * @param props the properties from the source object
104     * @exception NullPointerException if {@code props} is null
105     */
106    public void setProperties(Hashtable<?,?> props) {
107        @SuppressWarnings("unchecked")
108        Hashtable<Object,Object> p = (Hashtable<Object,Object>)props.clone();
109        Object o = p.get("filters");
110        if (o == null) {
111            p.put("filters", toString());
112        } else if (o instanceof String) {
113            p.put("filters", ((String) o)+toString());
114        }
115        consumer.setProperties(p);
116    }
117
118    /**
119     * Filter the information provided in the setColorModel method
120     * of the ImageConsumer interface.
121     * <p>
122     * Note: This method is intended to be called by the ImageProducer
123     * of the Image whose pixels are being filtered.  Developers using
124     * this class to filter pixels from an image should avoid calling
125     * this method directly since that operation could interfere
126     * with the filtering operation.
127     * @see ImageConsumer#setColorModel
128     */
129    public void setColorModel(ColorModel model) {
130        consumer.setColorModel(model);
131    }
132
133    /**
134     * Filters the information provided in the setHints method
135     * of the ImageConsumer interface.
136     * <p>
137     * Note: This method is intended to be called by the ImageProducer
138     * of the Image whose pixels are being filtered.  Developers using
139     * this class to filter pixels from an image should avoid calling
140     * this method directly since that operation could interfere
141     * with the filtering operation.
142     * @see ImageConsumer#setHints
143     */
144    public void setHints(int hints) {
145        consumer.setHints(hints);
146    }
147
148    /**
149     * Filters the information provided in the setPixels method of the
150     * ImageConsumer interface which takes an array of bytes.
151     * <p>
152     * Note: This method is intended to be called by the ImageProducer
153     * of the Image whose pixels are being filtered.  Developers using
154     * this class to filter pixels from an image should avoid calling
155     * this method directly since that operation could interfere
156     * with the filtering operation.
157     * @see ImageConsumer#setPixels
158     */
159    public void setPixels(int x, int y, int w, int h,
160                          ColorModel model, byte pixels[], int off,
161                          int scansize) {
162        consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
163    }
164
165    /**
166     * Filters the information provided in the setPixels method of the
167     * ImageConsumer interface which takes an array of integers.
168     * <p>
169     * Note: This method is intended to be called by the ImageProducer
170     * of the Image whose pixels are being filtered.  Developers using
171     * this class to filter pixels from an image should avoid calling
172     * this method directly since that operation could interfere
173     * with the filtering operation.
174     * @see ImageConsumer#setPixels
175     */
176    public void setPixels(int x, int y, int w, int h,
177                          ColorModel model, int pixels[], int off,
178                          int scansize) {
179        consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
180    }
181
182    /**
183     * Filters the information provided in the imageComplete method of
184     * the ImageConsumer interface.
185     * <p>
186     * Note: This method is intended to be called by the ImageProducer
187     * of the Image whose pixels are being filtered.  Developers using
188     * this class to filter pixels from an image should avoid calling
189     * this method directly since that operation could interfere
190     * with the filtering operation.
191     * @see ImageConsumer#imageComplete
192     */
193    public void imageComplete(int status) {
194        consumer.imageComplete(status);
195    }
196
197    /**
198     * Responds to a request for a TopDownLeftRight (TDLR) ordered resend
199     * of the pixel data from an {@code ImageConsumer}.
200     * When an {@code ImageConsumer} being fed
201     * by an instance of this {@code ImageFilter}
202     * requests a resend of the data in TDLR order,
203     * the {@code FilteredImageSource}
204     * invokes this method of the {@code ImageFilter}.
205     *
206     * <p>
207     *
208     * An {@code ImageFilter} subclass might override this method or not,
209     * depending on if and how it can send data in TDLR order.
210     * Three possibilities exist:
211     *
212     * <ul>
213     * <li>
214     * Do not override this method.
215     * This makes the subclass use the default implementation,
216     * which is to
217     * forward the request
218     * to the indicated {@code ImageProducer}
219     * using this filter as the requesting {@code ImageConsumer}.
220     * This behavior
221     * is appropriate if the filter can determine
222     * that it will forward the pixels
223     * in TDLR order if its upstream producer object
224     * sends them in TDLR order.
225     *
226     * <li>
227     * Override the method to simply send the data.
228     * This is appropriate if the filter can handle the request itself &#8212;
229     * for example,
230     * if the generated pixels have been saved in some sort of buffer.
231     *
232     * <li>
233     * Override the method to do nothing.
234     * This is appropriate
235     * if the filter cannot produce filtered data in TDLR order.
236     * </ul>
237     *
238     * @see ImageProducer#requestTopDownLeftRightResend
239     * @param ip the ImageProducer that is feeding this instance of
240     * the filter - also the ImageProducer that the request should be
241     * forwarded to if necessary
242     * @exception NullPointerException if {@code ip} is null
243     */
244    public void resendTopDownLeftRight(ImageProducer ip) {
245        ip.requestTopDownLeftRightResend(this);
246    }
247
248    /**
249     * Clones this object.
250     */
251    public Object clone() {
252        try {
253            return super.clone();
254        } catch (CloneNotSupportedException e) {
255            // this shouldn't happen, since we are Cloneable
256            throw new InternalError(e);
257        }
258    }
259}
260