removed unused classes

This commit is contained in:
hns 2002-10-02 14:46:17 +00:00
parent 8731eaffc7
commit c8a85d5a04
45 changed files with 0 additions and 8999 deletions

View file

@ -1,613 +0,0 @@
// Fmt - some simple single-arg sprintf-like routines
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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;
/// Some simple single-arg sprintf-like routines.
// <P>
// It is apparently impossible to declare a Java method that accepts
// variable numbers of any type of argument. You can declare it to take
// Objects, but numeric variables and constants are not in fact Objects.
// <P>
// However, using the built-in string concatenation, it's almost as
// convenient to make a series of single-argument formatting routines.
// <P>
// Fmt can format the following types:
// <BLOCKQUOTE><CODE>
// byte short int long float double char String Object
// </CODE></BLOCKQUOTE>
// For each type there is a set of overloaded methods, each returning
// a formatted String. There's the plain formatting version:
// <BLOCKQUOTE><PRE>
// Fmt.fmt( x )
// </PRE></BLOCKQUOTE>
// There's a version specifying a minimum field width:
// <BLOCKQUOTE><PRE>
// Fmt.fmt( x, minWidth )
// </PRE></BLOCKQUOTE>
// And there's a version that takes flags:
// <BLOCKQUOTE><PRE>
// Fmt.fmt( x, minWidth, flags )
// </PRE></BLOCKQUOTE>
// Currently available flags are:
// <BLOCKQUOTE><PRE>
// Fmt.ZF - zero-fill
// Fmt.LJ - left justify
// Fmt.HX - hexadecimal
// Fmt.OC - octal
// </PRE></BLOCKQUOTE>
// The HX and OC flags imply unsigned output.
// <P>
// For doubles and floats, there's a significant-figures parameter before
// the flags:
// <BLOCKQUOTE><PRE>
// Fmt.fmt( d )
// Fmt.fmt( d, minWidth )
// Fmt.fmt( d, minWidth, sigFigs )
// Fmt.fmt( d, minWidth, sigFigs, flags )
// </PRE></BLOCKQUOTE>
// <P>
// <A HREF="/resources/classes/Acme/Fmt.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <HR>
// Similar classes:
// <UL>
// <LI> Andrew Scherpbier's <A HREF="http://www.sdsu.edu/doc/java-SDSU/sdsu.FormatString.html">FormatString</A>
// Tries to allow variable numbers of arguments by
// supplying overloaded routines with different combinations of parameters,
// but doesn't actually supply that many. The floating point conversion
// is described as "very incomplete".
// <LI> Core Java's <A HREF="http://www.apl.jhu.edu/~hall/java/CoreJava-Format.html">Format</A>.
// The design seems a little weird. They want you to create an instance,
// passing the format string to the constructor, and then call an instance
// method with your data to do the actual formatting. The extra steps are
// pointless; better to just use static methods.
// </UL>
public class Fmt
{
// Flags.
/// Zero-fill.
public static final int ZF = 1;
/// Left justify.
public static final int LJ = 2;
/// Hexadecimal.
public static final int HX = 4;
/// Octal.
public static final int OC = 8;
// Was a number - internal use.
private static final int WN = 16;
// byte
public static String fmt( byte b )
{
return fmt( b, 0, 0 );
}
public static String fmt( byte b, int minWidth )
{
return fmt( b, minWidth, 0 );
}
public static String fmt( byte b, int minWidth, int flags )
{
boolean hexadecimal = ( ( flags & HX ) != 0 );
boolean octal = ( ( flags & OC ) != 0 );
if ( hexadecimal )
return fmt( Integer.toString( b & 0xff, 16 ), minWidth, flags|WN );
else if ( octal )
return fmt( Integer.toString( b & 0xff, 8 ), minWidth, flags|WN );
else
return fmt( Integer.toString( b & 0xff ), minWidth, flags|WN );
}
// short
public static String fmt( short s )
{
return fmt( s, 0, 0 );
}
public static String fmt( short s, int minWidth )
{
return fmt( s, minWidth, 0 );
}
public static String fmt( short s, int minWidth, int flags )
{
boolean hexadecimal = ( ( flags & HX ) != 0 );
boolean octal = ( ( flags & OC ) != 0 );
if ( hexadecimal )
return fmt(
Integer.toString( s & 0xffff, 16 ), minWidth, flags|WN );
else if ( octal )
return fmt(
Integer.toString( s & 0xffff, 8 ), minWidth, flags|WN );
else
return fmt( Integer.toString( s ), minWidth, flags|WN );
}
// int
public static String fmt( int i )
{
return fmt( i, 0, 0 );
}
public static String fmt( int i, int minWidth )
{
return fmt( i, minWidth, 0 );
}
public static String fmt( int i, int minWidth, int flags )
{
boolean hexadecimal = ( ( flags & HX ) != 0 );
boolean octal = ( ( flags & OC ) != 0 );
if ( hexadecimal )
return fmt(
Long.toString( i & 0xffffffffL, 16 ), minWidth, flags|WN );
else if ( octal )
return fmt(
Long.toString( i & 0xffffffffL, 8 ), minWidth, flags|WN );
else
return fmt( Integer.toString( i ), minWidth, flags|WN );
}
// long
public static String fmt( long l )
{
return fmt( l, 0, 0 );
}
public static String fmt( long l, int minWidth )
{
return fmt( l, minWidth, 0 );
}
public static String fmt( long l, int minWidth, int flags )
{
boolean hexadecimal = ( ( flags & HX ) != 0 );
boolean octal = ( ( flags & OC ) != 0 );
if ( hexadecimal )
{
if ( ( l & 0xf000000000000000L ) != 0 )
return fmt(
Long.toString( l >>> 60, 16 ) +
fmt( l & 0x0fffffffffffffffL, 15, HX|ZF ),
minWidth, flags|WN );
else
return fmt( Long.toString( l, 16 ), minWidth, flags|WN );
}
else if ( octal )
{
if ( ( l & 0x8000000000000000L ) != 0 )
return fmt(
Long.toString( l >>> 63, 8 ) +
fmt( l & 0x7fffffffffffffffL, 21, OC|ZF ),
minWidth, flags|WN );
else
return fmt( Long.toString( l, 8 ), minWidth, flags|WN );
}
else
return fmt( Long.toString( l ), minWidth, flags|WN );
}
// float
public static String fmt( float f )
{
return fmt( f, 0, 0, 0 );
}
public static String fmt( float f, int minWidth )
{
return fmt( f, minWidth, 0, 0 );
}
public static String fmt( float f, int minWidth, int sigFigs )
{
return fmt( f, minWidth, sigFigs, 0 );
}
public static String fmt( float f, int minWidth, int sigFigs, int flags )
{
if ( sigFigs != 0 )
return fmt(
sigFigFix( Float.toString( f ), sigFigs ), minWidth,
flags|WN );
else
return fmt( Float.toString( f ), minWidth, flags|WN );
}
// double
public static String fmt( double d )
{
return fmt( d, 0, 0, 0 );
}
public static String fmt( double d, int minWidth )
{
return fmt( d, minWidth, 0, 0 );
}
public static String fmt( double d, int minWidth, int sigFigs )
{
return fmt( d, minWidth, sigFigs, 0 );
}
public static String fmt( double d, int minWidth, int sigFigs, int flags )
{
if ( sigFigs != 0 )
return fmt(
sigFigFix( doubleToString( d ), sigFigs ), minWidth,
flags|WN );
else
return fmt( doubleToString( d ), minWidth, flags|WN );
}
// char
public static String fmt( char c )
{
return fmt( c, 0, 0 );
}
public static String fmt( char c, int minWidth )
{
return fmt( c, minWidth, 0 );
}
public static String fmt( char c, int minWidth, int flags )
{
// return fmt( Character.toString( c ), minWidth, flags );
// Character currently lacks a static toString method. Workaround
// is to make a temporary instance and use the instance toString.
return fmt( new Character( c ).toString(), minWidth, flags );
}
// Object
public static String fmt( Object o )
{
return fmt( o, 0, 0 );
}
public static String fmt( Object o, int minWidth )
{
return fmt( o, minWidth, 0 );
}
public static String fmt( Object o, int minWidth, int flags )
{
return fmt( o.toString(), minWidth, flags );
}
// String
public static String fmt( String s )
{
return fmt( s, 0, 0 );
}
public static String fmt( String s, int minWidth )
{
return fmt( s, minWidth, 0 );
}
public static String fmt( String s, int minWidth, int flags )
{
int len = s.length();
boolean zeroFill = ( ( flags & ZF ) != 0 );
boolean leftJustify = ( ( flags & LJ ) != 0 );
boolean hexadecimal = ( ( flags & HX ) != 0 );
boolean octal = ( ( flags & OC ) != 0 );
boolean wasNumber = ( ( flags & WN ) != 0 );
if ( ( hexadecimal || octal || zeroFill ) && ! wasNumber )
throw new InternalError( "Acme.Fmt: number flag on a non-number" );
if ( zeroFill && leftJustify )
throw new InternalError( "Acme.Fmt: zero-fill left-justify is silly" );
if ( hexadecimal && octal )
throw new InternalError( "Acme.Fmt: can't do both hex and octal" );
if ( len >= minWidth )
return s;
int fillWidth = minWidth - len;
StringBuffer fill = new StringBuffer( fillWidth );
for ( int i = 0; i < fillWidth; ++i )
if ( zeroFill )
fill.append( '0' );
else
fill.append( ' ' );
if ( leftJustify )
return s + fill;
else if ( zeroFill && s.startsWith( "-" ) )
return "-" + fill + s.substring( 1 );
else
return fill + s;
}
// Internal routines.
private static String sigFigFix( String s, int sigFigs )
{
// First dissect the floating-point number string into sign,
// integer part, fraction part, and exponent.
String sign;
String unsigned;
if ( s.startsWith( "-" ) || s.startsWith( "+" ) )
{
sign = s.substring( 0, 1 );
unsigned = s.substring( 1 );
}
else
{
sign = "";
unsigned = s;
}
String mantissa;
String exponent;
int eInd = unsigned.indexOf( 'e' );
if ( eInd == -1 ) // it may be 'e' or 'E'
eInd = unsigned.indexOf( 'E' );
if ( eInd == -1 )
{
mantissa = unsigned;
exponent = "";
}
else
{
mantissa = unsigned.substring( 0, eInd );
exponent = unsigned.substring( eInd );
}
StringBuffer number, fraction;
int dotInd = mantissa.indexOf( '.' );
if ( dotInd == -1 )
{
number = new StringBuffer( mantissa );
fraction = new StringBuffer( "" );
}
else
{
number = new StringBuffer( mantissa.substring( 0, dotInd ) );
fraction = new StringBuffer( mantissa.substring( dotInd + 1 ) );
}
int numFigs = number.length();
int fracFigs = fraction.length();
if ( ( numFigs == 0 || number.equals( "0" ) ) && fracFigs > 0 )
{
// Don't count leading zeros in the fraction.
numFigs = 0;
for ( int i = 0; i < fraction.length(); ++i )
{
if ( fraction.charAt( i ) != '0' )
break;
--fracFigs;
}
}
int mantFigs = numFigs + fracFigs;
if ( sigFigs > mantFigs )
{
// We want more figures; just append zeros to the fraction.
for ( int i = mantFigs; i < sigFigs; ++i )
fraction.append( '0' );
}
else if ( sigFigs < mantFigs && sigFigs >= numFigs )
{
// Want fewer figures in the fraction; chop.
fraction.setLength(
fraction.length() - ( fracFigs - ( sigFigs - numFigs ) ) );
// Round?
}
else if ( sigFigs < numFigs )
{
// Want fewer figures in the number; turn them to zeros.
fraction.setLength( 0 ); // should already be zero, but make sure
for ( int i = sigFigs; i < numFigs; ++i )
number.setCharAt( i, '0' );
// Round?
}
// Else sigFigs == mantFigs, which is fine.
if ( fraction.length() == 0 )
return sign + number + exponent;
else
return sign + number + "." + fraction + exponent;
}
/// Improved version of Double.toString(), returns more decimal places.
// <P>
// The JDK 1.0.2 version of Double.toString() returns only six decimal
// places on some systems. In JDK 1.1 full precision is returned on
// all platforms.
// @deprecated
// @see java.lang.Double#toString
public static String doubleToString( double d )
{
// Handle special numbers first, to avoid complications.
if ( Double.isNaN( d ) )
return "NaN";
if ( d == Double.NEGATIVE_INFINITY )
return "-Inf";
if ( d == Double.POSITIVE_INFINITY )
return "Inf";
// Grab the sign, and then make the number positive for simplicity.
boolean negative = false;
if ( d < 0.0D )
{
negative = true;
d = -d;
}
// Get the native version of the unsigned value, as a template.
String unsStr = Double.toString( d );
// Dissect out the exponent.
String mantStr, expStr;
int exp;
int eInd = unsStr.indexOf( 'e' );
if ( eInd == -1 ) // it may be 'e' or 'E'
eInd = unsStr.indexOf( 'E' );
if ( eInd == -1 )
{
mantStr = unsStr;
expStr = "";
exp = 0;
}
else
{
mantStr = unsStr.substring( 0, eInd );
expStr = unsStr.substring( eInd + 1 );
if ( expStr.startsWith( "+" ) )
exp = Integer.parseInt( expStr.substring( 1 ) );
else
exp = Integer.parseInt( expStr );
}
// Dissect out the number part.
String numStr;
int dotInd = mantStr.indexOf( '.' );
if ( dotInd == -1 )
numStr = mantStr;
else
numStr = mantStr.substring( 0, dotInd );
long num;
if ( numStr.length() == 0 )
num = 0;
else
num = Integer.parseInt( numStr );
// Build the new mantissa.
StringBuffer newMantBuf = new StringBuffer( numStr + "." );
double p = Math.pow( 10, exp );
double frac = d - num * p;
String digits = "0123456789";
int nDigits = 16 - numStr.length(); // about 16 digits in a double
for ( int i = 0; i < nDigits; ++i )
{
p /= 10.0D;
int dig = (int) ( frac / p );
if ( dig < 0 ) dig = 0;
if ( dig > 9 ) dig = 9;
newMantBuf.append( digits.charAt( dig ) );
frac -= dig * p;
}
if ( (int) ( frac / p + 0.5D ) == 1 )
{
// Round up.
boolean roundMore = true;
for ( int i = newMantBuf.length() - 1; i >= 0; --i )
{
int dig = digits.indexOf( newMantBuf.charAt( i ) );
if ( dig == -1 )
continue;
++dig;
if ( dig == 10 )
{
newMantBuf.setCharAt( i, '0' );
continue;
}
newMantBuf.setCharAt( i, digits.charAt( dig ) );
roundMore = false;
break;
}
if ( roundMore )
{
// If this happens, we need to prepend a 1. But I haven't
// found a test case yet, so I'm leaving it out for now.
// But if you get this message, please let me know!
newMantBuf.append( "ROUNDMORE" );
}
}
// Chop any trailing zeros.
int len = newMantBuf.length();
while ( newMantBuf.charAt( len - 1 ) == '0' )
newMantBuf.setLength( --len );
// And chop a trailing dot, if any.
if ( newMantBuf.charAt( len - 1 ) == '.' )
newMantBuf.setLength( --len );
// Done.
return ( negative ? "-" : "" ) +
newMantBuf +
( expStr.length() != 0 ? ( "e" + expStr ) : "" );
}
/******************************************************************************
/// Test program.
public static void main( String[] args )
{
System.out.println( "Starting tests." );
show( Fmt.fmt( "Hello there." ) );
show( Fmt.fmt( 123 ) );
show( Fmt.fmt( 123, 10 ) );
show( Fmt.fmt( 123, 10, Fmt.ZF ) );
show( Fmt.fmt( 123, 10, Fmt.LJ ) );
show( Fmt.fmt( -123 ) );
show( Fmt.fmt( -123, 10 ) );
show( Fmt.fmt( -123, 10, Fmt.ZF ) );
show( Fmt.fmt( -123, 10, Fmt.LJ ) );
show( Fmt.fmt( (byte) 0xbe, 22, Fmt.OC ) );
show( Fmt.fmt( (short) 0xbabe, 22, Fmt.OC ) );
show( Fmt.fmt( 0xcafebabe, 22, Fmt.OC ) );
show( Fmt.fmt( 0xdeadbeefcafebabeL, 22, Fmt.OC ) );
show( Fmt.fmt( 0x8000000000000000L, 22, Fmt.OC ) );
show( Fmt.fmt( (byte) 0xbe, 16, Fmt.HX ) );
show( Fmt.fmt( (short) 0xbabe, 16, Fmt.HX ) );
show( Fmt.fmt( 0xcafebabe, 16, Fmt.HX ) );
show( Fmt.fmt( 0xdeadbeefcafebabeL, 16, Fmt.HX ) );
show( Fmt.fmt( 0x8000000000000000L, 16, Fmt.HX ) );
show( Fmt.fmt( 'c' ) );
show( Fmt.fmt( new java.util.Date() ) );
show( Fmt.fmt( 123.456F ) );
show( Fmt.fmt( 123456000000000000.0F ) );
show( Fmt.fmt( 123.456F, 0, 8 ) );
show( Fmt.fmt( 123.456F, 0, 7 ) );
show( Fmt.fmt( 123.456F, 0, 6 ) );
show( Fmt.fmt( 123.456F, 0, 5 ) );
show( Fmt.fmt( 123.456F, 0, 4 ) );
show( Fmt.fmt( 123.456F, 0, 3 ) );
show( Fmt.fmt( 123.456F, 0, 2 ) );
show( Fmt.fmt( 123.456F, 0, 1 ) );
show( Fmt.fmt( 123456000000000000.0F, 0, 4 ) );
show( Fmt.fmt( -123.456F, 0, 4 ) );
show( Fmt.fmt( -123456000000000000.0F, 0, 4 ) );
show( Fmt.fmt( 123.0F ) );
show( Fmt.fmt( 123.0D ) );
show( Fmt.fmt( 1.234567890123456789F ) );
show( Fmt.fmt( 1.234567890123456789D ) );
show( Fmt.fmt( 1234567890123456789F ) );
show( Fmt.fmt( 1234567890123456789D ) );
show( Fmt.fmt( 0.000000000000000000001234567890123456789F ) );
show( Fmt.fmt( 0.000000000000000000001234567890123456789D ) );
show( Fmt.fmt( 12300.0F ) );
show( Fmt.fmt( 12300.0D ) );
show( Fmt.fmt( 123000.0F ) );
show( Fmt.fmt( 123000.0D ) );
show( Fmt.fmt( 1230000.0F ) );
show( Fmt.fmt( 1230000.0D ) );
show( Fmt.fmt( 12300000.0F ) );
show( Fmt.fmt( 12300000.0D ) );
show( Fmt.fmt( Float.NaN ) );
show( Fmt.fmt( Float.POSITIVE_INFINITY ) );
show( Fmt.fmt( Float.NEGATIVE_INFINITY ) );
show( Fmt.fmt( Double.NaN ) );
show( Fmt.fmt( Double.POSITIVE_INFINITY ) );
show( Fmt.fmt( Double.NEGATIVE_INFINITY ) );
show( Fmt.fmt( 1.0F / 8.0F ) );
show( Fmt.fmt( 1.0D / 8.0D ) );
System.out.println( "Done with tests." );
}
private static void show( String str )
{
System.out.println( "#" + str + "#" );
}
******************************************************************************/
}

View file

@ -1,314 +0,0 @@
// ImageDecoder - abstract class for reading in an image
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.Decoders;
import java.util.*;
import java.io.*;
import java.awt.image.*;
/// Abstract class for reading in an image.
// <P>
// A framework for classes that read in and decode an image in
// a particular file format.
// <P>
// This provides a very simplified rendition of the ImageProducer interface.
// It requires the decoder to read the image a row at a time. It requires
// use of the RGBdefault color model.
// If you want more flexibility you can always implement ImageProducer
// directly.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Decoders/ImageDecoder.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see PpmDecoder
// @see Acme.JPM.Encoders.ImageEncoder
public abstract class ImageDecoder implements ImageProducer
{
private InputStream in;
private int width, height;
private boolean[] rowsRead;
private int[][] rgbPixels;
private boolean startedRead = false;
private boolean gotSize = false;
private boolean err = false;
private boolean producing = false;
private Vector consumers = new Vector();
private static final ColorModel model = ColorModel.getRGBdefault();
/// Constructor.
// @param in The stream to read the bytes from.
public ImageDecoder( InputStream in )
{
this.in = in;
}
// Methods that subclasses implement.
/// Subclasses implement this to read in enough of the image stream
// to figure out the width and height.
abstract void readHeader( InputStream in ) throws IOException;
/// Subclasses implement this to return the width, or -1 if not known.
abstract int getWidth();
/// Subclasses implement this to return the height, or -1 if not known.
abstract int getHeight();
/// Subclasses implement this to read pixel data into the rgbRow
// array, an int[width]. One int per pixel, no offsets or padding,
// RGBdefault (AARRGGBB) color model.
abstract void readRow( InputStream in, int row, int[] rgbRow ) throws IOException;
// Our own methods.
void readImage()
{
try
{
readHeader( in );
width = getWidth();
height = getHeight();
if ( width == -1 || height == -1 )
err = true;
else
{
rowsRead = new boolean[height];
for ( int row = 0; row < height; ++row )
rowsRead[row] = false;
gotSize = true;
notifyThem();
rgbPixels = new int[height][width];
for ( int row = 0; row < height; ++row )
{
readRow( in, row, rgbPixels[row] );
rowsRead[row] = true;
notifyThem();
}
}
}
catch ( IOException e )
{
err = true;
width = -1;
height = -1;
rowsRead = null;
rgbPixels = null;
}
}
private synchronized void notifyThem()
{
notifyAll();
}
void sendImage()
{
// Grab the list of consumers, in case it changes while we're sending.
ImageConsumer[] c = new ImageConsumer[consumers.size()];
int i;
for ( i = 0; i < c.length; ++i )
c[i] = (ImageConsumer) consumers.elementAt( i );
// Try to be as parallel as possible.
waitForSize();
for ( i = 0; i < c.length; ++i )
sendHead( c[i] );
for ( int row = 0; row < height; ++row )
for ( i = 0; i < c.length; ++i )
sendPixelRow( c[i], row );
for ( i = 0; i < c.length; ++i )
sendTail( c[i] );
producing = false;
}
private synchronized void waitForSize()
{
while ( ( ! err ) && ( ! gotSize ))
{
try
{
wait();
}
catch ( InterruptedException ignore ) {}
}
}
private synchronized void waitForRow( int row )
{
while ( ( ! err ) && ( ! rowsRead[row] ) )
{
try
{
wait();
}
catch ( InterruptedException ignore ) {}
}
}
private void sendHead( ImageConsumer ic )
{
if ( err )
return;
ic.setDimensions( width, height );
ic.setColorModel( model );
ic.setHints(
ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME );
}
private void sendPixelRow( ImageConsumer ic, int row )
{
if ( err )
return;
waitForRow( row );
if ( err )
return;
ic.setPixels( 0, row, width, 1, model, rgbPixels[row], 0, width );
}
private void sendTail( ImageConsumer ic )
{
if ( err )
ic.imageComplete( ImageConsumer.IMAGEERROR );
else
ic.imageComplete( ImageConsumer.STATICIMAGEDONE );
}
// Methods from ImageProducer.
/// This method is used to register an ImageConsumer with the
// ImageProducer for access to the image data during a later
// reconstruction of the Image. The ImageProducer may, at its
// discretion, start delivering the image data to the consumer
// using the ImageConsumer interface immediately, or when the
// next available image reconstruction is triggered by a call
// to the startProduction method.
// @see #startProduction
public void addConsumer( ImageConsumer ic )
{
if ( ic != null && ! isConsumer( ic ) )
consumers.addElement( ic );
}
/// This method determines if a given ImageConsumer object
// is currently registered with this ImageProducer as one
// of its consumers.
public boolean isConsumer( ImageConsumer ic )
{
return consumers.contains( ic );
}
/// This method removes the given ImageConsumer object
// from the list of consumers currently registered to
// receive image data. It is not considered an error
// to remove a consumer that is not currently registered.
// The ImageProducer should stop sending data to this
// consumer as soon as is feasible.
public void removeConsumer( ImageConsumer ic )
{
consumers.removeElement( ic );
}
/// This method both registers the given ImageConsumer object
// as a consumer and starts an immediate reconstruction of
// the image data which will then be delivered to this
// consumer and any other consumer which may have already
// been registered with the producer. This method differs
// from the addConsumer method in that a reproduction of
// the image data should be triggered as soon as possible.
// @see #addConsumer
public void startProduction( ImageConsumer ic )
{
addConsumer( ic );
if ( ! startedRead )
{
startedRead = true;
new ImageDecoderRead( this );
}
if ( ! producing )
{
producing = true;
sendImage();
}
}
/// This method is used by an ImageConsumer to request that
// the ImageProducer attempt to resend the image data one
// more time in TOPDOWNLEFTRIGHT order so that higher
// quality conversion algorithms which depend on receiving
// pixels in order can be used to produce a better output
// version of the image. The ImageProducer is free to
// ignore this call if it cannot resend the data in that
// order. If the data can be resent, then the ImageProducer
// should respond by executing the following minimum set of
// ImageConsumer method calls:
// <PRE>
// ic.setHints( TOPDOWNLEFTRIGHT | [otherhints] );
// ic.setPixels( [...] ); // as many times as needed
// ic.imageComplete( [status] );
// </PRE>
// @see ImageConsumer#setHints
public void requestTopDownLeftRightResend( ImageConsumer ic )
{
addConsumer( ic );
waitForSize();
sendHead( ic );
for ( int row = 0; row < height; ++row )
sendPixelRow( ic, row );
sendTail( ic );
}
}
class ImageDecoderRead extends Thread
{
private ImageDecoder parent;
public ImageDecoderRead( ImageDecoder parent )
{
this.parent = parent;
start();
}
// Methods from Runnable.
public void run()
{
parent.readImage();
}
}

View file

@ -1,267 +0,0 @@
// PpmDecoder - read in a PPM image
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.Decoders;
import java.io.*;
import java.awt.image.*;
/// Read in a PPM image.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Decoders/PpmDecoder.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see Acme.JPM.Encoders.PpmEncoder
public class PpmDecoder extends ImageDecoder
{
/// Constructor.
// @param in The stream to read the bytes from.
public PpmDecoder( InputStream in )
{
super( in );
}
private int type;
private static final int PBM_ASCII = 1;
private static final int PGM_ASCII = 2;
private static final int PPM_ASCII = 3;
private static final int PBM_RAW = 4;
private static final int PGM_RAW = 5;
private static final int PPM_RAW = 6;
private int width = -1, height = -1;
private int maxval;
/// Subclasses implement this to read in enough of the image stream
// to figure out the width and height.
void readHeader( InputStream in ) throws IOException
{
char c1, c2;
c1 = (char) readByte( in );
c2 = (char) readByte( in );
if ( c1 != 'P' )
throw new IOException( "not a PBM/PGM/PPM file" );
switch ( c2 )
{
case '1':
type = PBM_ASCII;
break;
case '2':
type = PGM_ASCII;
break;
case '3':
type = PPM_ASCII;
break;
case '4':
type = PBM_RAW;
break;
case '5':
type = PGM_RAW;
break;
case '6':
type = PPM_RAW;
break;
default:
throw new IOException( "not a standard PBM/PGM/PPM file" );
}
width = readInt( in );
height = readInt( in );
if ( type != PBM_ASCII && type != PBM_RAW )
maxval = readInt( in );
}
/// Subclasses implement this to return the width, or -1 if not known.
int getWidth()
{
return width;
}
/// Subclasses implement this to return the height, or -1 if not known.
int getHeight()
{
return height;
}
/// Subclasses implement this to read pixel data into the rgbRow
// array, an int[width]. One int per pixel, no offsets or padding,
// RGBdefault (AARRGGBB) color model
void readRow( InputStream in, int row, int[] rgbRow ) throws IOException
{
int col, r, g, b;
int rgb = 0;
char c;
for ( col = 0; col < width; ++col )
{
switch ( type )
{
case PBM_ASCII:
c = readChar( in );
if ( c == '1' )
rgb = 0xff000000;
else if ( c == '0' )
rgb = 0xffffffff;
else
throw new IOException( "illegal PBM bit" );
break;
case PGM_ASCII:
g = readInt( in );
rgb = makeRgb( g, g, g );
break;
case PPM_ASCII:
r = readInt( in );
g = readInt( in );
b = readInt( in );
rgb = makeRgb( r, g, b );
break;
case PBM_RAW:
if ( readBit( in ) )
rgb = 0xff000000;
else
rgb = 0xffffffff;
break;
case PGM_RAW:
g = readByte( in );
if ( maxval != 255 )
g = fixDepth( g );
rgb = makeRgb( g, g, g );
break;
case PPM_RAW:
r = readByte( in );
g = readByte( in );
b = readByte( in );
if ( maxval != 255 )
{
r = fixDepth( r );
g = fixDepth( g );
b = fixDepth( b );
}
rgb = makeRgb( r, g, b );
break;
}
rgbRow[col] = rgb;
}
}
/// Utility routine to read a byte. Instead of returning -1 on
// EOF, it throws an exception.
private static int readByte( InputStream in ) throws IOException
{
int b = in.read();
if ( b == -1 )
throw new EOFException();
return b;
}
private int bitshift = -1;
private int bits;
/// Utility routine to read a bit, packed eight to a byte, big-endian.
private boolean readBit( InputStream in ) throws IOException
{
if ( bitshift == -1 )
{
bits = readByte( in );
bitshift = 7;
}
boolean bit = ( ( ( bits >> bitshift ) & 1 ) != 0 );
--bitshift;
return bit;
}
/// Utility routine to read a character, ignoring comments.
private static char readChar( InputStream in ) throws IOException
{
char c;
c = (char) readByte( in );
if ( c == '#' )
{
do
{
c = (char) readByte( in );
}
while ( c != '\n' && c != '\r' );
}
return c;
}
/// Utility routine to read the first non-whitespace character.
private static char readNonwhiteChar( InputStream in ) throws IOException
{
char c;
do
{
c = readChar( in );
}
while ( c == ' ' || c == '\t' || c == '\n' || c == '\r' );
return c;
}
/// Utility routine to read an ASCII integer, ignoring comments.
private static int readInt( InputStream in ) throws IOException
{
char c;
int i;
c = readNonwhiteChar( in );
if ( c < '0' || c > '9' )
throw new IOException( "junk in file where integer should be" );
i = 0;
do
{
i = i * 10 + c - '0';
c = readChar( in );
}
while ( c >= '0' && c <= '9' );
return i;
}
/// Utility routine to rescale a pixel value from a non-eight-bit maxval.
private int fixDepth( int p )
{
return ( p * 255 + maxval / 2 ) / maxval;
}
/// Utility routine make an RGBdefault pixel from three color values.
private static int makeRgb( int r, int g, int b )
{
return 0xff000000 | ( r << 16 ) | ( g << 8 ) | b;
}
}

View file

@ -1,448 +0,0 @@
// JpegEncoder - write out an image as a JPEG
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.Encoders;
import java.util.*;
import java.io.*;
import java.awt.Image;
import java.awt.image.*;
/// Write out an image as a JPEG.
// DOESN'T WORK YET.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Encoders/JpegEncoder.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see ToJpeg
public class JpegEncoder extends ImageEncoder
{
/// Constructor.
// @param img The image to encode.
// @param out The stream to write the JPEG to.
public JpegEncoder( Image img, OutputStream out ) throws IOException
{
super( img, out );
}
/// Constructor.
// @param prod The ImageProducer to encode.
// @param out The stream to write the JPEG to.
public JpegEncoder( ImageProducer prod, OutputStream out ) throws IOException
{
super( prod, out );
}
int qfactor = 100;
/// Set the Q-factor.
public void setQfactor( int qfactor )
{
this.qfactor = qfactor;
}
int width, height;
int[][] rgbPixels;
void encodeStart( int width, int height ) throws IOException
{
this.width = width;
this.height = height;
rgbPixels = new int[height][width];
}
void encodePixels(
int x, int y, int w, int h, int[] rgbPixels, int off, int scansize )
throws IOException
{
// Save the pixels.
for ( int row = 0; row < h; ++row )
System.arraycopy(
rgbPixels, row * scansize + off,
this.rgbPixels[y + row], x, w );
}
void encodeDone() throws IOException
{
writeJfifHuffHeader();
// !!!
}
// Some of the following code is derived from the Berkeley Continuous
// Media Toolkit (http://bmrc.berkeley.edu/projects/cmt/), which is
// Copyright (c) 1996 The Regents of the University of California.
// All rights reserved.
//
// IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
// OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
// UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
// This array represents the default JFIF header for quality = 100 and
// size = 640x480, with Huffman tables. The values are adjusted when a
// file is generated.
private static byte[] jfifHuff100Header = {
// SOI
(byte) 0xFF, (byte) 0xD8,
// JFIF header
(byte) 0xFF, (byte) 0xE0, // Marker
(byte) 0x00, (byte) 0x10, // Length = 16 bytes
(byte) 0x4A, (byte) 0x46, (byte) 0x49, (byte) 0x46, // "JFIF"
(byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00,
(byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
// Start of frame (section B.2.2)
(byte) 0xFF, (byte) 0xC0, // Baseline DCT
(byte) 0x00, (byte) 0x11, // Length = 17 bytes
(byte) 0x08, // Sample precision
(byte) 0x01, (byte) 0xE0, // Height
(byte) 0x02, (byte) 0x80, // Width
(byte) 0x03, // Number of components = 3
// Scan 1: 2:1 horiz, (byte) 1:1 vertical, (byte) use QT 0
(byte) 0x01, (byte) 0x21, (byte) 0x00,
// Scan 2: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
(byte) 0x02, (byte) 0x11, (byte) 0x01,
// Scan 3: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
(byte) 0x03, (byte) 0x11, (byte) 0x01,
// Define Quant table (section B.2.4.1)
(byte) 0xFF, (byte) 0xDB, // Marker
(byte) 0x00, (byte) 0x84, // Length (both tables)
(byte) 0x00, // 8 bit values, (byte) table 0
(byte) 0x10, (byte) 0x0B, (byte) 0x0C, (byte) 0x0E, (byte) 0x0C,
(byte) 0x0A, (byte) 0x10, (byte) 0x0E, (byte) 0x0D, (byte) 0x0E,
(byte) 0x12, (byte) 0x11, (byte) 0x10, (byte) 0x13, (byte) 0x18,
(byte) 0x28, (byte) 0x1A, (byte) 0x18, (byte) 0x16, (byte) 0x16,
(byte) 0x18, (byte) 0x31, (byte) 0x23, (byte) 0x25, (byte) 0x1D,
(byte) 0x28, (byte) 0x3A, (byte) 0x33, (byte) 0x3D, (byte) 0x3C,
(byte) 0x39, (byte) 0x33, (byte) 0x38, (byte) 0x37, (byte) 0x40,
(byte) 0x48, (byte) 0x5C, (byte) 0x4E, (byte) 0x40, (byte) 0x44,
(byte) 0x57, (byte) 0x45, (byte) 0x37, (byte) 0x38, (byte) 0x50,
(byte) 0x6D, (byte) 0x51, (byte) 0x57, (byte) 0x5F, (byte) 0x62,
(byte) 0x67, (byte) 0x68, (byte) 0x67, (byte) 0x3E, (byte) 0x4D,
(byte) 0x71, (byte) 0x79, (byte) 0x70, (byte) 0x64, (byte) 0x78,
(byte) 0x5C, (byte) 0x65, (byte) 0x67, (byte) 0x63,
(byte) 0x01, // 8 bit values, (byte) table 1
(byte) 0x11, (byte) 0x12, (byte) 0x12, (byte) 0x18, (byte) 0x15,
(byte) 0x18, (byte) 0x2F, (byte) 0x1A, (byte) 0x1A, (byte) 0x2F,
(byte) 0x63, (byte) 0x42, (byte) 0x38, (byte) 0x42, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
// Define huffman table (section B.2.4.1)
(byte) 0xFF, (byte) 0xC4, // Marker
(byte) 0x00, (byte) 0x1F, // Length (31 bytes)
(byte) 0x00, // DC, (byte) table 0
(byte) 0x00, (byte) 0x01, (byte) 0x05, (byte) 0x01, (byte) 0x01,
(byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
(byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
(byte) 0x09, (byte) 0x0A, (byte) 0x0B,
// Define huffman table (section B.2.4.1)
(byte) 0xFF, (byte) 0xC4, // Marker
(byte) 0x00, (byte) 0xB5, // Length (181 bytes)
(byte) 0x10, // AC, (byte) table 0
(byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x03,
(byte) 0x02, (byte) 0x04, (byte) 0x03, (byte) 0x05, (byte) 0x05,
(byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x01,
(byte) 0x7D, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00,
(byte) 0x04, (byte) 0x11, (byte) 0x05, (byte) 0x12, (byte) 0x21,
(byte) 0x31, (byte) 0x41, (byte) 0x06, (byte) 0x13, (byte) 0x51,
(byte) 0x61, (byte) 0x07, (byte) 0x22, (byte) 0x71, (byte) 0x14,
(byte) 0x32, (byte) 0x81, (byte) 0x91, (byte) 0xA1, (byte) 0x08,
(byte) 0x23, (byte) 0x42, (byte) 0xB1, (byte) 0xC1, (byte) 0x15,
(byte) 0x52, (byte) 0xD1, (byte) 0xF0, (byte) 0x24, (byte) 0x33,
(byte) 0x62, (byte) 0x72, (byte) 0x82, (byte) 0x09, (byte) 0x0A,
(byte) 0x16, (byte) 0x17, (byte) 0x18, (byte) 0x19, (byte) 0x1A,
(byte) 0x25, (byte) 0x26, (byte) 0x27, (byte) 0x28, (byte) 0x29,
(byte) 0x2A, (byte) 0x34, (byte) 0x35, (byte) 0x36, (byte) 0x37,
(byte) 0x38, (byte) 0x39, (byte) 0x3A, (byte) 0x43, (byte) 0x44,
(byte) 0x45, (byte) 0x46, (byte) 0x47, (byte) 0x48, (byte) 0x49,
(byte) 0x4A, (byte) 0x53, (byte) 0x54, (byte) 0x55, (byte) 0x56,
(byte) 0x57, (byte) 0x58, (byte) 0x59, (byte) 0x5A, (byte) 0x63,
(byte) 0x64, (byte) 0x65, (byte) 0x66, (byte) 0x67, (byte) 0x68,
(byte) 0x69, (byte) 0x6A, (byte) 0x73, (byte) 0x74, (byte) 0x75,
(byte) 0x76, (byte) 0x77, (byte) 0x78, (byte) 0x79, (byte) 0x7A,
(byte) 0x83, (byte) 0x84, (byte) 0x85, (byte) 0x86, (byte) 0x87,
(byte) 0x88, (byte) 0x89, (byte) 0x8A, (byte) 0x92, (byte) 0x93,
(byte) 0x94, (byte) 0x95, (byte) 0x96, (byte) 0x97, (byte) 0x98,
(byte) 0x99, (byte) 0x9A, (byte) 0xA2, (byte) 0xA3, (byte) 0xA4,
(byte) 0xA5, (byte) 0xA6, (byte) 0xA7, (byte) 0xA8, (byte) 0xA9,
(byte) 0xAA, (byte) 0xB2, (byte) 0xB3, (byte) 0xB4, (byte) 0xB5,
(byte) 0xB6, (byte) 0xB7, (byte) 0xB8, (byte) 0xB9, (byte) 0xBA,
(byte) 0xC2, (byte) 0xC3, (byte) 0xC4, (byte) 0xC5, (byte) 0xC6,
(byte) 0xC7, (byte) 0xC8, (byte) 0xC9, (byte) 0xCA, (byte) 0xD2,
(byte) 0xD3, (byte) 0xD4, (byte) 0xD5, (byte) 0xD6, (byte) 0xD7,
(byte) 0xD8, (byte) 0xD9, (byte) 0xDA, (byte) 0xE1, (byte) 0xE2,
(byte) 0xE3, (byte) 0xE4, (byte) 0xE5, (byte) 0xE6, (byte) 0xE7,
(byte) 0xE8, (byte) 0xE9, (byte) 0xEA, (byte) 0xF1, (byte) 0xF2,
(byte) 0xF3, (byte) 0xF4, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7,
(byte) 0xF8, (byte) 0xF9, (byte) 0xFA,
// Define huffman table (section B.2.4.1)
(byte) 0xFF, (byte) 0xC4, // Marker
(byte) 0x00, (byte) 0x1F, // Length (31 bytes)
(byte) 0x01, // DC, (byte) table 1
(byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x01,
(byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
(byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
(byte) 0x09, (byte) 0x0A, (byte) 0x0B,
// Define huffman table (section B.2.4.1)
(byte) 0xFF, (byte) 0xC4, // Marker
(byte) 0x00, (byte) 0xB5, // Length (181 bytes)
(byte) 0x11, // AC, (byte) table 1
(byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x04,
(byte) 0x04, (byte) 0x03, (byte) 0x04, (byte) 0x07, (byte) 0x05,
(byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x02,
(byte) 0x77, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
(byte) 0x11, (byte) 0x04, (byte) 0x05, (byte) 0x21, (byte) 0x31,
(byte) 0x06, (byte) 0x12, (byte) 0x41, (byte) 0x51, (byte) 0x07,
(byte) 0x61, (byte) 0x71, (byte) 0x13, (byte) 0x22, (byte) 0x32,
(byte) 0x81, (byte) 0x08, (byte) 0x14, (byte) 0x42, (byte) 0x91,
(byte) 0xA1, (byte) 0xB1, (byte) 0xC1, (byte) 0x09, (byte) 0x23,
(byte) 0x33, (byte) 0x52, (byte) 0xF0, (byte) 0x15, (byte) 0x62,
(byte) 0x72, (byte) 0xD1, (byte) 0x0A, (byte) 0x16, (byte) 0x24,
(byte) 0x34, (byte) 0xE1, (byte) 0x25, (byte) 0xF1, (byte) 0x17,
(byte) 0x18, (byte) 0x19, (byte) 0x1A, (byte) 0x26, (byte) 0x27,
(byte) 0x28, (byte) 0x29, (byte) 0x2A, (byte) 0x35, (byte) 0x36,
(byte) 0x37, (byte) 0x38, (byte) 0x39, (byte) 0x3A, (byte) 0x43,
(byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47, (byte) 0x48,
(byte) 0x49, (byte) 0x4A, (byte) 0x53, (byte) 0x54, (byte) 0x55,
(byte) 0x56, (byte) 0x57, (byte) 0x58, (byte) 0x59, (byte) 0x5A,
(byte) 0x63, (byte) 0x64, (byte) 0x65, (byte) 0x66, (byte) 0x67,
(byte) 0x68, (byte) 0x69, (byte) 0x6A, (byte) 0x73, (byte) 0x74,
(byte) 0x75, (byte) 0x76, (byte) 0x77, (byte) 0x78, (byte) 0x79,
(byte) 0x7A, (byte) 0x82, (byte) 0x83, (byte) 0x84, (byte) 0x85,
(byte) 0x86, (byte) 0x87, (byte) 0x88, (byte) 0x89, (byte) 0x8A,
(byte) 0x92, (byte) 0x93, (byte) 0x94, (byte) 0x95, (byte) 0x96,
(byte) 0x97, (byte) 0x98, (byte) 0x99, (byte) 0x9A, (byte) 0xA2,
(byte) 0xA3, (byte) 0xA4, (byte) 0xA5, (byte) 0xA6, (byte) 0xA7,
(byte) 0xA8, (byte) 0xA9, (byte) 0xAA, (byte) 0xB2, (byte) 0xB3,
(byte) 0xB4, (byte) 0xB5, (byte) 0xB6, (byte) 0xB7, (byte) 0xB8,
(byte) 0xB9, (byte) 0xBA, (byte) 0xC2, (byte) 0xC3, (byte) 0xC4,
(byte) 0xC5, (byte) 0xC6, (byte) 0xC7, (byte) 0xC8, (byte) 0xC9,
(byte) 0xCA, (byte) 0xD2, (byte) 0xD3, (byte) 0xD4, (byte) 0xD5,
(byte) 0xD6, (byte) 0xD7, (byte) 0xD8, (byte) 0xD9, (byte) 0xDA,
(byte) 0xE2, (byte) 0xE3, (byte) 0xE4, (byte) 0xE5, (byte) 0xE6,
(byte) 0xE7, (byte) 0xE8, (byte) 0xE9, (byte) 0xEA, (byte) 0xF2,
(byte) 0xF3, (byte) 0xF4, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7,
(byte) 0xF8, (byte) 0xF9, (byte) 0xFA,
// Start of Scan (section B.2.3)
(byte) 0xFF, (byte) 0xDA, // Marker
(byte) 0x00, (byte) 0x0C, // Length of header
(byte) 0x03, // Number of image components
// Scan 1: use DC/AC huff tables 0/0
(byte) 0x01, (byte) 0x00,
// Scan 2: use DC/AC huff tables 1/1
(byte) 0x02, (byte) 0x11,
// Scan 3: use DC/AC huff tables 1/1
(byte) 0x03, (byte) 0x11,
(byte) 0x00, (byte) 0x3F, (byte) 0x00 // Not used
};
// This array represents the default JFIF header for quality = 100 and
// size = 640x480, without Huffman tables. The values are adjusted when a
// file is generated.
private static byte[] jfifNoHuff100Header = {
// SOI
(byte) 0xFF, (byte) 0xD8,
// JFIF header
(byte) 0xFF, (byte) 0xE0, // Marker
(byte) 0x00, (byte) 0x10, // Length = 16 bytes
(byte) 0x4A, (byte) 0x46, (byte) 0x49, (byte) 0x46, // "JFIF"
(byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00,
(byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
// Start of frame (section B.2.2)
(byte) 0xFF, (byte) 0xC0, // Baseline DCT
(byte) 0x00, (byte) 0x11, // Length = 17 bytes
(byte) 0x08, // Sample precision
(byte) 0x01, (byte) 0xE0, // Height
(byte) 0x02, (byte) 0x80, // Width
(byte) 0x03, // Number of components = 3
// Scan 1: 2:1 horiz, (byte) 1:1 vertical, (byte) use QT 0
(byte) 0x01, (byte) 0x21, (byte) 0x00,
// Scan 2: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
(byte) 0x02, (byte) 0x11, (byte) 0x01,
// Scan 3: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
(byte) 0x03, (byte) 0x11, (byte) 0x01,
// Define Quant table (section B.2.4.1)
(byte) 0xFF, (byte) 0xDB, // Marker
(byte) 0x00, (byte) 0x84, // Length (both tables)
(byte) 0x00, // 8 bit values, (byte) table 0
(byte) 0x10, (byte) 0x0B, (byte) 0x0C, (byte) 0x0E, (byte) 0x0C,
(byte) 0x0A, (byte) 0x10, (byte) 0x0E, (byte) 0x0D, (byte) 0x0E,
(byte) 0x12, (byte) 0x11, (byte) 0x10, (byte) 0x13, (byte) 0x18,
(byte) 0x28, (byte) 0x1A, (byte) 0x18, (byte) 0x16, (byte) 0x16,
(byte) 0x18, (byte) 0x31, (byte) 0x23, (byte) 0x25, (byte) 0x1D,
(byte) 0x28, (byte) 0x3A, (byte) 0x33, (byte) 0x3D, (byte) 0x3C,
(byte) 0x39, (byte) 0x33, (byte) 0x38, (byte) 0x37, (byte) 0x40,
(byte) 0x48, (byte) 0x5C, (byte) 0x4E, (byte) 0x40, (byte) 0x44,
(byte) 0x57, (byte) 0x45, (byte) 0x37, (byte) 0x38, (byte) 0x50,
(byte) 0x6D, (byte) 0x51, (byte) 0x57, (byte) 0x5F, (byte) 0x62,
(byte) 0x67, (byte) 0x68, (byte) 0x67, (byte) 0x3E, (byte) 0x4D,
(byte) 0x71, (byte) 0x79, (byte) 0x70, (byte) 0x64, (byte) 0x78,
(byte) 0x5C, (byte) 0x65, (byte) 0x67, (byte) 0x63,
(byte) 0x01, // 8 bit values, (byte) table 1
(byte) 0x11, (byte) 0x12, (byte) 0x12, (byte) 0x18, (byte) 0x15,
(byte) 0x18, (byte) 0x2F, (byte) 0x1A, (byte) 0x1A, (byte) 0x2F,
(byte) 0x63, (byte) 0x42, (byte) 0x38, (byte) 0x42, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
// Start of Scan (section B.2.3)
(byte) 0xFF, (byte) 0xDA, // Marker
(byte) 0x00, (byte) 0x0C, // Length of header
(byte) 0x03, // Number of image components
// Scan 1: use DC/AC huff tables 0/0
(byte) 0x01, (byte) 0x00,
// Scan 2: use DC/AC huff tables 1/1
(byte) 0x02, (byte) 0x11,
// Scan 3: use DC/AC huff tables 1/1
(byte) 0x03, (byte) 0x11,
(byte) 0x00, (byte) 0x3F, (byte) 0x00 // Not used
};
private void writeJfifHuffHeader() throws IOException
{
byte[] newHeader = new byte[jfifHuff100Header.length];
System.arraycopy(
jfifHuff100Header, 0, newHeader, 0, jfifHuff100Header.length );
// Set image width in JFIF header.
newHeader[27] = (byte) ( ( width >>> 8 ) & 0xff );
newHeader[28] = (byte) ( width & 0xff );
// Set image height in JFIF header.
newHeader[25] = (byte) ( ( height >>> 8 ) & 0xff );
newHeader[26] = (byte) ( height & 0xff );
// Adjust the quality factor.
//
// The default quality factor is 100, therefore if
// our quality factor does not equal 100 we must
// scale the quantization matrices in the JFIF header.
// Note that values are clipped to a max of 255.
if ( qfactor != 100 )
{
for ( int i = 44; i < 108; ++i )
{
int t = ( newHeader[i] * qfactor ) / 100;
newHeader[i] = (byte) Math.max( t, 0xff );
}
for ( int i = 109; i < 173; ++i )
{
int t = ( newHeader[i] * qfactor ) / 100;
newHeader[i] = (byte) Math.max( t, 0xff );
}
}
// Write out buffer.
out.write( newHeader );
}
private void writeJfifNoHuffHeader() throws IOException
{
byte[] newHeader = new byte[jfifNoHuff100Header.length];
System.arraycopy(
jfifNoHuff100Header, 0, newHeader, 0, jfifNoHuff100Header.length );
// Set image width in JFIF header.
newHeader[27] = (byte) ( ( width >>> 8 ) & 0xff );
newHeader[28] = (byte) ( width & 0xff );
// Set image height in JFIF header.
newHeader[25] = (byte) ( ( height >>> 8 ) & 0xff );
newHeader[26] = (byte) ( height & 0xff );
// Adjust the quality factor.
//
// The default quality factor is 100, therefore if
// our quality factor does not equal 100 we must
// scale the quantization matrices in the JFIF header.
// Note that values are clipped to a max of 255.
if ( qfactor != 100 )
{
for ( int i = 44; i < 108; ++i )
{
int t = ( newHeader[i] * qfactor ) / 100;
newHeader[i] = (byte) Math.max( t, 0xff );
}
for ( int i = 109; i < 173; ++i )
{
int t = ( newHeader[i] * qfactor ) / 100;
newHeader[i] = (byte) Math.max( t, 0xff );
}
}
// Write out buffer.
out.write( newHeader );
}
}

View file

@ -1,103 +0,0 @@
// PpmEncoder - write out an image as a PPM
//
// Copyright (C)1996,1998 by Jef Poskanzer <jef@acme.com>. 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.Encoders;
import java.util.*;
import java.io.*;
import java.awt.Image;
import java.awt.image.*;
/// Write out an image as a PPM.
// <P>
// Writes an image onto a specified OutputStream in the PPM file format.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Encoders/PpmEncoder.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see ToPpm
public class PpmEncoder extends ImageEncoder
{
/// Constructor.
// @param img The image to encode.
// @param out The stream to write the PPM to.
public PpmEncoder( Image img, OutputStream out ) throws IOException
{
super( img, out );
}
/// Constructor.
// @param prod The ImageProducer to encode.
// @param out The stream to write the PPM to.
public PpmEncoder( ImageProducer prod, OutputStream out ) throws IOException
{
super( prod, out );
}
void encodeStart( int width, int height ) throws IOException
{
writeString( out, "P6\n" );
writeString( out, width + " " + height + "\n" );
writeString( out, "255\n" );
}
static void writeString( OutputStream out, String str ) throws IOException
{
byte[] buf = str.getBytes();
out.write( buf );
}
void encodePixels(
int x, int y, int w, int h, int[] rgbPixels, int off, int scansize )
throws IOException
{
byte[] ppmPixels = new byte[w * 3];
for ( int row = 0; row < h; ++row )
{
int rowOff = off + row * scansize;
for ( int col = 0; col < w; ++col )
{
int i = rowOff + col;
int j = col * 3;
ppmPixels[j ] = (byte) ( ( rgbPixels[i] & 0xff0000 ) >> 16 );
ppmPixels[j + 1] = (byte) ( ( rgbPixels[i] & 0x00ff00 ) >> 8 );
ppmPixels[j + 2] = (byte) ( rgbPixels[i] & 0x0000ff );
}
out.write( ppmPixels );
}
}
void encodeDone() throws IOException
{
// Nothing.
}
}

View file

@ -1,106 +0,0 @@
// CompositeFilter - compose two filters into one
//
// Copyright (C) 1997 by Jef Poskanzer <jef@acme.com>. 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.util.*;
/// Compose two filters into one.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/CompositeFilter.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class CompositeFilter extends ImageFilterPlus
{
private ImageFilterPlus filterOne, filterTwo;
private ImageFilter instanceOne, instanceTwo;
/// Constructor. Builds a filter chain with a FilteredImageSource as
// the glue.
public CompositeFilter( ImageProducer producer, ImageFilterPlus filterOne, ImageFilterPlus filterTwo )
{
super( producer );
this.filterOne = filterOne;
this.filterTwo = filterTwo;
filterOne.setSource( producer );
ImageProducer producerOne =
new FilteredImageSource( producer, filterOne );
filterTwo.setSource( producerOne );
}
public ImageFilter getFilterInstance( ImageConsumer consumer )
{
CompositeFilter instance = (CompositeFilter) clone();
instance.instanceTwo = filterTwo.getFilterInstance( consumer );
instance.instanceOne = filterOne.getFilterInstance( instanceTwo );
return (ImageFilter) instance;
}
// The rest of the methods just delegate to instanceOne.
public void setColorModel( ColorModel model )
{
instanceOne.setColorModel( model );
}
public void setDimensions( int width, int height )
{
instanceOne.setDimensions( width, height );
}
public void setHints( int hintflags )
{
instanceOne.setHints( hintflags );
}
public void setProperties( Hashtable props )
{
instanceOne.setProperties( props );
}
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
{
instanceOne.setPixels( x, y, w, h, model, pixels, off, scansize );
}
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
{
instanceOne.setPixels( x, y, w, h, model, pixels, off, scansize );
}
public void imageComplete( int status )
{
//super.imageComplete( status );
instanceOne.imageComplete( status );
}
}

View file

@ -1,169 +0,0 @@
// EdgeDetect - edge-detection filter
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.io.*;
import java.awt.image.*;
import Acme.JPM.Decoders.*;
import Acme.JPM.Encoders.*;
/// Edge-detection filter.
// <IMG ALIGN=RIGHT WIDTH=202 HEIGHT=200 SRC="Earth-EdgeDetect.jpg">
// <IMG ALIGN=RIGHT WIDTH=202 HEIGHT=200 SRC="Earth.jpg">
// <P>
// Outlines the edges of an image.
// The edge detection technique used is to take the Pythagorean sum of
// two Sobel gradient operators at 90 degrees to each other, separately
// for each color component.
// For more details see "Digital Image Processing" by Gonzalez and Wintz,
// chapter 7.
// <P>
// This filter is slow.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/EdgeDetect.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class EdgeDetect extends RGBAllFilter
{
// Constructor.
public EdgeDetect( ImageProducer producer )
{
super( producer );
}
private static final double SCALE = 1.8D;
public void filterRGBAll( int width, int height, int[][] rgbPixels )
{
int[][] newPixels = new int[height][width];
long sum1, sum2;
double sum;
int r, g, b;
// First and last rows are black.
for ( int col = 0; col < width; ++col )
{
newPixels[0][col] = 0xff000000;
newPixels[height - 1][col] = 0xff000000;
}
for ( int row = 1; row < height - 1; ++row )
{
// First and last columns are black too.
newPixels[row][0] = 0xff000000;
newPixels[row][width - 1] = 0xff000000;
// The real pixels.
for ( int col = 1; col < width - 1; ++col )
{
sum1 =
rgbModel.getRed( rgbPixels[row - 1][col + 1] ) -
rgbModel.getRed( rgbPixels[row - 1][col - 1] ) +
2 * (
rgbModel.getRed( rgbPixels[row][col + 1] ) -
rgbModel.getRed( rgbPixels[row][col - 1] ) ) +
rgbModel.getRed( rgbPixels[row + 1][col + 1] ) -
rgbModel.getRed( rgbPixels[row + 1][col - 1] );
sum2 = (
rgbModel.getRed( rgbPixels[row + 1][col - 1] ) +
2 * rgbModel.getRed( rgbPixels[row + 1][col] ) +
rgbModel.getRed( rgbPixels[row + 1][col + 1] )
) - (
rgbModel.getRed( rgbPixels[row - 1][col - 1] ) +
2 * rgbModel.getRed( rgbPixels[row - 1][col] ) +
rgbModel.getRed( rgbPixels[row - 1][col + 1] )
);
sum = Math.sqrt( (double) ( sum1*sum1 + sum2*sum2 ) ) / SCALE;
r = Math.min( (int) sum, 255 );
sum1 =
rgbModel.getGreen( rgbPixels[row - 1][col + 1] ) -
rgbModel.getGreen( rgbPixels[row - 1][col - 1] ) +
2 * (
rgbModel.getGreen( rgbPixels[row][col + 1] ) -
rgbModel.getGreen( rgbPixels[row][col - 1] ) ) +
rgbModel.getGreen( rgbPixels[row + 1][col + 1] ) -
rgbModel.getGreen( rgbPixels[row + 1][col - 1] );
sum2 = (
rgbModel.getGreen( rgbPixels[row + 1][col - 1] ) +
2 * rgbModel.getGreen( rgbPixels[row + 1][col] ) +
rgbModel.getGreen( rgbPixels[row + 1][col + 1] )
) - (
rgbModel.getGreen( rgbPixels[row - 1][col - 1] ) +
2 * rgbModel.getGreen( rgbPixels[row - 1][col] ) +
rgbModel.getGreen( rgbPixels[row - 1][col + 1] )
);
sum = Math.sqrt( (double) ( sum1*sum1 + sum2*sum2 ) ) / SCALE;
g = Math.min( (int) sum, 255 );
sum1 =
rgbModel.getBlue( rgbPixels[row - 1][col + 1] ) -
rgbModel.getBlue( rgbPixels[row - 1][col - 1] ) +
2 * (
rgbModel.getBlue( rgbPixels[row][col + 1] ) -
rgbModel.getBlue( rgbPixels[row][col - 1] ) ) +
rgbModel.getBlue( rgbPixels[row + 1][col + 1] ) -
rgbModel.getBlue( rgbPixels[row + 1][col - 1] );
sum2 = (
rgbModel.getBlue( rgbPixels[row + 1][col - 1] ) +
2 * rgbModel.getBlue( rgbPixels[row + 1][col] ) +
rgbModel.getBlue( rgbPixels[row + 1][col + 1] )
) - (
rgbModel.getBlue( rgbPixels[row - 1][col - 1] ) +
2 * rgbModel.getBlue( rgbPixels[row - 1][col] ) +
rgbModel.getBlue( rgbPixels[row - 1][col + 1] )
);
sum = Math.sqrt( (double) ( sum1*sum1 + sum2*sum2 ) ) / SCALE;
b = Math.min( (int) sum, 255 );
newPixels[row][col] =
0xff000000 | ( r << 16 ) | ( g << 8 ) | b;
}
}
setPixels( width, height, newPixels );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
if ( args.length != 0 )
usage();
ImageFilterPlus filter = new EdgeDetect( null );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: EdgeDetect" );
System.exit( 1 );
}
}

View file

@ -1,140 +0,0 @@
// Enlarge - an ImageFilter that enlarges by pixel replication
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.*;
/// An ImageFilter that enlarges by pixel replication.
// <P>
// Enlarges an image an integral factor by replicating pixels.
// The output uses the same color model as the input.
// This filter is very fast.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Enlarge.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see Shrink
// @see ScaleCopy
public class Enlarge extends ImageFilterPlus
{
private int multiplier;
private int newWidth, newHeight;
/// Constructor.
public Enlarge( ImageProducer producer, int multiplier )
{
super( producer );
this.multiplier = multiplier;
}
public void setDimensions( int width, int height )
{
newWidth = width * multiplier;
newHeight = height * multiplier;
consumer.setDimensions( newWidth, newHeight );
}
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
{
int newX = Math.min( x * multiplier, newWidth - 1 );
int newY = Math.min( y * multiplier, newHeight - 1 );
int newW = w * multiplier;
if ( newX + newW > newWidth )
newW = newWidth - newX;
int newH = h * multiplier;
if ( newY + newH > newHeight )
newH = newHeight - newY;
byte[] newPixels = new byte[newW * newH];
for ( int row = 0; row < h; ++row )
{
for ( int col = 0; col < w; ++col )
{
byte pixel = pixels[row * scansize + off + col];
for ( int i = 0; i < multiplier; ++i )
for ( int j = 0; j < multiplier; ++j )
{
int newRow = row * multiplier + i;
int newCol = col * multiplier + j;
newPixels[newRow * newW + newCol] = pixel;
}
}
}
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
}
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
{
int newX = Math.min( x * multiplier, newWidth - 1 );
int newY = Math.min( y * multiplier, newHeight - 1 );
int newW = w * multiplier;
if ( newX + newW > newWidth )
newW = newWidth - newX;
int newH = h * multiplier;
if ( newY + newH > newHeight )
newH = newHeight - newY;
int[] newPixels = new int[newW * newH];
for ( int row = 0; row < h; ++row )
{
for ( int col = 0; col < w; ++col )
{
int pixel = pixels[row * scansize + off + col];
for ( int i = 0; i < multiplier; ++i )
for ( int j = 0; j < multiplier; ++j )
{
int newRow = row * multiplier + i;
int newCol = col * multiplier + j;
newPixels[newRow * newW + newCol] = pixel;
}
}
}
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
if ( args.length != 1 )
usage();
ImageFilterPlus filter =
new Enlarge( null, Integer.parseInt( args[0] ) );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Enlarge <multiplier>" );
System.exit( 1 );
}
}

View file

@ -1,295 +0,0 @@
// Flip - an ImageFilter that flips or rotates the image
//
// Copyright (C) 1997 by Jef Poskanzer <jef@acme.com>. 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.*;
/// An ImageFilter that flips or rotates the image.
// <P>
// Flips the image left-right, top-bottom, rotates clockwise or
// counter-clockwise, or otherwise munges the image as specified.
// This filter is fast.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Flip.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class Flip extends ImageFilterPlus
{
/// The null transformation.
public static final int FLIP_NULL = 0;
/// Flip left to right.
public static final int FLIP_LR = 1;
/// Flip top to bottom.
public static final int FLIP_TB = 2;
/// Transpose X and Y - reflection along a diagonal.
public static final int FLIP_XY = 3;
/// Rotate clockwise 90 degrees.
public static final int FLIP_CW = 4;
/// Rotate counter-clockwise 90 degrees.
public static final int FLIP_CCW = 5;
/// Rotate 180 degrees.
public static final int FLIP_R180 = 6;
private int flipType;
private int width, height;
private int newWidth, newHeight;
/// Constructor.
public Flip( ImageProducer producer, int flipType )
{
super( producer, true );
this.flipType = flipType;
}
public void setDimensions( int width, int height )
{
this.width = width;
this.height = height;
switch ( flipType )
{
case FLIP_NULL:
case FLIP_LR:
case FLIP_TB:
case FLIP_R180:
newWidth = width;
newHeight = height;
break;
case FLIP_XY:
case FLIP_CW:
case FLIP_CCW:
newWidth = height;
newHeight = width;
break;
}
consumer.setDimensions( newWidth, newHeight );
}
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
{
int newX = x;
int newY = y;
int newW = w;
int newH = h;
switch ( flipType )
{
case FLIP_NULL:
break;
case FLIP_LR:
newX = width - ( x + w );
break;
case FLIP_TB:
newY = height - ( y + h );
break;
case FLIP_XY:
newW = h;
newH = w;
newX = y;
newY = x;
break;
case FLIP_CW:
newW = h;
newH = w;
newX = height - ( y + h );
newY = x;
break;
case FLIP_CCW:
newW = h;
newH = w;
newX = y;
newY = width - ( x + w );
break;
case FLIP_R180:
newX = width - ( x + w );
newY = height - ( y + h );
break;
}
byte[] newPixels = new byte[newW * newH];
for ( int row = 0; row < h; ++row )
{
for ( int col = 0; col < w; ++col )
{
int index = row * scansize + off + col;
int newRow = row;
int newCol = col;
switch ( flipType )
{
case FLIP_NULL:
break;
case FLIP_LR:
newCol = w - col - 1;
break;
case FLIP_TB:
newRow = h - row - 1;
break;
case FLIP_XY:
newRow = col;
newCol = row;
break;
case FLIP_CW:
newRow = col;
newCol = h - row - 1;;
break;
case FLIP_CCW:
newRow = w - col - 1;
newCol = row;
break;
case FLIP_R180:
newRow = h - row - 1;
newCol = w - col - 1;
break;
}
int newIndex = newRow * newW + newCol;
newPixels[newIndex] = pixels[index];
}
}
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
}
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
{
int newX = x;
int newY = y;
int newW = w;
int newH = h;
switch ( flipType )
{
case FLIP_NULL:
break;
case FLIP_LR:
newX = width - ( x + w );
break;
case FLIP_TB:
newY = height - ( y + h );
break;
case FLIP_XY:
newW = h;
newH = w;
newX = y;
newY = x;
break;
case FLIP_CW:
newW = h;
newH = w;
newX = height - ( y + h );
newY = x;
break;
case FLIP_CCW:
newW = h;
newH = w;
newX = y;
newY = width - ( x + w );
break;
case FLIP_R180:
newX = width - ( x + w );
newY = height - ( y + h );
break;
}
int[] newPixels = new int[newW * newH];
for ( int row = 0; row < h; ++row )
{
for ( int col = 0; col < w; ++col )
{
int index = row * scansize + off + col;
int newRow = row;
int newCol = col;
switch ( flipType )
{
case FLIP_NULL:
break;
case FLIP_LR:
newCol = w - col - 1;
break;
case FLIP_TB:
newRow = h - row - 1;
break;
case FLIP_XY:
newRow = col;
newCol = row;
break;
case FLIP_CW:
newRow = col;
newCol = h - row - 1;;
break;
case FLIP_CCW:
newRow = w - col - 1;
newCol = row;
break;
case FLIP_R180:
newRow = h - row - 1;
newCol = w - col - 1;
break;
}
int newIndex = newRow * newW + newCol;
newPixels[newIndex] = pixels[index];
}
}
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
if ( args.length != 1 )
usage();
int flipType = FLIP_NULL;
if ( args[0].equalsIgnoreCase( "-lr" ) )
flipType = FLIP_LR;
else if ( args[0].equalsIgnoreCase( "-tb" ) )
flipType = FLIP_TB;
else if ( args[0].equalsIgnoreCase( "-xy" ) )
flipType = FLIP_XY;
else if ( args[0].equalsIgnoreCase( "-cw" ) )
flipType = FLIP_CW;
else if ( args[0].equalsIgnoreCase( "-ccw" ) )
flipType = FLIP_CCW;
else if ( args[0].equalsIgnoreCase( "-r180" ) )
flipType = FLIP_R180;
else
usage();
ImageFilterPlus filter = new Flip( null, flipType );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Flip -lr|-tb|-xy|-cw|-ccw|-r180" );
System.exit( 1 );
}
}

View file

@ -1,148 +0,0 @@
// Gamma - gamma-correction filter
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.*;
/// Gamma-correction filter.
// <P>
// Gamma correction fixes a form of color distortion common to many monitors.
// Values less than 1.0 darken the image, and greater than 1.0 lighten it.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Gamma.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class Gamma extends RGBBlockFilter
{
private double rValue, gValue, bValue;
/// Constructor, single exponent.
public Gamma( ImageProducer producer, double value )
{
this( producer, value, value, value );
}
/// Constructor, different exponents for R G and B.
public Gamma( ImageProducer producer, double rValue, double gValue, double bValue )
{
super( producer );
this.rValue = rValue;
this.gValue = gValue;
this.bValue = bValue;
}
private int[] rTable, gTable, bTable;
public int[][] filterRGBBlock( int x, int y, int width, int height, int[][] rgbPixels )
{
initialize();
for ( int row = 0; row < height; ++row )
for ( int col = 0; col < width; ++col )
{
int rgb = rgbPixels[row][col];
int a = ( rgb >> 24 ) & 0xff;
int r = ( rgb >> 16 ) & 0xff;
int g = ( rgb >> 8 ) & 0xff;
int b = rgb & 0xff;
r = rTable[r];
g = gTable[g];
b = bTable[b];
rgbPixels[row][col] =
( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
}
return rgbPixels;
}
private boolean initialized = false;
private void initialize()
{
if ( initialized )
return;
initialized = true;
rTable = buildTable( rValue );
if ( gValue == rValue )
gTable = rTable;
else
gTable = buildTable( gValue );
if ( bValue == rValue )
bTable = rTable;
else if ( bValue == gValue )
bTable = gTable;
else
bTable = buildTable( bValue );
}
private int[] buildTable( double gamma )
{
int[] table = new int[256];
double oneOverGamma = 1.0D / gamma;
for ( int i = 0; i < 256; ++i )
{
int v = (int) (
( 255.0D * Math.pow( i / 255.0D, oneOverGamma ) ) + 0.5D );
if ( v > 255 )
v = 255;
table[i] = v;
}
return table;
}
// Main routine for command-line interface.
public static void main( String[] args )
{
ImageFilterPlus filter = null;
if ( args.length == 1 )
filter = new Gamma( null, Double.valueOf( args[0] ).doubleValue() );
else if ( args.length == 3 )
filter = new Gamma( null,
Double.valueOf( args[0] ).doubleValue(),
Double.valueOf( args[1] ).doubleValue(),
Double.valueOf( args[2] ).doubleValue() );
else
usage();
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Gamma <value>" );
System.err.println( "or: Gamma <rValue> <gValue> <bValue>" );
System.exit( 1 );
}
}

View file

@ -1,160 +0,0 @@
// ImageFilterPlus - an ImageFilter with some extra features and bug fixes
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.
// <P>
// You can use an image filter to turn one Image into another via
// a FilteredImageSource, e.g.:
// <BLOCKQUOTE><CODE><PRE>
// Image newImage = comp.createImage( new FilteredImageSource(
// oldImage.getSource(), new SomeFilter( oldImage.getSource() ) ) );
// </PRE></CODE></BLOCKQUOTE>
// Or use the convenient utility JPMUtils.filterImage():
// <BLOCKQUOTE><CODE><PRE>
// Image newImage = JPMUtils.filterImage(
// comp, SomeFilter( oldImage.getSource() ) );
// </PRE></CODE></BLOCKQUOTE>
// <P>
// 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:
// <BLOCKQUOTE><CODE><PRE>
// System.exit(
// ImageFilterPlus.filterStream(
// System.in, System.out,
// new SomeFilter( null ) ) );
// </PRE></CODE></BLOCKQUOTE>
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/ImageFilterPlus.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
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.
// <P>
// 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;
}
}

View file

@ -1,83 +0,0 @@
// Invert - color-inversion filter
//
// Copyright (C) 1997 by Jef Poskanzer <jef@acme.com>. 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.*;
/// Color-inversion filter.
// <P>
// Switches black for white, and all the other colors too.
// This filter is very fast.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Invert.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class Invert extends RGBBlockFilter
{
/// Constructor.
public Invert( ImageProducer producer )
{
super( producer );
}
public int[][] filterRGBBlock( int x, int y, int width, int height, int[][] rgbPixels )
{
for ( int row = 0; row < height; ++row )
for ( int col = 0; col < width; ++col )
{
int rgb = rgbPixels[row][col];
int alpha = rgb & 0xff000000;
int rest = ( ~ rgb ) & 0x00ffffff;
rgbPixels[row][col] = alpha | rest;
}
return rgbPixels;
}
// Main routine for command-line interface.
public static void main( String[] args )
{
ImageFilterPlus filter = null;
if ( args.length == 0 )
filter = new Invert( null );
else
usage();
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Invert" );
System.exit( 1 );
}
}

View file

@ -1,133 +0,0 @@
// Margin - an ImageFilter that adds a margin to an image
//
// Copyright (C) 1997 by Jef Poskanzer <jef@acme.com>. 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.*;
import java.awt.image.*;
/// An ImageFilter that adds a margin to an image.
// <P>
// Adds a margin of a specified color and width around an image.
// The output uses the same color model as the input.
// This filter is very fast.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Margin.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class Margin extends ImageFilterPlus
{
private Color color;
private int size;
private int width, height;
private int newWidth;
/// Constructor.
public Margin( ImageProducer producer, Color color, int size )
{
super( producer, true );
this.color = color;
this.size = size;
}
public void setDimensions( int width, int height )
{
this.width = width;
this.height = height;
newWidth = width + size * 2;
consumer.setDimensions( newWidth, height + size * 2 );
}
private boolean started = false;
private void start()
{
started = true;
int rgb = color.getRGB();
int[] fullRow = new int[newWidth];
for ( int col = 0; col < newWidth; ++col )
fullRow[col] = rgb;
for ( int row = 0; row < size; ++row )
{
consumer.setPixels(
0, row, newWidth, 1, rgbModel, fullRow, 0, newWidth );
consumer.setPixels(
0, size + height + row, newWidth, 1, rgbModel, fullRow, 0,
newWidth );
}
int[] sideRow = new int[size];
for ( int col = 0; col < size; ++col )
sideRow[col] = rgb;
for ( int row = 0; row < height; ++row )
{
consumer.setPixels(
0, size + row, size, 1, rgbModel, sideRow, 0, size );
consumer.setPixels(
size + width, size + row, size, 1, rgbModel, sideRow, 0, size );
}
}
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
{
if ( ! started )
start();
consumer.setPixels(
x + size, y + size, w, h, model, pixels, off, scansize );
}
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
{
if ( ! started )
start();
consumer.setPixels(
x + size, y + size, w, h, model, pixels, off, scansize );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
if ( args.length != 1 )
usage();
ImageFilterPlus filter =
new Margin( null, Color.black, Integer.parseInt( args[0] ) );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Margin <size>" );
System.exit( 1 );
}
}

View file

@ -1,141 +0,0 @@
// Oil - oil-transfer filter
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.*;
/// Oil-transfer filter.
// <IMG ALIGN=RIGHT WIDTH=202 HEIGHT=200 SRC="Earth-Oil.jpg">
// <IMG ALIGN=RIGHT WIDTH=202 HEIGHT=200 SRC="Earth.jpg">
// <P>
// The oil transfer is described in "Beyond Photography" by Holzmann,
// chapter 4, photo 7.
// It's a sort of localized smearing.
// The parameter controls the size of the smeared area, with a default of 3.
// <P>
// This filter is very slow.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Oil.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class Oil extends RGBAllFilter
{
private int n;
/// Constructor.
public Oil( ImageProducer producer, int n )
{
super( producer );
this.n = n;
}
/// Constructor, default value.
public Oil( ImageProducer producer )
{
this( producer, 3 );
}
public void filterRGBAll( int width, int height, int[][] rgbPixels )
{
int[][] newPixels = new int[height][width];
int[] rHist = new int[256];
int[] gHist = new int[256];
int[] bHist = new int[256];
for ( int row = 0; row < height; ++row )
{
for ( int col = 0; col < width; ++col )
{
for ( int i = 0; i < 256; ++i )
rHist[i] = gHist[i] = bHist[i] =0;
for ( int drow = row - n; drow <= row + n; ++drow )
if ( drow >= 0 && drow < height )
for ( int dcol = col - n; dcol <= col + n; ++dcol )
if ( dcol >= 0 && dcol < width )
{
int rgb = rgbPixels[drow][dcol];
rHist[( rgb >> 16 ) & 0xff]++;
gHist[( rgb >> 8 ) & 0xff]++;
bHist[rgb & 0xff]++;
}
int r = 0, g = 0, b = 0;
for ( int i = 1; i < 256; ++i )
{
if ( rHist[i] > rHist[r] )
r = i;
if ( gHist[i] > gHist[g] )
g = i;
if ( bHist[i] > bHist[b] )
b = i;
}
newPixels[row][col] =
0xff000000 | ( r << 16 ) | ( g << 8 ) | b;
}
}
setPixels( width, height, newPixels );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
int n = -1;
int argc = args.length;
int argn;
for ( argn = 0; argn < argc && args[argn].charAt( 0 ) == '-'; ++argn )
{
if ( args[argn].equals( "-n" ) && argn + 1 < argc )
{
++argn;
n = Integer.parseInt( args[argn] );
}
else
usage();
}
if ( argn != argc )
usage();
ImageFilterPlus filter;
if ( n == -1 )
filter = new Oil( null );
else
filter = new Oil( null, n );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Oil [-n N]" );
System.exit( 1 );
}
}

View file

@ -1,170 +0,0 @@
// RGBAllFilter - an ImageFilter that grabs the whole image
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.*;
/// An ImageFilter that grabs the whole image.
// <P>
// Many image filters need to work on the whole image at once.
// This class collects up the image and hands it to a single
// routine for processing.
// <P>
// Also, because Java's image classes allow each setPixels() call to
// use a different color model, we have to convert all pixels into
// the default RGB model.
// <P>
// Here's a sample RGBAllFilter that smooths an image by averaging
// nine adjacent pixels.
// <BLOCKQUOTE><CODE><PRE>
// class SmoothFilter extends RGBAllFilter
// {
// public void filterRGBAll( int width, int height, int[][] rgbPixels )
// {
// int[][] newPixels = new int[height][width];
// for ( int row = 0; row &lt; height; ++row )
// for ( int col = 0; col &lt; width; ++col )
// {
// int a = 0, r = 0, g = 0, b = 0, c = 0;
// for ( int subrow = row - 1; subrow &lt;= row + 1; ++subrow )
// if ( subrow &gt;= 0 && subrow &lt; height )
// for ( int subcol = col - 1; subcol &lt;= col + 1; ++subcol )
// if ( subcol &gt;= 0 && subcol &lt; width )
// {
// int pixel = rgbPixels[subrow][subcol];
// a += rgbModel.getAlpha( pixel );
// r += rgbModel.getRed( pixel );
// g += rgbModel.getGreen( pixel );
// b += rgbModel.getBlue( pixel );
// ++c;
// }
// a /= c;
// r /= c;
// g /= c;
// b /= c;
// newPixels[row][col] =
// ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
// }
// setPixels( width, height, newPixels );
// }
// }
// </PRE></CODE></BLOCKQUOTE>
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/RGBAllFilter.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public abstract class RGBAllFilter extends ImageFilterPlus
{
private int width = -1, height = -1;
private int[][] rgbPixels = null;
public RGBAllFilter( ImageProducer producer )
{
super( producer );
}
/// This is the routine that subclasses must implement.
// It gets the entire image as an int[height][width] in the default
// RGB color model. It should call setPixels() with a filtered array,
// same color model.
public abstract void filterRGBAll( int width, int height, int[][] rgbPixels );
/// The version of setPixels() that gets called by the subclass.
public void setPixels( int newWidth, int newHeight, int[][] newPixels )
{
// Send it on to the consumer.
consumer.setDimensions( newWidth, newHeight );
for ( int row = 0; row < newHeight; ++row )
consumer.setPixels(
0, row, newWidth, 1, rgbModel, newPixels[row], 0, newWidth );
}
public void setColorModel( ColorModel model )
{
consumer.setColorModel( rgbModel );
}
public void setDimensions( int width, int height )
{
if ( width == this.width && height == this.height )
return;
this.width = width;
this.height = height;
rgbPixels = new int[height][width];
}
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
{
for ( int row = 0; row < h; ++row )
{
int rowOffsetIn = row * scansize + off;
for ( int col = 0; col < w; ++col )
rgbPixels[y + row][x + col] =
model.getRGB( pixels[rowOffsetIn + col] & 0xff );
}
}
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
{
for ( int row = 0; row < h; ++row )
{
int rowOffsetIn = row * scansize + off;
if ( model == rgbModel )
System.arraycopy(
pixels, rowOffsetIn, rgbPixels[y + row], x, w );
else
for ( int col = 0; col < w; ++col )
rgbPixels[y + row][x + col] =
model.getRGB( pixels[rowOffsetIn + col] );
}
}
public void imageComplete( int status )
{
if ( status == ImageConsumer.IMAGEERROR ||
status == ImageConsumer.IMAGEABORTED )
{
super.imageComplete( status );
return;
}
// Do the actual work.
filterRGBAll( width, height, rgbPixels );
// And we're done.
super.imageComplete( status );
}
}

View file

@ -1,135 +0,0 @@
// RGBBlockFilter - more efficient RGB ImageFilter
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.*;
/// More efficient RGB ImageFilter.
// <P>
// Similar in concept to java.awt.image.RGBImageFilter, but designed
// to run more efficiently when filtering large images.
// <P>
// As with RGBImageFilter, you only have to implement a single routine
// to use the filter. However, RGBImageFilter's routine filters a single
// pixel at a time. This means a lot of routine-calling overhead.
// RGBBlockFilter filters a block at a time.
// <P>
// Here's a sample RGBBlockFilter that makes an image translucent
// by setting all the alpha values to 0x80:
// <BLOCKQUOTE><CODE><PRE>
// class TranslucentFilter extends RGBBlockFilter
// {
// public int[] filterRGBBlock(
// int x, int y, int width, int height, int[][] rgbPixels )
// {
// for ( int row = 0; row &lt; height; ++row )
// for ( int col = 0; col &lt; width; ++col )
// rgbPixels[row][col] =
// ( rgbPixels[row][col] & 0x00ffffff ) | 0x80000000;
// return rgbPixels;
// }
// }
// </PRE></CODE></BLOCKQUOTE>
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/RGBBlockFilter.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public abstract class RGBBlockFilter extends ImageFilterPlus
{
public RGBBlockFilter( ImageProducer producer )
{
super( producer );
}
/// This is the routine that subclasses must implement.
// It gets a block of the image as an int[height][width] in the default
// RGB color model. It should return a filtered array, same size
// and same model.
public abstract int[][] filterRGBBlock(
int x, int y, int width, int height, int[][] rgbPixels );
public void setColorModel( ColorModel model )
{
consumer.setColorModel( rgbModel );
}
/// Byte version of setPixels reformats the pixels to RGB and the
// array to 2 dimensions.
public void setPixels(
int x, int y, int width, int height, ColorModel model,
byte[] pixels, int offset, int scansize )
{
int[][] rgbPixels = new int[height][width];
for ( int row = 0; row < height; ++row )
{
int rowOffsetIn = offset + row * scansize;
for ( int col = 0; col < width; ++col )
rgbPixels[row][col] =
model.getRGB( pixels[rowOffsetIn + col] & 0xff );
}
setPixels( x, y, width, height, rgbPixels );
}
/// Int version of setPixels reformats the array to 2 dimensions.
public void setPixels(
int x, int y, int width, int height, ColorModel model,
int[] pixels, int offset, int scansize )
{
int[][] rgbPixels = new int[height][width];
for ( int row = 0; row < height; ++row )
{
int rowOffsetIn = offset + row * scansize;
int rowOffsetOut = row * width;
// Convert color models if necessary.
if ( model == rgbModel )
System.arraycopy(
pixels, rowOffsetIn, rgbPixels[row], 0, width );
else
for ( int col = 0; col < width; ++col )
rgbPixels[row][col] =
model.getRGB( pixels[rowOffsetIn + col] );
}
setPixels( x, y, width, height, rgbPixels );
}
/// Call the filter routine, and send the results to the consumer.
private void setPixels( int x, int y, int width, int height, int[][] rgbPixels )
{
int[][] newPixels = filterRGBBlock( x, y, width, height, rgbPixels );
// And send it on to the consumer.
for ( int row = 0; row < height; ++row )
consumer.setPixels(
x, y + row, width, 1, rgbModel, newPixels[row], 0, width );
}
}

View file

@ -1,81 +0,0 @@
// Rotate - rotate an image by some angle
//
// Copyright (C) 1997 by Jef Poskanzer <jef@acme.com>. 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.*;
/// Rotate an image by some angle.
// <P>
// Rotates an image by the specified angle.
// The angle is in degrees measured counter-clockwise.
// It can be negative, but it should be between -90 and 90
// or the resulting image will be unreasonably large.
// Staying between -45 and 45 is best.
// <P>
// The rotation algorithm is Alan Paeth's three-shear method, described
// in "A Fast Algorithm for General Raster Rotation", Graphics Interface
// '86, pp. 77-81.
// <P>
// This filter is slow.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Rotate.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class Rotate extends CompositeFilter
{
private double angle;
/// Constructor.
public Rotate( ImageProducer producer, double angle )
{
super( producer, new Shear( null, angle ), new Flip( null, Flip.FLIP_XY ) );
this.angle = angle * Math.PI / 180.0;
double xshearfac = Math.tan( angle / 2.0 );
double yshearfac = Math.sin( angle );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
if ( args.length != 1 )
usage();
ImageFilterPlus filter = new Rotate( null, Integer.parseInt( args[0] ) );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Rotate <angle>" );
System.exit( 1 );
}
}

View file

@ -1,159 +0,0 @@
// ScaleCopy - an ImageFilter that scales by pixel copying
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.*;
/// An ImageFilter that scales by pixel copying.
// <P>
// Scales an image by copying pixels.
// If the image is being enlarged, pixels get replicated;
// if the image is being shrunk, pixels get dropped.
// The output uses the same color model as the input.
// For enlarging, this filter is slightly slower than Enlarge due
// to the floating-point arithmetic;
// for shrinking, it's much faster than Shrink, but
// the results aren't as nice.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/ScaleCopy.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see Enlarge
// @see Shrink
public class ScaleCopy extends ImageFilterPlus
{
private double xScale, yScale;
private int newWidth, newHeight;
/// Constructor, same X and Y scale factor.
public ScaleCopy( ImageProducer producer, double scale )
{
this( producer, scale, scale );
}
/// Constructor, different X and Y scale factors.
public ScaleCopy( ImageProducer producer, double xScale, double yScale )
{
super( producer );
this.xScale = xScale;
this.yScale = yScale;
}
public void setDimensions( int width, int height )
{
newWidth = (int) ( width * xScale );
newHeight = (int) ( height * yScale );
consumer.setDimensions( newWidth, newHeight );
}
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
{
int newX = Math.min( (int) ( x * xScale ), newWidth - 1 );
int newY = Math.min( (int) ( y * yScale ), newHeight - 1 );
int newW = Math.max( (int) ( w * xScale ), 1 );
if ( newX + newW > newWidth )
newW = newWidth - newX;
int newH = Math.max( (int) ( h * yScale ), 1 );
if ( newY + newH > newHeight )
newH = newHeight - newY;
byte[] newPixels = new byte[newW * newH];
for ( int newRow = 0; newRow < newH; ++newRow )
{
int row = (int) ( newRow / yScale );
if ( row >= h )
continue;
for ( int newCol = 0; newCol < newW; ++newCol )
{
int col = (int) ( newCol / xScale );
if ( col >= w )
continue;
newPixels[newRow * newW + newCol] =
pixels[row * scansize + off + col];
}
}
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
}
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
{
int newX = Math.min( (int) ( x * xScale ), newWidth - 1 );
int newY = Math.min( (int) ( y * yScale ), newHeight - 1 );
int newW = Math.max( (int) ( w * xScale ), 1 );
if ( newX + newW > newWidth )
newW = newWidth - newX;
int newH = Math.max( (int) ( h * yScale ), 1 );
if ( newY + newH > newHeight )
newH = newHeight - newY;
int[] newPixels = new int[newW * newH];
for ( int newRow = 0; newRow < newH; ++newRow )
{
int row = (int) ( newRow / yScale );
if ( row >= h )
continue;
for ( int newCol = 0; newCol < newW; ++newCol )
{
int col = (int) ( newCol / xScale );
if ( col >= w )
continue;
newPixels[newRow * newW + newCol] =
pixels[row * scansize + off + col];
}
}
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
ImageFilterPlus filter = null;
if ( args.length == 1 )
filter = new ScaleCopy( null,
Double.valueOf( args[0] ).doubleValue() );
else if ( args.length == 2 )
filter = new ScaleCopy( null,
Double.valueOf( args[0] ).doubleValue(),
Double.valueOf( args[1] ).doubleValue() );
else
usage();
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: ScaleCopy scale" );
System.err.println( "or: ScaleCopy xScale yScale" );
System.exit( 1 );
}
}

View file

@ -1,144 +0,0 @@
// Shear - shear an image by some angle
//
// Copyright (C) 1997 by Jef Poskanzer <jef@acme.com>. 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.*;
/// Shear an image by some angle.
// <P>
// Shears an image by the specified angle.
// The angle is in degrees (floating point), and measures this:
// <BLOCKQUOTE><PRE><CODE>
// +-------+ +-------+
// | | |\ \
// | OLD | | \ NEW \
// | | |an\ \
// +-------+ |gle+-------+
// </CODE></PRE></BLOCKQUOTE>
// If the angle is negative, it shears the other way:
// <BLOCKQUOTE><PRE><CODE>
// +-------+ |-an+-------+
// | | |gl/ /
// | OLD | |e/ NEW /
// | | |/ /
// +-------+ +-------+
// </CODE></PRE></BLOCKQUOTE>
// The angle should not get too close to 90 or -90, or the resulting
// image will be unreasonably wide. Staying between -45 and 45 is best.
// <P>
// The shearing is implemented by looping over the source pixels and
// distributing fractions to each of the destination pixels.
// This has an "anti-aliasing" effect - it avoids jagged edges and similar
// artifacts.
// <P>
// This filter is fast.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Shear.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class Shear extends RGBAllFilter
{
private double angle;
/// Constructor.
public Shear( ImageProducer producer, double angle )
{
super( producer );
this.angle = angle * Math.PI / 180.0;
}
public void filterRGBAll( int width, int height, int[][] rgbPixels )
{
double shearfac = Math.tan( angle );
if ( shearfac < 0.0 )
shearfac = -shearfac;
int newWidth = (int) ( height * shearfac + width + 0.999999 );
int[][] newPixels = new int[height][newWidth];
for ( int row = 0; row < height; ++row )
{
double new0;
if ( angle > 0.0 )
new0 = row * shearfac;
else
new0 = ( height - row ) * shearfac;
int intnew0 = (int) new0;
double fracnew0 = new0 - intnew0;
double omfracnew0 = 1.0 - fracnew0;
for ( int col = 0; col < newWidth; ++col )
newPixels[row][col] = 0x00000000;
int preva = 0;
int prevr = ( rgbPixels[row][0] >> 16 ) & 0xff;
int prevg = ( rgbPixels[row][0] >> 8 ) & 0xff;
int prevb = rgbPixels[row][0] & 0xff;
for ( int col = 0; col < width; ++col )
{
int rgb = rgbPixels[row][col];
int a = ( rgb >> 24 ) & 0xff;
int r = ( rgb >> 16 ) & 0xff;
int g = ( rgb >> 8 ) & 0xff;
int b = rgb & 0xff;
newPixels[row][intnew0 + col] =
( (int) ( fracnew0 * preva + omfracnew0 * a ) << 24 ) |
( (int) ( fracnew0 * prevr + omfracnew0 * r ) << 16 ) |
( (int) ( fracnew0 * prevg + omfracnew0 * g ) << 8 ) |
( (int) ( fracnew0 * prevb + omfracnew0 * b ) );
preva = a;
prevr = r;
prevg = g;
prevb = b;
}
newPixels[row][intnew0 + width] =
( (int) ( fracnew0 * preva ) << 24 ) |
( prevr << 16 ) | ( prevg << 8 ) | prevb;
}
setPixels( newWidth, height, newPixels );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
if ( args.length != 1 )
usage();
ImageFilterPlus filter = new Shear( null, Integer.parseInt( args[0] ) );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Shear <angle>" );
System.exit( 1 );
}
}

View file

@ -1,116 +0,0 @@
// Shrink - an ImageFilter that shrinks by pixel averaging
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.*;
/// An ImageFilter that shrinks by pixel averaging.
// <P>
// Shrinks an image an integral factor by averaging pixels.
// Because the resulting pixels might not fit into the input's
// color model, the output is always in the default RGB color model.
// This filter is somewhat slow.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Shrink.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see Enlarge
// @see ScaleCopy
public class Shrink extends RGBAllFilter
{
private int divisor;
/// Constructor.
public Shrink( ImageProducer producer, int divisor )
{
super( producer );
this.divisor = divisor;
}
public void filterRGBAll( int width, int height, int[][] rgbPixels )
{
int divisor2 = divisor * divisor;
int newWidth = Math.max( width / divisor, 1 );
int newHeight = Math.max( height / divisor, 1 );
int[][] newPixels = new int[newHeight][newWidth];
for ( int newRow = 0; newRow < newHeight; ++newRow )
{
for ( int newCol = 0; newCol < newWidth; ++newCol )
{
int a = 0, r = 0, g = 0, b = 0;
for ( int i = 0; i < divisor; ++i )
{
int row = newRow * divisor + i;
if ( row >= height )
continue;
for ( int j = 0; j < divisor; ++j )
{
int col = newCol * divisor + j;
if ( col >= width )
continue;
int rgb = rgbPixels[row][col];
a += ( rgb >> 24 ) & 0xff;
r += ( rgb >> 16 ) & 0xff;
g += ( rgb >> 8 ) & 0xff;
b += rgb & 0xff;
}
}
a /= divisor2;
r /= divisor2;
g /= divisor2;
b /= divisor2;
newPixels[newRow][newCol] =
( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
}
}
setPixels( newWidth, newHeight, newPixels );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
if ( args.length != 1 )
usage();
ImageFilterPlus filter = new Enlarge(
null, Integer.parseInt( args[0] ) );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Shrink <divisor>" );
System.exit( 1 );
}
}

View file

@ -1,123 +0,0 @@
// Smooth - smoothing filter
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.*;
/// Smoothing filter.
// <P>
// Smooths an image by averaging adjacent pixels.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Smooth.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class Smooth extends RGBAllFilter
{
private int n;
/// Constructor.
public Smooth( ImageProducer producer, int n )
{
super( producer );
this.n = n;
}
/// Constructor, default value.
public Smooth( ImageProducer producer )
{
this( producer, 1 );
}
public void filterRGBAll( int width, int height, int[][] rgbPixels )
{
int[][] newPixels = new int[height][width];
for ( int row = 0; row < height; ++row )
for ( int col = 0; col < width; ++col )
{
int a = 0, r = 0, g = 0, b = 0, c = 0;
for ( int subrow = row - n; subrow <= row + n; ++subrow )
if ( subrow >= 0 && subrow < height )
for ( int subcol = col - n; subcol <= col + n; ++subcol )
if ( subcol >= 0 && subcol < width )
{
int rgb = rgbPixels[subrow][subcol];
a += ( rgb >> 24 ) & 0xff;
r += ( rgb >> 16 ) & 0xff;
g += ( rgb >> 8 ) & 0xff;
b += rgb & 0xff;
++c;
}
a /= c;
r /= c;
g /= c;
b /= c;
newPixels[row][col] =
( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
}
setPixels( width, height, newPixels );
}
// Main routine for command-line interface.
public static void main( String[] args )
{
int n = -1;
int argc = args.length;
int argn;
for ( argn = 0; argn < argc && args[argn].charAt( 0 ) == '-'; ++argn )
{
if ( args[argn].equals( "-n" ) && argn + 1 < argc )
{
++argn;
n = Integer.parseInt( args[argn] );
}
else
usage();
}
if ( argn != argc )
usage();
ImageFilterPlus filter;
if ( n == -1 )
filter = new Smooth( null );
else
filter = new Smooth( null, n );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Smooth [-n N]" );
System.exit( 1 );
}
}

View file

@ -1,126 +0,0 @@
// Tile - an ImageFilter that replicates an image in a tiled pattern
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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.*;
/// An ImageFilter that replicates an image in a tiled pattern.
// <P>
// Tiles the image onto an output image of a specified size.
// The output uses the same color model as the input.
// This filter is very fast.
// <P>
// <A HREF="/resources/classes/Acme/JPM/Filters/Tile.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class Tile extends ImageFilterPlus
{
private int width, height;
private int newWidth, newHeight;
private int nWide, nHigh;
/// Constructor.
public Tile( ImageProducer producer, int newWidth, int newHeight )
{
super( producer, true );
this.newWidth = newWidth;
this.newHeight = newHeight;
}
public void setDimensions( int width, int height )
{
this.width = width;
this.height = height;
consumer.setDimensions( newWidth, newHeight );
nWide = ( newWidth + width - 1 ) / width;
nHigh = ( newHeight + height - 1 ) / height;
}
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
{
for ( int r = 0; r < nHigh; ++r )
{
int ty = r * height + y;
int th = h;
if ( ty + th > newHeight )
th = newHeight - ty;
for ( int c = 0; c < nWide; ++c )
{
int tx = c * width + x;
int tw = w;
if ( tx + tw > newWidth )
tw = newWidth - tx;
consumer.setPixels(
tx, ty, tw, th, model, pixels, off, scansize );
}
}
}
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
{
for ( int r = 0; r < nHigh; ++r )
{
int ty = r * height + y;
int th = h;
if ( ty + th > newHeight )
th = newHeight - ty;
for ( int c = 0; c < nWide; ++c )
{
int tx = c * width + x;
int tw = w;
if ( tx + tw > newWidth )
tw = newWidth - tx;
consumer.setPixels(
tx, ty, tw, th, model, pixels, off, scansize );
}
}
}
// Main routine for command-line interface.
public static void main( String[] args )
{
if ( args.length != 2 )
usage();
ImageFilterPlus filter =
new Tile( null,
Integer.parseInt( args[0] ), Integer.parseInt( args[1] ) );
System.exit(
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
}
private static void usage()
{
System.err.println( "usage: Tile <width> <height>" );
System.exit( 1 );
}
}

View file

@ -1,50 +0,0 @@
// JPMUtils - static utility routines for the JPM packages
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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;
import java.awt.*;
import java.awt.image.*;
import Acme.JPM.Filters.*;
/// Static utility routines for the JPM packages.
// <P>
// <A HREF="/resources/classes/Acme/JPM/JPMUtils.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
public class JPMUtils
{
/// Filter one image into another.
public static Image filterImage( Component comp, ImageFilterPlus filter )
{
return comp.createImage(
new FilteredImageSource( filter.getSource(), filter ) );
}
}

View file

@ -1,303 +0,0 @@
// LruHashtable - a Hashtable that expires least-recently-used objects
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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;
import java.util.*;
/// A Hashtable that expires least-recently-used objects.
// <P>
// Use just like java.util.Hashtable, except that the initial-capacity
// parameter is required. Instead of growing bigger than that size,
// it will throw out objects that haven't been looked at in a while.
// <P>
// <A HREF="/resources/classes/Acme/LruHashtable.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see java.util.Hashtable
public class LruHashtable extends Hashtable
{
// Number of buckets.
private static final int nBuckets = 2;
// Load factor.
private float loadFactor;
// When count exceeds this threshold, expires the old table.
private int threshold;
// Capacity of each bucket.
private int eachCapacity;
// The tables.
private Hashtable oldTable;
private Hashtable newTable;
/// Constructs a new, empty hashtable with the specified initial
// capacity and the specified load factor.
// Unlike a plain Hashtable, an LruHashtable will never grow or
// shrink from this initial capacity.
// @param initialCapacity the initial number of buckets
// @param loadFactor a number between 0.0 and 1.0, it defines
// the threshold for expiring old entries
// @exception IllegalArgumentException If the initial capacity
// is less than or equal to zero.
// @exception IllegalArgumentException If the load factor is
// less than or equal to zero.
public LruHashtable( int initialCapacity, float loadFactor )
{
// We have to call a superclass constructor, but we're not actually
// going to use it at all. The only reason we want to extend Hashtable
// is for type conformance. So, make a parent hash table of minimum
// size and then ignore it.
super( 1 );
if ( initialCapacity <= 0 || loadFactor <= 0.0 )
throw new IllegalArgumentException();
this.loadFactor = loadFactor;
threshold = (int) ( initialCapacity * loadFactor ) - 1;
eachCapacity = initialCapacity / nBuckets + 1;
oldTable = new Hashtable( eachCapacity, loadFactor );
newTable = new Hashtable( eachCapacity, loadFactor );
}
/// Constructs a new, empty hashtable with the specified initial
// capacity.
// Unlike a plain Hashtable, an LruHashtable will never grow or
// shrink from this initial capacity.
// @param initialCapacity the initial number of buckets
public LruHashtable( int initialCapacity )
{
this( initialCapacity, 0.75F );
}
/// Returns the number of elements contained in the hashtable.
public int size()
{
return newTable.size() + oldTable.size();
}
/// Returns true if the hashtable contains no elements.
public boolean isEmpty()
{
return size() == 0;
}
/// Returns an enumeration of the hashtable's keys.
// @see LruHashtable#elements
// @see Enumeration
public synchronized Enumeration keys()
{
return new LruHashtableEnumerator( oldTable, newTable, true );
}
/// Returns an enumeration of the elements. Use the Enumeration methods
// on the returned object to fetch the elements sequentially.
// @see LruHashtable#keys
// @see Enumeration
public synchronized Enumeration elements()
{
return new LruHashtableEnumerator( oldTable, newTable, false );
}
/// Returns true if the specified object is an element of the hashtable.
// This operation is more expensive than the containsKey() method.
// @param value the value that we are looking for
// @exception NullPointerException If the value being searched
// for is equal to null.
// @see LruHashtable#containsKey
public synchronized boolean contains( Object value )
{
if ( newTable.contains( value ) )
return true;
if ( oldTable.contains( value ) )
{
// We would like to move the object from the old table to the
// new table. However, we need keys to re-add the objects, and
// there's no good way to find all the keys for the given object.
// We'd have to enumerate through all the keys and check each
// one. Yuck. For now we just punt. Anyway, contains() is
// probably not a commonly-used operation.
return true;
}
return false;
}
/// Returns true if the collection contains an element for the key.
// @param key the key that we are looking for
// @see LruHashtable#contains
public synchronized boolean containsKey( Object key )
{
if ( newTable.containsKey( key ) )
return true;
if ( oldTable.containsKey( key ) )
{
// Move object from old table to new table.
Object value = oldTable.get( key );
newTable.put( key, value );
oldTable.remove( key );
return true;
}
return false;
}
/// Gets the object associated with the specified key in the
// hashtable.
// @param key the specified key
// @returns the element for the key or null if the key
// is not defined in the hash table.
// @see LruHashtable#put
public synchronized Object get( Object key )
{
Object value;
value = newTable.get( key );
if ( value != null )
return value;
value = oldTable.get( key );
if ( value != null )
{
// Move object from old table to new table.
newTable.put( key, value );
oldTable.remove( key );
return value;
}
return null;
}
/// Puts the specified element into the hashtable, using the specified
// key. The element may be retrieved by doing a get() with the same key.
// The key and the element cannot be null.
// @param key the specified key in the hashtable
// @param value the specified element
// @exception NullPointerException If the value of the element
// is equal to null.
// @see LruHashtable#get
// @return the old value of the key, or null if it did not have one.
public synchronized Object put( Object key, Object value )
{
Object oldValue = newTable.put( key, value );
if ( oldValue != null )
return oldValue;
oldValue = oldTable.get( key );
if ( oldValue != null )
oldTable.remove( key );
else
{
if ( size() >= threshold )
{
// Rotate the tables.
oldTable = newTable;
newTable = new Hashtable( eachCapacity, loadFactor );
}
}
return oldValue;
}
/// Removes the element corresponding to the key. Does nothing if the
// key is not present.
// @param key the key that needs to be removed
// @return the value of key, or null if the key was not found.
public synchronized Object remove( Object key )
{
Object oldValue = newTable.remove( key );
if ( oldValue == null )
oldValue = oldTable.remove( key );
return oldValue;
}
/// Clears the hash table so that it has no more elements in it.
public synchronized void clear()
{
newTable.clear();
oldTable.clear();
}
/// Creates a clone of the hashtable. A shallow copy is made,
// the keys and elements themselves are NOT cloned. This is a
// relatively expensive operation.
public synchronized Object clone()
{
LruHashtable n = (LruHashtable) super.clone();
n.newTable = (Hashtable) n.newTable.clone();
n.oldTable = (Hashtable) n.oldTable.clone();
return n;
}
// toString() can be inherited.
}
class LruHashtableEnumerator implements Enumeration
{
Enumeration oldEnum;
Enumeration newEnum;
boolean old;
LruHashtableEnumerator( Hashtable oldTable, Hashtable newTable, boolean keys )
{
if ( keys )
{
oldEnum = oldTable.keys();
newEnum = newTable.keys();
}
else
{
oldEnum = oldTable.elements();
newEnum = newTable.elements();
}
old = true;
}
public boolean hasMoreElements()
{
boolean r;
if ( old )
{
r = oldEnum.hasMoreElements();
if ( ! r )
{
old = false;
r = newEnum.hasMoreElements();
}
}
else
r = newEnum.hasMoreElements();
return r;
}
public Object nextElement()
{
if ( old )
return oldEnum.nextElement();
return newEnum.nextElement();
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,147 +0,0 @@
// WildcardDictionary - a dictionary with wildcard lookups
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. 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;
import java.util.*;
/// A dictionary with wildcard lookups.
// <P>
// The keys in this dictionary are wildcard patterns. When you do a get(),
// the string you pass in is matched against all the patterns, and the
// first match is returned.
// <P>
// The wildcard matcher is fairly simple, it implements * meaning any
// string, ? meaning any single character, and | separating multiple
// patterns. All other characters must match literally.
// <P>
// <A HREF="/resources/classes/Acme/WildcardDictionary.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see Acme.Utils#match
public class WildcardDictionary extends Dictionary
{
private Vector keys;
private Vector elements;
/// Constructor.
public WildcardDictionary()
{
keys = new Vector();
elements = new Vector();
}
/// Returns the number of elements contained within the dictionary.
public int size()
{
return elements.size();
}
/// Returns true if the dictionary contains no elements.
public boolean isEmpty()
{
return size() == 0;
}
/// Returns an enumeration of the dictionary's keys.
public Enumeration keys()
{
return keys.elements();
}
/// Returns an enumeration of the elements. Use the Enumeration methods
// on the returned object to fetch the elements sequentially.
public Enumeration elements()
{
return elements.elements();
}
/// Gets the object associated with the specified key in the dictionary.
// The key is assumed to be a String, which is matched against
// the wildcard-pattern keys in the dictionary.
// @param key the string to match
// @returns the element for the key, or null if there's no match
// @see Acme.Utils#match
public synchronized Object get( Object key )
{
String sKey = (String) key;
for ( int i = 0; i < keys.size(); ++i )
{
String thisKey = (String) keys.elementAt( i );
if ( Acme.Utils.match( thisKey, sKey ) )
return elements.elementAt( i );
}
return null;
}
/// Puts the specified element into the Dictionary, using the specified
// key. The element may be retrieved by doing a get() with the same
// key. The key and the element cannot be null.
// @param key the specified wildcard-pattern key
// @param value the specified element
// @return the old value of the key, or null if it did not have one.
// @exception NullPointerException If the value of the specified
// element is null.
public synchronized Object put( Object key, Object element )
{
int i = keys.indexOf( key );
if ( i != -1 )
{
Object oldElement = elements.elementAt( i );
elements.setElementAt( element, i );
return oldElement;
}
else
{
keys.addElement( key );
elements.addElement( element );
return null;
}
}
/// Removes the element corresponding to the key. Does nothing if the
// key is not present.
// @param key the key that needs to be removed
// @return the value of key, or null if the key was not found.
public synchronized Object remove( Object key )
{
int i = keys.indexOf( key );
if ( i != -1 )
{
Object oldElement = elements.elementAt( i );
keys.removeElementAt( i );
elements.removeElementAt( i );
return oldElement;
}
else
return null;
}
}