/* * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package java.awt.image; import java.awt.Image; import java.awt.image.ImageFilter; import java.awt.image.ImageConsumer; import java.awt.image.ImageProducer; import java.util.Hashtable; import java.awt.image.ColorModel; /** * This class is an implementation of the ImageProducer interface which * takes an existing image and a filter object and uses them to produce * image data for a new filtered version of the original image. * Here is an example which filters an image by swapping the red and * blue compents: *
 *
 *      Image src = getImage("doc:///demo/images/duke/T1.gif");
 *      ImageFilter colorfilter = new RedBlueSwapFilter();
 *      Image img = createImage(new FilteredImageSource(src.getSource(),
 *                                                      colorfilter));
 *
 * 
 *
 * @see ImageProducer
 *
 * @author      Jim Graham
 */
public class FilteredImageSource implements ImageProducer {
    ImageProducer src;
    ImageFilter filter;
    /**
     * Constructs an ImageProducer object from an existing ImageProducer
     * and a filter object.
     * @param orig the specified ImageProducer
     * @param imgf the specified ImageFilter
     * @see ImageFilter
     * @see java.awt.Component#createImage
     */
    public FilteredImageSource(ImageProducer orig, ImageFilter imgf) {
        src = orig;
        filter = imgf;
    }
    private Hashtable proxies;
    /**
     * Adds the specified ImageConsumer
     * to the list of consumers interested in data for the filtered image.
     * An instance of the original ImageFilter
     * is created
     * (using the filter's getFilterInstance method)
     * to manipulate the image data
     * for the specified ImageConsumer.
     * The newly created filter instance
     * is then passed to the addConsumer method
     * of the original ImageProducer.
     *
     * 
     * This method is public as a side effect
     * of this class implementing
     * the ImageProducer interface.
     * It should not be called from user code,
     * and its behavior if called from user code is unspecified.
     *
     * @param ic  the consumer for the filtered image
     * @see ImageConsumer
     */
    public synchronized void addConsumer(ImageConsumer ic) {
        if (proxies == null) {
            proxies = new Hashtable();
        }
        if (!proxies.containsKey(ic)) {
            ImageFilter imgf = filter.getFilterInstance(ic);
            proxies.put(ic, imgf);
            src.addConsumer(imgf);
        }
    }
    /**
     * Determines whether an ImageConsumer is on the list of consumers
     * currently interested in data for this image.
     *
     * 
     * This method is public as a side effect
     * of this class implementing
     * the ImageProducer interface.
     * It should not be called from user code,
     * and its behavior if called from user code is unspecified.
     *
     * @param ic the specified ImageConsumer
     * @return true if the ImageConsumer is on the list; false otherwise
     * @see ImageConsumer
     */
    public synchronized boolean isConsumer(ImageConsumer ic) {
        return (proxies != null && proxies.containsKey(ic));
    }
    /**
     * Removes an ImageConsumer from the list of consumers interested in
     * data for this image.
     *
     * 
     * This method is public as a side effect
     * of this class implementing
     * the ImageProducer interface.
     * It should not be called from user code,
     * and its behavior if called from user code is unspecified.
     *
     * @see ImageConsumer
     */
    public synchronized void removeConsumer(ImageConsumer ic) {
        if (proxies != null) {
            ImageFilter imgf = (ImageFilter) proxies.get(ic);
            if (imgf != null) {
                src.removeConsumer(imgf);
                proxies.remove(ic);
                if (proxies.isEmpty()) {
                    proxies = null;
                }
            }
        }
    }
    /**
     * Starts production of the filtered image.
     * If the specified ImageConsumer
     * isn't already a consumer of the filtered image,
     * an instance of the original ImageFilter
     * is created
     * (using the filter's getFilterInstance method)
     * to manipulate the image data
     * for the ImageConsumer.
     * The filter instance for the ImageConsumer
     * is then passed to the startProduction method
     * of the original ImageProducer.
     *
     * 
     * This method is public as a side effect
     * of this class implementing
     * the ImageProducer interface.
     * It should not be called from user code,
     * and its behavior if called from user code is unspecified.
     *
     * @param ic  the consumer for the filtered image
     * @see ImageConsumer
     */
    public void startProduction(ImageConsumer ic) {
        if (proxies == null) {
            proxies = new Hashtable();
        }
        ImageFilter imgf = (ImageFilter) proxies.get(ic);
        if (imgf == null) {
            imgf = filter.getFilterInstance(ic);
            proxies.put(ic, imgf);
        }
        src.startProduction(imgf);
    }
    /**
     * Requests that a given ImageConsumer have the image data delivered
     * one more time in top-down, left-right order.  The request is
     * handed to the ImageFilter for further processing, since the
     * ability to preserve the pixel ordering depends on the filter.
     *
     * 
     * This method is public as a side effect
     * of this class implementing
     * the ImageProducer interface.
     * It should not be called from user code,
     * and its behavior if called from user code is unspecified.
     *
     * @see ImageConsumer
     */
    public void requestTopDownLeftRightResend(ImageConsumer ic) {
        if (proxies != null) {
            ImageFilter imgf = (ImageFilter) proxies.get(ic);
            if (imgf != null) {
                imgf.resendTopDownLeftRight(src);
            }
        }
    }
}