// ImageFilterPlus - an ImageFilter with some extra features and bug fixes // // Copyright (C) 1996 by Jef Poskanzer . All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. // // Visit the ACME Labs Java page for up-to-date versions of this and other // fine Java utilities: http://www.acme.com/java/ package Acme.JPM.Filters; import java.awt.image.*; import java.io.*; import Acme.JPM.Decoders.*; import Acme.JPM.Encoders.*; /// An ImageFilter with some extra features and bug fixes. //

// You can use an image filter to turn one Image into another via // a FilteredImageSource, e.g.: //

// Image newImage = comp.createImage( new FilteredImageSource(
//     oldImage.getSource(), new SomeFilter( oldImage.getSource() ) ) );
// 
// Or use the convenient utility JPMUtils.filterImage(): //
// Image newImage = JPMUtils.filterImage(
//     comp, SomeFilter( oldImage.getSource() ) );
// 
//

// You can also use image filters from the command line, reading PPM // from stdin and writing PPM to stdout, if you add code like the following // to each filter: //

// System.exit( 
//     ImageFilterPlus.filterStream(
//         System.in, System.out,
//         new SomeFilter( null ) ) );
// 
//

// Fetch the software.
// Fetch the entire Acme package. public class ImageFilterPlus extends ImageFilter { private ImageProducer producer; private boolean pixelOrderChanges; /// Constructor. // @param producer The ImageProducer is required, so that we can // remove ourself from its consumers list when we're done. // However, if you don't have the producer available when you want // to create the filter, you can pass in null and set it later // via setSource(). public ImageFilterPlus( ImageProducer producer ) { this( producer, false ); } /// Constructor, with pixel order change. // @param producer The ImageProducer is required, so that we can // remove ourself from its consumers list when we're done. // However, if you don't have the producer available when you want // to create the filter, you can pass in null and set it later // via setSource(). // @param pixelOrderChanges If the filter may output pixels in a different // order from the one they were delivered in, this flag must be set. public ImageFilterPlus( ImageProducer producer, boolean pixelOrderChanges ) { setSource( producer ); this.pixelOrderChanges = pixelOrderChanges; } /// The default color model - useful for comparisons. public static final ColorModel rgbModel = ColorModel.getRGBdefault(); /// Return the ImageProducer for this filter. public ImageProducer getSource() { return producer; } /// Set the ImageProducer for this filter, if it wasn't set by the // constructor. public void setSource( ImageProducer producer ) { this.producer = producer; } /// Set the hint flags. If the pixel order may change, we have to // turn off the TOPDOWNLEFTRIGHT flag; otherwise the flags are passed // through unmodified. public void setHints( int hintflags ) { if ( pixelOrderChanges ) hintflags &= ~TOPDOWNLEFTRIGHT; consumer.setHints( hintflags ); } /// This routine fixes a bug in java.awt.image.ImageFilter. All // ImageConsumers are required remove themselves from the producer's // list when they're done reading. If they don't do this then some // producers will generate an error. The standard ImageFilter class // fails to do this, but this one does it. public void imageComplete( int status ) { if ( status != ImageConsumer.SINGLEFRAMEDONE ) producer.removeConsumer( this ); super.imageComplete( status ); } /// Filter a PPM InputStream to a PPM OutputStream. //

// Create the filter with a null producer, and this routine will // fill it in for you. // @return a status code suitable for use with System.exit(). public static int filterStream( InputStream in, OutputStream out, ImageFilterPlus filter ) { ImageDecoder producer = new PpmDecoder( in ); filter.setSource( producer ); try { ImageEncoder consumer = new PpmEncoder( new FilteredImageSource( producer, filter ), out ); consumer.encode(); } catch ( IOException e ) { System.err.println( e.toString() ); return 1; } return 0; } }