Hello,

This java.awt.Image enables the creation of animation using
MemoryImageSource.

Included an applet I picked on Internet to test it (Plasma).

--
------------------------------------
| Guilhem Lavaux [EMAIL PROTECTED] |
------------------------------------


package java.awt;

import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.IndexColorModel;
import java.awt.image.MemoryImageSource;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import kaffe.io.AccessibleBAOStream;
import kaffe.util.Ptr;
import kaffe.util.VectorSnapshot;

/**
 * Copyright (c) 1998
 *    Transvirtual Technologies, Inc.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file.
 *
 * @author P.C.Mehlitz
 */
public class Image
{
        Ptr nativeData;
        int width = -1;
        int height = -1;
        ImageProducer producer;
        Object observers;
        int flags;
        Hashtable props;
        Image next;
        final public static int SCALE_DEFAULT = 1;
        final public static int SCALE_FAST = 2;
        final public static int SCALE_SMOOTH = 4;
        final public static int SCALE_REPLICATE = 8;
        final public static int SCALE_AREA_AVERAGING = 16;
        final static int MASK = ImageObserver.WIDTH|ImageObserver.HEIGHT|
                        ImageObserver.PROPERTIES|ImageObserver.SOMEBITS|
                        ImageObserver.FRAMEBITS|ImageObserver.ALLBITS|
                        ImageObserver.ERROR|ImageObserver.ABORT;
        final static int PRODUCING = 1 << 8;
        final static int READY = ImageObserver.WIDTH | ImageObserver.HEIGHT | 
ImageObserver.ALLBITS | PRODUCING;
        final static int SCREEN = 1 << 10;
        final static int BLOCK_FRAMELOADER = 1 << 11;
        final public static Object UndefinedProperty = ImageLoader.class;

Image ( File file ) {
        producer = new ImageNativeProducer( this, file);
}

Image ( Image img, int w, int h ) {
        nativeData = Toolkit.imgCreateScaledImage(img.nativeData, w, h);
        width = w;
        height = h;
        flags = READY;
}

Image ( ImageProducer ip ) {
        producer = ip;

        // there currently is no way to check the size of a MemoryImageSource, 
        // so everything != 0 causes async production
        if ( (Defaults.MemImageSrcThreshold == 0) && (producer instanceof 
MemoryImageSource) ) {
                flags |= PRODUCING;
                synchronized ( ImageLoader.syncLoader ) {
                        ImageLoader.syncLoader.img = this;
                        ip.startProduction( ImageLoader.syncLoader);
                }
        }
}

Image ( URL url ) {
        producer = new ImageNativeProducer( url);
}

Image ( byte[] data, int offs, int len) {
        producer = new ImageNativeProducer( this, data, offs, len);
}

Image ( int w, int h ) {
        nativeData = Toolkit.imgCreateScreenImage( w, h );
        width = w;
        height = h;
        flags = READY | SCREEN;
}

synchronized void activateFrameLoader () {
  // activate waiting FrameLoader
        if ( (flags & BLOCK_FRAMELOADER) != 0 ){
                flags &= ~BLOCK_FRAMELOADER;
                notify();
        }
}

// -------------------------------------------------------------------------
void addObserver ( ImageObserver observer ) {
        if ( observer == null ) {
                return;
        }

        if ( observers == null ) {
                observers = observer;
        }       
        else if ( observers instanceof Vector ) {
                Vector v = (Vector) observers;
                if ( !v.contains(observer) )
                        v.addElement(observer);
        }
        else {
                if ( observer != observers ) {
                        Vector v = new Vector( 3);
                        v.addElement( observers);
                        v.addElement( observer);
                        observers = v;
                }
        }
}

synchronized int checkImage ( int w, int h, ImageObserver obs, boolean load ){
        if ( (flags & (ImageObserver.ALLBITS | ImageObserver.FRAMEBITS)) != 0 ) {
                if ( ((w > 0) || (h > 0)) && (w != width) && (h != height) ){
                        scale( w, h);
                }
                
                if ( load && (flags & ImageObserver.FRAMEBITS) != 0 )
                        addObserver( obs);
        }
        else if ( load && ((flags & PRODUCING) == 0) ) {
                loadImage( w, h, obs);
        }

        return (flags & MASK);
}

protected void finalize () throws Throwable {
        flush();
        super.finalize();
}

public void flush () {
        // This is the bad guy - the spec demands that it reverts us into a 
"not-yet-loaded"
        // state, "to be recreated or fetched again from its source" when a subsequent
        // rendering takes place. Since "its source" doesn't mean the *original* source
        // (see getSource() - "an object that *produces* the image"), we could stay 
with the
        // native representation (probably the most efficient storage and prod 
environment),
        // but apps explicitly using flush most probably use it because the original
        // image source has changed, i.e. they use flush() as a way to in-situ modify
        // otherwise constant images (by means of changed sources). Only heaven knows 
why
        // they don't replace the image (this is like a Graphics that can be brought 
back
        // to life after a dispose()). That means we have to keep a ref of byte[] 
data, and
        // we can't produce on-screen images

        if ( nativeData != null && (flags & ImageObserver.ALLBITS) != 0){
                Toolkit.imgFreeImage( nativeData);
                nativeData = null;
                flags = 0;
                width = -1;
                height = -1;
        }
}

public Graphics getGraphics () {
        if ((flags & SCREEN) == 0 || nativeData == null) {
                return null;
        }
        else {
                return NativeGraphics.getGraphics( this,
                                   nativeData, NativeGraphics.TGT_TYPE_IMAGE,
                                   0, 0, 0, 0, width, height,
                                                                                   
Color.black, Color.white, Defaults.WndFont, false);
        }
}

public synchronized int getHeight ( ImageObserver observer ) {
        if ( (flags & ImageObserver.HEIGHT) != 0 ) {
                return height;
        }
        else {
                loadImage(-1, -1, observer);
                return (-1);
        }
}

public Object getProperty ( String name, ImageObserver observer ) {
        if ( props == null ) {
                if ( (flags & (ImageObserver.FRAMEBITS | ImageObserver.ALLBITS)) != 0 )
                        return UndefinedProperty;
                else if ( (flags & PRODUCING) == 0 )
                        loadImage( -1, -1, observer);

                return null;
        }
        else {
                Object val = props.get( name);
                if ( val == null )
                        return UndefinedProperty;
                        
                return val;
        }
}

public Image getScaledInstance (int width, int height, int hints) {
        if (nativeData == null || width <= 0 || height <= 0 || (flags & SCREEN) != 0 
|| (flags & ImageObserver.ALLBITS) == 0) {
                return (null);
        }
        return (new Image(this, width, height));
}

public ImageProducer getSource () {
        if ( producer == null )
                producer = new ImageNativeProducer( this);

        return producer;
}

public synchronized int getWidth ( ImageObserver observer ) {
        if ( (flags & ImageObserver.WIDTH) != 0 ) {
                return (width);
        }
        else {
                loadImage(-1, -1, observer);
                return (-1);
        }
}

synchronized boolean loadImage ( int w, int h, ImageObserver obs ) {
        // it's (partly?) loaded already
        if ( (flags & (ImageObserver.FRAMEBITS|ImageObserver.ALLBITS)) != 0 ){
                if ( ((w > 0) || (h > 0)) && (w != width) && (h != height) ) {
                        // but do we have to scale it? 
                        scale( w, h);
                }
                if ( (flags & ImageObserver.FRAMEBITS) != 0 ) {
                        addObserver( obs);
                }
                return (true);
        }
        // we ultimately failed
        else if ( (flags & ImageObserver.ABORT) != 0 ) {
                return (false);
        }
        // there's work ahead, kick it off
        else if ( (flags & PRODUCING) == 0 ) {
                flags |= PRODUCING;
                if ( obs != null ) {
                        addObserver( obs);
                }
                /*
                 * We now load the image data synchronously - it's not clear
                 * that's what you should actually do but it fixes a problem
                 * with the Citrix ICA client. (Tim 1/18/99)
                 */
                ImageLoader.loadSync( this);
                return (true);
        }
        return (false);
}

void removeObserver ( ImageObserver observer ) {
        if ( (observers == null) || (observer == null) )
                return;

        if ( observers == observer ){
                observers = null;
        }
        else if ( observers instanceof Vector ) {
                Vector v = (Vector)observers;
                v.removeElement( observer);
                
                if ( v.size() == 1 )
                        observers = v.firstElement();
        }
}

private boolean scale (int w, int h) {
        if ((flags & SCREEN) != 0 || (flags & ImageObserver.ALLBITS) == 0 || 
nativeData == null) {
                return (false);
        }
        if (w != width || h != height) {
                Ptr oldNativeData = nativeData;
                nativeData = Toolkit.imgCreateScaledImage( nativeData, w, h );
                Toolkit.imgFreeImage( oldNativeData);
                width = w;
                height = h;
        }
        return (true);
}

synchronized void stateChange(int flags, int x, int y, int w, int h) {
        ImageObserver obs;

        this.flags |= flags;

        if (observers == null) {
                return;
        }

        // We get false if they're no longer interested in updates. This is *NOT* what 
is said in the
        // Addison-Wesley documentation, but is what is says in the JDK javadoc 
documentation.  
        if ( observers instanceof ImageObserver ){
                obs = (ImageObserver) observers;
                if ( obs.imageUpdate( this, flags, x, y, w, h) == false ) {
                        observers = null;
                }
        }
        else if ( observers instanceof Vector ){
                // we can't use a (index-based) standard Vector enumerator because we 
have
                // to notify *all* elements regardless of any removals
                for ( Enumeration e=VectorSnapshot.getCached( (Vector)observers); 
e.hasMoreElements(); ) {
                        obs = (ImageObserver) e.nextElement();
                        if ( obs.imageUpdate( this, flags, x, y, w, h) == false )
                                removeObserver( obs);
                }
        }
}

public String toString() {
        String s = getClass().getName() + " [" + width + ',' + height + 
                      ((nativeData != null) ? ", native" : ", non-native") +
                ", flags: "  + Integer.toHexString( flags);

        if ( (flags & PRODUCING) != 0 )
                s += " producing";
        if ( (flags & ImageObserver.ALLBITS) != 0 )
                s += " allbits";
        else if ( (flags & ImageObserver.FRAMEBITS) != 0 )
                s += " framebits";
        else if ( (flags & ImageObserver.ERROR) != 0 )
                s += " error";

        s += "]";

        return s;               
}
}

class ImageFrameLoader
  extends Thread implements ImageConsumer
{
        Image img;

public void imageComplete( int status ) {
        int s = 0;

        if ( status == STATICIMAGEDONE ){
          s = ImageObserver.ALLBITS;
          // give native layer a chance to do alpha channel reduction
          Toolkit.imgComplete( img.nativeData, status);

          img.producer.removeConsumer(this);
        }
        else if ( status == SINGLEFRAMEDONE ) {
            s = ImageObserver.FRAMEBITS;
            Toolkit.imgComplete( img.nativeData, status);
        }
        else {
            if ( (status & IMAGEERROR) != 0 )       s |= ImageObserver.ERROR;
            if ( (status & IMAGEABORTED) != 0 )     s |= ImageObserver.ABORT;
            img.producer.removeConsumer(this);
        }

        img.stateChange( s, 0, 0, img.width, img.height);       
}

public void setColorModel( ColorModel model ) {
}

public void setDimensions ( int width, int height ) {
}

public void setHints ( int hints ) {
}

public void setPixels ( int x, int y, int w, int h, ColorModel model, byte pixels[], 
int offset, int scansize ) {
    if ( img.nativeData == null ) {
        // producer trouble, we haven't got dimensions yet
        return;
    }
    
    if ( model instanceof IndexColorModel ) {
        IndexColorModel icm = (IndexColorModel) model;
        Toolkit.imgSetIdxPels( img.nativeData, x, y, w, h, icm.rgbs,
                               pixels, icm.trans, offset, scansize);
        img.stateChange( ImageObserver.SOMEBITS, x, y, w, h);
    }
    else {
        System.err.println("Unhandled colorModel: " + model.getClass());        
    }
    
}

public void setPixels ( int x, int y, int w, int h, ColorModel model, int pixels[], 
int offset, int scansize ) {
        if ( img.nativeData == null ) {
                // producer trouble, we haven't got dimensions yet
            return;
        }

        if ( model instanceof DirectColorModel ) {
            // in case our pels aren't default RGB yet, convert them using the 
ColorModel
            if ( model != ColorModel.getRGBdefault() ){
                int xw = x + w;
                int yh = y + h;
                int i, j, idx;
                int i0 = y * scansize + offset;
                for ( j = y; j < yh; j++, i0 += scansize ) {
                    for ( i = x, idx = i+i0; i < xw; i++, idx++) {
                        // are we allowed to in-situ change the array?
                        pixels[idx] = model.getRGB( pixels[idx]);
                    }
                }
            }
            
            Toolkit.imgSetRGBPels( img.nativeData, x, y, w, h, pixels, offset, 
scansize);
            img.stateChange( ImageObserver.SOMEBITS, x, y, w, h);
        }
        else {
            System.out.println("Unhandled colorModel: " + model.getClass());
        }
}

public void setProperties ( Hashtable properties ) {
    img.props = properties;
    img.stateChange( img.flags | ImageObserver.PROPERTIES, 0, 0, img.width, 
img.height);
}

ImageFrameLoader ( Image img ) {
        super("ImageFrameLoader");
        this.img = img;

        img.flags |= Image.BLOCK_FRAMELOADER;
        img.producer.startProduction( this );

        setPriority( NORM_PRIORITY - 3);
        start();
}

public void run () {

        // Note that we get started *after* the first SINGLEFRAMEDONE, i.e. our image 
observers
        // already got the preceeding dimension notification

        if ( img.producer instanceof ImageNativeProducer ) {
                runINPLoop();
        }
        else {
        }
}

public void runINPLoop () {
        int w, h, latency;
        Ptr ptr;

        // we already have the whole thing physically read in, so just start to notify 
round-robin. We also
        // got the first frame propperly reported, i.e. we start with flipping to the 
next one
        do {
          // wait until we get requested the next time (to prevent being spinned 
around by a MediaTracker)
                synchronized ( img ) {
                        try {
                                while ( (img.flags & Image.BLOCK_FRAMELOADER) != 0 ){
                                        img.wait();
                                }
                        } catch ( InterruptedException _ ) {}
                }
                latency = Toolkit.imgGetLatency( img.nativeData);
                try { Thread.sleep( latency); } catch ( Exception _ ) {}

                if ( (ptr = Toolkit.imgGetNextFrame( img.nativeData)) == null )

                        break;
                img.nativeData = ptr;
                w = Toolkit.imgGetWidth( img.nativeData);
                h = Toolkit.imgGetHeight( img.nativeData);
                if ( (img.width != w) || (img.height != h) ){
                        img.width = w;
                        img.height = h;
                        img.stateChange( ImageObserver.WIDTH|ImageObserver.HEIGHT, 0, 
0, img.width, img.height);
                }

                img.flags |= Image.BLOCK_FRAMELOADER;
                img.stateChange( ImageObserver.FRAMEBITS, 0, 0, img.width, img.height);

        } while ( img.observers != null );
}
}

class ImageLoader
  implements ImageConsumer, Runnable
{
        Image queueHead;
        Image queueTail;
        Image img;
        static ImageLoader asyncLoader;
        static ImageLoader syncLoader = new ImageLoader();

public synchronized void imageComplete ( int status ) {
        int s = 0;

        if ( status == STATICIMAGEDONE ){
          s = ImageObserver.ALLBITS;
                // give native layer a chance to do alpha channel reduction
                if ( !(img.producer instanceof ImageNativeProducer) )
                        Toolkit.imgComplete( img.nativeData, status);
        }
        else if ( status == SINGLEFRAMEDONE ) {
                s = ImageObserver.FRAMEBITS;

                // This is a (indefinite) movie production - move it out of the way 
(in its own thread)
                // so that we can go on with useful work. Note that if our producer 
was a ImageNativeProducer,
                // the whole external image has been read in already (no IO required, 
anymore)
                new ImageFrameLoader(img);
        }
        else {
                if ( (status & IMAGEERROR) != 0 )       s |= ImageObserver.ERROR;
                if ( (status & IMAGEABORTED) != 0 )     s |= ImageObserver.ABORT;
        }

        img.stateChange( s, 0, 0, img.width, img.height);

        // this has to be called *after* a optional ImageFrameLoader went into action, 
since
        // the producer might decide to stop if it doesn't have another consumer
        img.producer.removeConsumer( this);
        
        img = null;     // we are done with it, prevent memory leaks
        if ( this == asyncLoader )
                notify();     // in case we had an async producer
}

static synchronized void load ( Image img ) {
        if ( asyncLoader == null ){
                asyncLoader = new ImageLoader();
                asyncLoader.queueHead = asyncLoader.queueTail = img;

                Thread t = new Thread( asyncLoader, "asyncLoader");
                t.setPriority( Thread.NORM_PRIORITY - 1);
                t.start();
        }
        else {
                if ( asyncLoader.queueTail == null ) {
                        asyncLoader.queueHead = asyncLoader.queueTail = img;
                }
                else {
                        asyncLoader.queueTail.next = img;
                        asyncLoader.queueTail = img;
                }
                
                ImageLoader.class.notify();
        }
}

static void loadSync( Image img ) {
        synchronized ( syncLoader ) {
                syncLoader.img = img;
                img.producer.startProduction(syncLoader);
        }
}

public void run () {
        for (;;) {
                synchronized ( ImageLoader.class ) {
                        if ( queueHead != null ) {
                                img = queueHead;
                                queueHead = img.next;
                                img.next = null;
                                if ( img == queueTail )
                                        queueTail = null;
                        }
                        else {
                                try {
                                        ImageLoader.class.wait( 20000);
                                        if ( queueHead == null ) {
                                                // Ok, we waited for too long, lets do 
suicide
                                                asyncLoader = null;
                                                return;
                                        }
                                        else {
                                                continue;
                                        }
                                }
                                catch ( InterruptedException xx ) { 
xx.printStackTrace(); }
                        }
                }
                
                try {
                        // this is hopefully sync, but who knows what kinds of 
producers are out there
                        img.producer.startProduction( this);

                        if ( img != null ) {
                                synchronized ( this ){
                                        wait();
                                }
                        }
                }
                catch ( Throwable x ) {
                        x.printStackTrace();
                        imageComplete( IMAGEERROR | IMAGEABORTED);
                }
        }
}

public void setColorModel ( ColorModel model ) {
        // No way to pass this to ImageObservers. Since we also get it in setPixels, we
        // just ignore it
}

public void setDimensions ( int width, int height ) {
        img.width = width;
        img.height = height;

        // If we were notified by a ImageNativeProducer, the nativeData field is 
already
        // set. In case this is just an arbitrary producer, create it so that we have a
        // target for subsequent setPixel() calls
        if ( img.nativeData == null ){
                img.nativeData = Toolkit.imgCreateImage( width, height);
        }

        img.stateChange( ImageObserver.WIDTH|ImageObserver.HEIGHT, 0, 0, width, 
height);
}

public void setHints ( int hints ) {
        // we don't honor them
}

public void setPixels ( int x, int y, int w, int h,
                        ColorModel model, byte pixels[], int offset, int scansize ) {
        if ( img.nativeData == null ) {
                // producer trouble, we haven't got dimensions yet
                return;
        }

        if ( model instanceof IndexColorModel ) {
                IndexColorModel icm = (IndexColorModel) model;
                Toolkit.imgSetIdxPels( img.nativeData, x, y, w, h, icm.rgbs,
                                       pixels, icm.trans, offset, scansize);
                img.stateChange( ImageObserver.SOMEBITS, x, y, w, h);
        }
        else {
                System.err.println("Unhandled colorModel: " + model.getClass());
        }
}

public void setPixels ( int x, int y, int w, int h,
                        ColorModel model, int pixels[], int offset, int scansize ) {
        if ( img.nativeData == null ) {
                // producer trouble, we haven't got dimensions yet
                return;
        }

        if ( model instanceof DirectColorModel ) {
                // in case our pels aren't default RGB yet, convert them using the 
ColorModel
                if ( model != ColorModel.getRGBdefault() ){
                        int xw = x + w;
                        int yh = y + h;
                        int i, j, idx;
                        int i0 = y * scansize + offset;
                        for ( j = y; j < yh; j++, i0 += scansize ) {
                                for ( i = x, idx = i+i0; i < xw; i++, idx++) {
                                        // are we allowed to in-situ change the array?
                                        pixels[idx] = model.getRGB( pixels[idx]);
                                }
                        }
                }

                Toolkit.imgSetRGBPels( img.nativeData, x, y, w, h, pixels, offset, 
scansize);
                img.stateChange( ImageObserver.SOMEBITS, x, y, w, h);
        }
        else {
                System.out.println("Unhandled colorModel: " + model.getClass());
        }
}

public void setProperties ( Hashtable properties ) {
        img.props = properties;
  img.stateChange( img.flags | ImageObserver.PROPERTIES, 0, 0, img.width, img.height);
}
}

/**
 * This shouldn't be a inner class since you can easily grab the source of an
 * image and use it outside of this image (e.g. to create other images - whatever
 * it might be good for)
 */
class ImageNativeProducer
  implements ImageProducer
{
        Object consumer;
        Object src;
        int off;
        int len;

ImageNativeProducer ( Image img ) {
        src = img;
}

ImageNativeProducer ( Image img, File file ) {
        src = file;

        // check if we can produce immediately
        if ( file.exists() ) {
                if  ( file.length() < Defaults.FileImageThreshold ){
                  img.flags |= Image.PRODUCING;
                        synchronized ( ImageLoader.syncLoader ) {
                                ImageLoader.syncLoader.img = img;
                                img.producer = this;
                                startProduction( ImageLoader.syncLoader);
                        }
                }
        }
        else {
                img.flags = ImageObserver.ERROR | ImageObserver.ABORT;
        }
}

ImageNativeProducer ( Image img, byte[] data, int off, int len ) {
        src = data;
        this.off = off;
        this.len = len;
        
        if ( len < Defaults.DataImageThreshold ) {
          img.flags |= Image.PRODUCING;
                synchronized ( ImageLoader.syncLoader ) {
                        ImageLoader.syncLoader.img = img;
                        img.producer = this;
                        startProduction( ImageLoader.syncLoader);
                }
        }
}

ImageNativeProducer ( URL url ) {
        src = url;
}

public void addConsumer ( ImageConsumer ic ) {
        if ( consumer == null ){
                consumer = ic;
        }
        else if ( this.consumer instanceof Vector ) {
                ((Vector)consumer).addElement( ic);
        }
        else {
                Vector v = new Vector(3);
                v.addElement( consumer);
                v.addElement( ic);
                consumer = v;
        }
}

void imageComplete ( int flags ){
        if ( consumer instanceof ImageConsumer ){
                ((ImageConsumer)consumer).imageComplete( flags);
        }
        else if ( consumer instanceof Vector) {
                Vector v = (Vector) consumer;
                int i, n = v.size();
                for ( i=0; i<n; i++ ){
                        ((ImageConsumer)v.elementAt( i)).imageComplete( flags);
                }
        }
}

public boolean isConsumer ( ImageConsumer ic ) {
        if ( consumer instanceof ImageConsumer )
                return (consumer == ic);
        else if ( consumer instanceof Vector )
                return ((Vector)consumer).contains( ic);
        else
                return false;
}

void produceFrom ( File file ) {
        Ptr ptr;

        if ( file.exists() &&
             (ptr = Toolkit.imgCreateFromFile( file.getAbsolutePath())) != null ){
                produceFrom( ptr);
        }
        else {
                imageComplete( ImageConsumer.IMAGEERROR | ImageConsumer.IMAGEABORTED);
        }
}

void produceFrom ( Ptr ptr ) {
        if ( consumer instanceof ImageLoader ) {
                ImageLoader loader = (ImageLoader)consumer;
                Image img = loader.img;
        
                img.nativeData = ptr;
                img.width = Toolkit.imgGetWidth( ptr);
                img.height = Toolkit.imgGetHeight( ptr);

                loader.setDimensions( img.width, img.height);
                loader.imageComplete( Toolkit.imgIsMultiFrame( ptr) ?
                                           ImageConsumer.SINGLEFRAMEDONE : 
ImageConsumer.STATICIMAGEDONE);
        }
        else {
                Toolkit.imgProduceImage( this, ptr);
                Toolkit.imgFreeImage( ptr);
        }
}

void produceFrom ( URL url ) {
        Ptr    ptr;
        byte[] buf = new byte[1024];
        int    n;

        // since this is most likely used in a browser context (no file
        // system), the only thing we can do (in the absence of a suspendable
        // native image production) is to temporarily store the data in
        // memory. Note that this is done via kaffe.io.AccessibleBAOStream,
        // to prevent the inacceptable memory consumption duplication of
        // "toByteArray()".
        // Ideally, we would have a suspendable image production (that can
        // deal with reading and processing "incomplete" data), but that
        // simply isn't supported by many native image conversion libraries.
        // Some could be done in Java (at the expense of a significant speed
        // degradation - this is the classical native functionality), but
        // things like Jpeg ?
        try {
                InputStream in = url.openStream();
                if ( in != null ) {
                        AccessibleBAOStream out = new AccessibleBAOStream(8192);
                        while ((n = in.read(buf)) >= 0) {
                                out.write(buf, 0, n);
                        }
                        in.close();
                        if ( (ptr = Toolkit.imgCreateFromData(out.getBuffer(), 0, 
out.size())) != null ){
                                produceFrom( ptr);
                                return;
                        }
                }
        }
        catch ( Exception x ) {}

        imageComplete( ImageConsumer.IMAGEERROR|ImageConsumer.IMAGEABORTED);
}

void produceFrom ( byte[] data, int off, int len ) {
        Ptr ptr;

        if ( (ptr = Toolkit.imgCreateFromData( data, off, len)) != null )
                produceFrom( ptr);
        else
                imageComplete( ImageConsumer.IMAGEERROR | ImageConsumer.IMAGEABORTED);
}

public void removeConsumer ( ImageConsumer ic ) {
        if ( consumer == ic ){
                consumer = null;
        }
        else if ( consumer instanceof Vector ) {
                Vector v = (Vector) consumer;           
                v.removeElement( ic);
                if ( v.size() == 1 )
                        consumer = v.elementAt( 0);
        }
}

public void requestTopDownLeftRightResend ( ImageConsumer consumer ) {
        // ignored
}

void setColorModel ( ColorModel model ){
        if ( consumer instanceof ImageConsumer ){
                ((ImageConsumer)consumer).setColorModel( model);
        }
        else if ( consumer instanceof Vector) {
                Vector v = (Vector)consumer;
                int i, n = v.size();
                for ( i=0; i<n; i++ ){
                        ((ImageConsumer)v.elementAt( i)).setColorModel( model);
                }
        }
}

void setDimensions ( int width, int height ){
        if ( consumer instanceof ImageConsumer ){
                ((ImageConsumer)consumer).setDimensions( width, height);
        }
        else if ( consumer instanceof Vector) {
                Vector v = (Vector)consumer;
                int i, n = v.size();
                for ( i=0; i<n; i++ ){
                        ((ImageConsumer)v.elementAt( i)).setDimensions( width, height);
                }
        }
}

void setHints ( int hints ){
        if ( consumer instanceof ImageConsumer ){
                ((ImageConsumer)consumer).setHints( hints);
        }
        else if ( consumer instanceof Vector) {
                Vector v = (Vector)consumer;
                int i, n = v.size();
                for ( i=0; i<n; i++ ){
                        ((ImageConsumer)v.elementAt( i)).setHints( hints);
                }
        }
}

void setPixels ( int x, int y, int w, int h,
                       ColorModel model, int pixels[], int offset, int scansize ) {
        if ( consumer instanceof ImageConsumer ){
                ((ImageConsumer)consumer).setPixels( x, y, w, h, model, pixels, 
offset, scansize);
        }
        else if ( consumer instanceof Vector) {
                Vector v = (Vector)consumer;
                int i, n = v.size();
                for ( i=0; i<n; i++ ){
                        ((ImageConsumer)v.elementAt( i)).setPixels( x, y, w, h,
                                                                    model, pixels, 
offset, scansize);
                }
        }
}

public void startProduction ( ImageConsumer ic ) {
        addConsumer( ic);

        if ( src instanceof File )
                produceFrom( (File)src);
        else if ( src instanceof URL )
                produceFrom( (URL)src);
        else if ( src instanceof byte[] )
                produceFrom( (byte[])src, off, len);
        else if ( src instanceof Image ) {
                Toolkit.imgProduceImage( this, ((Image)src).nativeData);
        }
        else
                System.err.println( "unsupported production source: " + 
src.getClass());
                
        removeConsumer( ic);
}
}



import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.lang.Math;
import java.lang.Integer;
import java.util.Random;

public
class plasm extends Applet implements Runnable

{

    Thread plasmThread;

    int [] plasmarray;
    int pwidth;
    int pheight;
    int xmove;
    int ymove;
    int plasm_overflow;



        MemoryImageSource bgsource;
    int [] bgarray;
    int bgwidth;
    int bgheight;

    int bgcolor;

    Image bgimage;


    public void init()

    {

        String spof = getParameter("PLASM_OVERFLOW");
        String saw = getParameter("APPLET_WIDTH");
        String sah = getParameter("APPLET_HEIGHT");
        String spw = getParameter("PLASMA_WIDTH");
        String sph = getParameter("PLASMA_HEIGHT");
        String sxm = getParameter("MOVEX");
        String sym = getParameter("MOVEY");
        String bgc = getParameter("BGCOLOR");

        plasm_overflow = (spof != null) ? Integer.parseInt(spof) : 250;
        bgwidth = (saw != null) ? Integer.parseInt(saw) : 200;
        bgheight = (sah != null) ? Integer.parseInt(sah) : 180;
        pwidth = (spw != null) ? Integer.parseInt(spw) : 120;
        pheight = (sph != null) ? Integer.parseInt(sph) : 80;
        xmove = (sxm != null) ? Integer.parseInt(sxm) : 30;
        ymove = (sym != null) ? Integer.parseInt(sym) : 30;
        bgcolor = (bgc != null) ? Integer.parseInt(bgc) : 0;
        bgcolor = bgcolor | 0xff000000;

        setLayout(null);
        setBackground (Color.black);

        bgarray=new int [bgwidth*bgheight];

        plasmarray=new int [pwidth*pheight];

        generatePlasm(plasmarray,pwidth,pheight);
        bgsource=new MemoryImageSource(bgwidth, bgheight, bgarray, 0, bgwidth);
        bgsource.setAnimated(true);
        bgimage = createImage( bgsource );

        }





    public void generatePlasm(int [] _parray, int _w, int _h )
    {


        int wert;
        double yfak, xfak;
        double dPI = 2*Math.PI;

        for ( int x=0 ; x < _w/2 ; x++ ) {
            for ( int y=0 ; y < _h/2 ; y++) {

            xfak = 1 - Math.cos(dPI * x / _w );
            yfak = 1 - Math.cos(dPI * y / _h );

            wert = (int) (68 * xfak * yfak) ;
            wert = (wert > 255) ? 255 : wert;

            _parray [ x + y*_w ]= _parray [ (_w-x-1) + y*_w ] = _parray [ x + 
(_h-y-1)*_w ] = _parray [ (_w-x-1) + (_h-y-1)*_w ]= wert;
            }
        }

    }


    public void start() {

        if (plasmThread == null )
            {
            plasmThread=new Thread(this);
            plasmThread.start();
            }
        }

    public void stop()
    {
        if (plasmThread != null)
            {

            plasmThread.stop();
            plasmThread = null;
        }
    }


    public void run() {

    int x[][] = new int [360][3];
    int y[][] = new int [360][3];


    int c=0;
    int x0 = (bgwidth/2) - (pwidth/2);
    int y0 = (bgheight/2) - (pheight/2);

    double fak = Math.PI/180;
    double fak3= 3*fak;

    Thread me = Thread.currentThread();


        for (int i=0; i < 360 ; i++) {

            x[i][0]= x0+(int) (Math.sin(i*fak3)*xmove);
            y[i][0]= y0+(int) (Math.cos(i*fak)*Math.sin(i*fak)*ymove);

            x[i][1]= x0+(int) (Math.cos(i*fak3)*xmove);
            y[i][1]= y0+(int) (Math.cos(i*fak3)*Math.sin(i*fak)*ymove);

            x[i][2]= x0+(int) (Math.sin(i*fak)*Math.cos(i*fak)*xmove);
            y[i][2]= y0+(int) (Math.sin(i*fak3)*ymove);

        }



    do {
        paint(getGraphics());

        try {
            me.sleep(20);
        } catch (InterruptedException e) {
            break;
  
        }

        c = (c+2)%360;

        clearbackground();
        drawRGPlasma(x[c][0],y[c][0]);
        drawGBPlasma(x[c][1],y[c][1]);
        drawRBPlasma(x[c][2],y[c][2]);
        bgsource.newPixels();
     } while (true);

    }


    public void clearbackground() {

        for (int i=0; i < bgwidth*bgheight ; i++) {
            bgarray[i]=bgcolor;
        }
        }


    public void drawGBPlasma(int _x, int _y)
    {


            int r,g,b,p;

        int xs,xe,ys,ye;

        xs = (_x >= 0) ? 0 : -_x;
        ys = (_y >= 0) ? 0 : -_y;
        xe = (_x + pwidth < bgwidth) ? pwidth : (bgwidth - _x);
        ye = (_y + pheight < bgheight) ? pheight : (bgheight - _y);

            for (int x=xs ; x < xe ; x++) {
                for (int y=ys ; y < ye ; y++) {

                p = plasmarray[x+y*pwidth];

            r = bgarray[ x + _x + (y + _y) * bgwidth] ;
            g = (r & 0xff00) >> 8;
            b = r & 0xff;
            r = r & 0xff0000;

            g+=p;
            b+=p;

            g = (g>plasm_overflow) ? 255 : g;
            b = (b>plasm_overflow) ? 255 : b;

            bgarray[ x + _x + (y + _y)*bgwidth] = 0xff000000 | r | (g<<8) |  b;
                }
        }
    }

    public void drawRGPlasma(int _x, int _y)
    {
        int xs,xe,ys,ye;
        int r,g,b,p;

        xs = (_x >= 0) ? 0 : -_x;
        ys = (_y >= 0) ? 0 : -_y;
        xe = (_x + pwidth < bgwidth) ? pwidth : (bgwidth - _x);
        ye = (_y + pheight < bgheight) ? pheight : (bgheight - _y);

            for (int x=xs ; x < xe ; x++) {
                for (int y=ys ; y < ye ; y++) {

                p = plasmarray[x+y*pwidth];

            r = bgarray[ x + _x + (y+_y)*bgwidth] ;
            g = (r & 0xff00) >> 8;
            b = r & 0xff;
            r = (r >> 16) & 0xff;

            r+=p;
            g+=p;

            g = (g>plasm_overflow) ? 255 : g;
            r = (r>plasm_overflow) ? 255 : r;

            bgarray[ x + _x + (y+_y)*bgwidth] = 0xff000000 | (r<<16) | (g<<8) |  b;
                }
        }
    }

    public void drawRBPlasma(int _x, int _y)
    {
            int r,g,b,p;
        int xs,xe,ys,ye;

        xs = (_x >= 0) ? 0 : -_x;
        ys = (_y >= 0) ? 0 : -_y;
        xe = (_x + pwidth < bgwidth) ? pwidth : (bgwidth - _x);
        ye = (_y + pheight < bgheight) ? pheight : (bgheight - _y);

            for (int x=xs ; x < xe ; x++) {
                for (int y=ys ; y < ye ; y++) {

                p = plasmarray[x+y*pwidth];

            r = bgarray[ x + _x + (y+_y)*bgwidth] ;
            g = (r & 0xff00);
            b = r & 0xff;
            r = ( r>>16 ) & 0xff;

            r+=p;
            b+=p;

            r = (r>plasm_overflow) ? 255 : r;
            b = (b>plasm_overflow) ? 255 : b;

            bgarray[ x + _x + (y+_y)*bgwidth] = 0xff000000 | (r << 16 ) | g |  b;
                }
        }
    }

    public synchronized void paint(Graphics g) {

        g.drawImage(bgimage,0,0,bgwidth,bgheight, Color.black, this);

        }

        public synchronized void update(Graphics g) {

        g.drawImage(bgimage,0,0,bgwidth,bgheight, Color.black, this);
        g.setColor(Color.white);
        // g.drawString("(c) 1998 eto",5,bgheight-5);


        }




}


Reply via email to