Link to home
Start Free TrialLog in
Avatar of lar_jens
lar_jens

asked on

IE JVM Problems

I have created an applet that does this sinusoidal wave thing on an image.

I have three classes in my system:

class WaveApplet extends Applet implements Runnable
class WaveFilter extends ImageFilter
class ImageProcessor

The WaveFilter is responsible for altering the image so that it's shape changes, and this filter also contains a frame number, so that it can generate an animation sequence of the image.

This works fine on the appletviewer.

On Internet Explorer, however, I get the correct effect on frames 0-5 and then on frames 6,11,21,26,31,36 and so on, the image does not change shape (i.e. into a sinus shaped image).

What is it that I do wrong here? Is there something wrong with the Java Virtual Machine on iexplore?

Avatar of heyhey_
heyhey_

can you post your code ?
Avatar of lar_jens

ASKER

Here's the code (classes delimited by hyphens)
--------------------------------------------------------
package WaveApplet;

import java.awt.*;
import java.awt.image.*;
import java.applet.*;

public class WaveApplet extends Applet implements Runnable {

      private Image raw_image;
      private Image image;
      private Image double_buffer[];
      private Rectangle bounds;
      private int frame;
      private int buffer;
      private Thread thread;
      
      public void renderImage() {
                  frame += 2;
                  WaveFilter waveFilter = new WaveFilter();
                  waveFilter.prepareFrame(frame);
                  ImageProducer imageProducer = raw_image.getSource();
                  FilteredImageSource filteredImageSource = new FilteredImageSource(imageProducer, waveFilter);
                  image = createImage(filteredImageSource);
                  ImageProcessor.completeCreation(this, image);
                  repaint();
      }

      public void init() {
      
            raw_image = getImage(getCodeBase(), getParameter("Image"));

            if (raw_image != null) {

                  frame = 0;
                  bounds = getBounds();
                  double_buffer = new Image[2];
                  double_buffer[0] = createImage(bounds.width, bounds.height);
                  double_buffer[1] = createImage(bounds.width, bounds.height);
                  buffer = 0;
                  ImageProcessor.completeCreation(this, raw_image);
            }
      }

      public void paint(Graphics g) {
            if (image != null) g.drawImage(image, 0, 0, null);
            g.setColor(Color.white);
      }

      public void update(Graphics g) {
            paint(double_buffer[buffer].getGraphics());
            buffer = (buffer == 0) ? 1 : 0;
            g.drawImage(double_buffer[buffer], 0, 0, null);
      }
 
      public void start() {
            thread = new Thread(this);
            thread.start();
      }
      
      public void stop() {
            thread = null;
      }

      public void run() {

            Thread currentThread = Thread.currentThread();
            while (thread == currentThread) {
                  
                  try {
                        currentThread.sleep(20);
                        renderImage();
                  }
                  
                  catch (InterruptedException exception) {
                        System.out.println("!!Interrupted exception caught!!");
                        showStatus(exception.toString());
                  }
            }
      }
}
--------------------------------------------------------
package WaveApplet;

import java.awt.*;
import java.awt.image.*;
import java.lang.Math;

class WaveFilter extends ImageFilter {
      private int width;
      private int height;
      private int frame;

      public WaveFilter() {
      }
      
      public void prepareFrame(int frame) {
            this.frame = frame;
      }
      
      public void setDimensions(int width, int height) {
            this.width = width;
            this.height = height;
            super.setDimensions(width, height);
      }
      
      public void setHints(int hint) {
            hint |= ImageConsumer.TOPDOWNLEFTRIGHT;
            super.setHints(hint);
      }
      
      public void setPixels(int x, int y, int width, int height,
            ColorModel model, byte pixels[], int offset, int scansize) {

            /*
            System.out.println(
                              "\nx        = " + x +
                              "\ny        = " + y +
                              "\nwidth    = " + width +
                              "\nheight   = " + height +
                              "\nmodel    = " + model +
                              "\noffset   = " + offset +
                              "\nscansize = " + scansize );
            */
            
            byte new_pixels[] = new byte[width * height];
            
            for ( int xc = 0; xc < width; xc++ ) {
                  
                  double changeOfY = (int)(25 * Math.sin(((double)xc/30.0) - 0.05f * frame));

                  for (int yc = 0; yc < height; yc++) {
                        
                        int oldY = (int)(yc + changeOfY);
                        
                        while (oldY<0) oldY += height;
                        while (oldY>=height) oldY -= height;
                        
                        // System.out.println("oldY = " + oldY);

                        new_pixels[xc + (yc*scansize) + offset] = pixels[xc + (oldY*scansize) + offset];
                  }
            }

            super.setPixels(x, y, width, height, model, new_pixels, offset, scansize);
      }

      public void setPixels(int x, int y, int width, int height,
            ColorModel model, int pixels[], int offset, int scansize) {

            /*
            System.out.println(
                              "\nx        = " + x +
                              "\ny        = " + y +
                              "\nwidth    = " + width +
                              "\nheight   = " + height +
                              "\nmodel    = " + model +
                              "\noffset   = " + offset +
                              "\nscansize = " + scansize );
            */
            
            int new_pixels[] = new int[width * height];
            
            for ( int xc = 0; xc < width; xc++ ) {
                  
                  int changeOfY = (int)(10 * Math.sin(((double)xc/30.0) - 0.05f * frame));

                  for (int yc = 0; yc < height; yc++) {
                        
                        int oldY = yc + changeOfY;
                        
                        while (oldY<0) oldY += height;
                        while (oldY>=height) oldY -= height;
                        
                        // System.out.println("oldY = " + oldY);

                        new_pixels[xc + (yc*scansize) + offset] = pixels[xc + (oldY*scansize) + offset];
                  }
            }
            
            super.setPixels(x, y, width, height, model, new_pixels, offset, scansize);
      }
}
--------------------------------------------------------
package WaveApplet;

import java.awt.*;
import java.awt.image.*;

class ImageProcessor {

      static void completeCreation(Component component, Image image) {

            MediaTracker mediaTracker = new MediaTracker(component);
            mediaTracker.addImage(image, 1);
            
            try {
                  mediaTracker.waitForID(1);
            }
            
            catch (Exception exception) {
                  exception.printStackTrace();
                  System.exit(0);
            }
      }
}
--------------------------------------------------------

Here's the code (classes delimited by hyphens)
--------------------------------------------------------
package WaveApplet;

import java.awt.*;
import java.awt.image.*;
import java.applet.*;

public class WaveApplet extends Applet implements Runnable {

      private Image raw_image;
      private Image image;
      private Image double_buffer[];
      private Rectangle bounds;
      private int frame;
      private int buffer;
      private Thread thread;
      
      public void renderImage() {
                  frame += 2;
                  WaveFilter waveFilter = new WaveFilter();
                  waveFilter.prepareFrame(frame);
                  ImageProducer imageProducer = raw_image.getSource();
                  FilteredImageSource filteredImageSource = new FilteredImageSource(imageProducer, waveFilter);
                  image = createImage(filteredImageSource);
                  ImageProcessor.completeCreation(this, image);
                  repaint();
      }

      public void init() {
      
            raw_image = getImage(getCodeBase(), getParameter("Image"));

            if (raw_image != null) {

                  frame = 0;
                  bounds = getBounds();
                  double_buffer = new Image[2];
                  double_buffer[0] = createImage(bounds.width, bounds.height);
                  double_buffer[1] = createImage(bounds.width, bounds.height);
                  buffer = 0;
                  ImageProcessor.completeCreation(this, raw_image);
            }
      }

      public void paint(Graphics g) {
            if (image != null) g.drawImage(image, 0, 0, null);
            g.setColor(Color.white);
      }

      public void update(Graphics g) {
            paint(double_buffer[buffer].getGraphics());
            buffer = (buffer == 0) ? 1 : 0;
            g.drawImage(double_buffer[buffer], 0, 0, null);
      }
 
      public void start() {
            thread = new Thread(this);
            thread.start();
      }
      
      public void stop() {
            thread = null;
      }

      public void run() {

            Thread currentThread = Thread.currentThread();
            while (thread == currentThread) {
                  
                  try {
                        currentThread.sleep(20);
                        renderImage();
                  }
                  
                  catch (InterruptedException exception) {
                        System.out.println("!!Interrupted exception caught!!");
                        showStatus(exception.toString());
                  }
            }
      }
}
--------------------------------------------------------
package WaveApplet;

import java.awt.*;
import java.awt.image.*;
import java.lang.Math;

class WaveFilter extends ImageFilter {
      private int width;
      private int height;
      private int frame;

      public WaveFilter() {
      }
      
      public void prepareFrame(int frame) {
            this.frame = frame;
      }
      
      public void setDimensions(int width, int height) {
            this.width = width;
            this.height = height;
            super.setDimensions(width, height);
      }
      
      public void setHints(int hint) {
            hint |= ImageConsumer.TOPDOWNLEFTRIGHT;
            super.setHints(hint);
      }
      
      public void setPixels(int x, int y, int width, int height,
            ColorModel model, byte pixels[], int offset, int scansize) {

            /*
            System.out.println(
                              "\nx        = " + x +
                              "\ny        = " + y +
                              "\nwidth    = " + width +
                              "\nheight   = " + height +
                              "\nmodel    = " + model +
                              "\noffset   = " + offset +
                              "\nscansize = " + scansize );
            */
            
            byte new_pixels[] = new byte[width * height];
            
            for ( int xc = 0; xc < width; xc++ ) {
                  
                  double changeOfY = (int)(25 * Math.sin(((double)xc/30.0) - 0.05f * frame));

                  for (int yc = 0; yc < height; yc++) {
                        
                        int oldY = (int)(yc + changeOfY);
                        
                        while (oldY<0) oldY += height;
                        while (oldY>=height) oldY -= height;
                        
                        // System.out.println("oldY = " + oldY);

                        new_pixels[xc + (yc*scansize) + offset] = pixels[xc + (oldY*scansize) + offset];
                  }
            }

            super.setPixels(x, y, width, height, model, new_pixels, offset, scansize);
      }

      public void setPixels(int x, int y, int width, int height,
            ColorModel model, int pixels[], int offset, int scansize) {

            /*
            System.out.println(
                              "\nx        = " + x +
                              "\ny        = " + y +
                              "\nwidth    = " + width +
                              "\nheight   = " + height +
                              "\nmodel    = " + model +
                              "\noffset   = " + offset +
                              "\nscansize = " + scansize );
            */
            
            int new_pixels[] = new int[width * height];
            
            for ( int xc = 0; xc < width; xc++ ) {
                  
                  int changeOfY = (int)(10 * Math.sin(((double)xc/30.0) - 0.05f * frame));

                  for (int yc = 0; yc < height; yc++) {
                        
                        int oldY = yc + changeOfY;
                        
                        while (oldY<0) oldY += height;
                        while (oldY>=height) oldY -= height;
                        
                        // System.out.println("oldY = " + oldY);

                        new_pixels[xc + (yc*scansize) + offset] = pixels[xc + (oldY*scansize) + offset];
                  }
            }
            
            super.setPixels(x, y, width, height, model, new_pixels, offset, scansize);
      }
}
--------------------------------------------------------
package WaveApplet;

import java.awt.*;
import java.awt.image.*;

class ImageProcessor {

      static void completeCreation(Component component, Image image) {

            MediaTracker mediaTracker = new MediaTracker(component);
            mediaTracker.addImage(image, 1);
            
            try {
                  mediaTracker.waitForID(1);
            }
            
            catch (Exception exception) {
                  exception.printStackTrace();
                  System.exit(0);
            }
      }
}
--------------------------------------------------------

I am kind of in hurry with this, so any help would be appreciated.
Avatar of rrz
Just a question until "heyhey" gets back.
Why do you have two of these methods?
> public void setPixels(int x, int y, int width, int height,
          ColorModel model, int pixels[], int offset, int scansize)


Ok, now I see that they do have differant signatures.Scratch that question. I did compile your code, but I can't get it to work yet. My image is displayed but I don't get waves( in IE6 ). Your thread is listed in the java console, so something is happening. Hopefully heyhey will help.
Have you checked the Java console for exceptions?
One possibility is that your running out of memory.

PS. You should not (cannot) call System.exit() in an applet.
I am not running out of memory or anything =) Windwos 2000 Task Manager has a stable memory usage. I did, however, change the run() method so that it slept for 1 ms instead of 20 ms. This caused some flickering in the appletviewer as well..

This lead me into thinking that the IE JVM is running a bit faster than the appletviewer. Maybe the MediaTracker doesn't do it's jobb of waiting properly when the image is filtered.

I've also tried to override the imageUpdate() method, so that I could se if it was called when the image was painted. The ImageObserver.ALLBITS flag was sent to the imageUpdate() method from time to time. This just strengthened my theory that the image is not done beeing created / filtered before it is painted.

What bothers me a bit about this, is that I have implemented a kind of double buffering in the update method. So theoretically, the flickering should not happen.

This is what I have done to get the applet running:

1. My disk folder structure is like the following :

...
-\ Software Development
 | WaveApplet.html
 -\ WaveApplet
  | WaveApplet.java
  | WaveApplet.class
  | WaveFilter.java
  | WaveFilter.class
  | ImageProcessor.java
  | ImageProcessor.class
...

2. The html file uses the <applet> tag like this :

<applet code="WaveApplet.WaveApplet.class" .... >

Oh I forgot..

The html file should also supply an image file.

<applet code="WaveApplet.WaveApplet.class" ....>
<param name=image value="someimage.gif">
</applet>
The JVM runs in its own memory space so it could still be possible for it to run out of memory without showing up in NT's usage.

Hang on while I get it running.


Seems to run ok here (IE5) , but it's a bit flickery.
objects - so you noticed.. =))

Read my question again, to se what my problem is all about.. -> The flickering.. *S*

It occurs in IE5, but not in the appletviewer. So I need to know why it flickers in IE5 and not in the appletviewer.
Has anyone figured out what it is yet..
I am about to give up, and write it all over again.. :(
I don't have any answers, but I got your program working in IE6. I see what you mean about the jumpy behavior when it gets to certain frames.I am using a 300x300 .gif with horizontal lines on it,with no noticable flicker.  I can't get it to wave in appletviewer(JDK1.3), it starts and the thread is running but no waves.
Give us more time. "objects and "heyhey" have a lot of expertise ( me,I am just a hack ).
I tried to change currentThread.sleep(20) to currentThread.sleep(1000) in the run() method of the applet. This will make perfectly clear what I mean about the strange behaviour of the IE JVM.

Every 5th frame is not run through the filter somehow.
I'm using JDK1.3 as well, an my appletviewer works.. This is odd.. ?!?!? I though java was the wave nature of computer science - it's non-localization =))
> Read my question again, to se what my problem
> is all about.. -> The flickering.. *S*

Your question does not mention flickering.
All it states is 'the image does not change shape'

>Every 5th frame is not run through the filter somehow.

I am not seeing that in my browser, seems closer to 50.
What I can see is that when the erratic behavior occurs the gc is doing its thing(I determined this by observing  the java console). This might explain the differences between what you see and what I observe. We probably have our MS-DOS memory set up differently.
At any rate, you are doing a lot of calculations and creating a lot of objects every time you call renderImage().  So, hopefully "objects" or "heyhey" will suggest a design that will work smoothly.
I think there's a problem with your WaveFilter class, it assumes that all the scanlines are being passed to it at one time. This is not the case, could be any number of scanlines.
And if the scanlines are passed to it one at a time, then no transformation will take place.

You might also want to have a look at creating a new pixel array everytime a bunch of pixels is transformed. Seems an unnecessary memory usage.
I am sorry about my last comment. I got to stay away from drugs, stop hallucinating and do more listening to the experts.
objects:

You said that no transformation will take place?
But I use two for loops that scans the width and the height of the image, thus transforming the whole image every time the function is called.

The documentation says that the pixels array contains all the pixels of the image to be transformed.
I've changed the setPixels methods to the following:

     public void setPixels(int x, int y, int w, int h,
          ColorModel model, byte pixels[], int offset, int scansize) {

          /*
          System.out.println(
                         "\nx        = " + x +
                         "\ny        = " + y +
                         "\nwidth    = " + width +
                         "\nheight   = " + height +
                         "\nmodel    = " + model +
                         "\noffset   = " + offset +
                         "\nscansize = " + scansize );
          */
         
          if ((x==0) && (y==0)) {
               new_byte_pixels = new byte[width * height];
          }
         
          for ( int xc = 0; xc < w; xc++ ) {
               
               double changeOfY = (int)(25 * Math.sin(((double)xc/30.0) - 0.05f * frame));

               for (int yc = 0; yc < h; yc++) {
                   
                    int oldY = (int)(yc + changeOfY);
                   
                    while (oldY<0) oldY += height;
                    while (oldY>=height) oldY -= height;
                   
                    // System.out.println("oldY = " + oldY);

                    new_byte_pixels[xc + (yc*scansize) + offset] = pixels[xc + (oldY*scansize) + offset];
               }
          }

          super.setPixels(x, y, w, h, model, new_byte_pixels, offset, scansize);
     }

Now this should take care of the situations where only one scanline is delivered at a time (if that is the problem), and also generetas a new pixel array only the first time of each transform.

But I STILL have incorrect behaviour in the IE JVM.
The appletviewer, however, still does it's thing all right.

Comments for above comment:

I have two arrays in the beginning of the class like this:

private int new_int_pixels[];
private byte new_byte_pixels[];

The creation of all the different objects in renderImage() was initially in another place. They have now been moved back to init().

The reason I moved them to renderImage() was to see if that was the cause of the flickering.

Can u post of email me your modified WaveFilter it's hard to keep track of were u are at.
> The documentation says that the pixels array contains
> all the pixels of the image to be transformed.

Which documentation are u referring 2?

> (if that is the problem)

Didn't say it was the problem, just said it possibly a problem :-)
Did u have joy getting your filter to work?

> The documentation says that the pixels array contains
> all the pixels of the image to be transformed.

I was thinking about this, and it doesn't make sense.
How can it pass the all the pixels if they have not been loaded yet?
And if it always passes all the pixels then why would it ever need to pass scanlines one at a time?

To objects:

I really can not see how your comments are helping me out here. ?!? Besides, I have rewritten the filter so that it takes the scanlines into consideration when filtering (see the last code I posted).

Why did you ask me wether or not I had joy getting my filter to work? (I do not understand that this has anything to do with solving the problem).

I do not mean to be sarcastic or anything. I just need to get my problem fixed.

To objects and everybody else:

Does anybody in here have any suggestions on how to solve this problem? I mean it works in about 60-90% of all the frames when run on Internet Explorer, and works ALWAYS in the appletviewer.

-LJJ
But your revised code still appears to assume that the pixel array passed to it contains all the pixels for the image which I believe it does not. Have you tried displaying the size of the 'pixels' array and checking the indexes that you are referencing within it.

I ran your new method here and the problem still appeared to be related to only single scanlines passed to it, causing the pixels array to accessed with invalid indexes.

I'm sorry that you feel I am not helping but I assure u that I'm trying to.

As auto-notification is currently down, feel free to contact me directly.

A good test would be to save each image frame to disk.
This would allow you to view each frame and determine if the problem is with the filter or with the displaying of the images.
> Why did you ask me wether or not I had joy getting my filter to work?

Because that is where I believe your problem is.
Here's a working wave filter:

class WaveFilter extends ImageFilter
{
   ColorModel defaultRGB = ColorModel.getRGBdefault();
   int amplitude, frequency, owidth, oheight, nheight;
   int sineArray[], intPixels[];
   int frame;
   
   public WaveFilter()
   {
      this(25,30);
   }
   
   public void prepareFrame(int frame)
   {
      this.frame = frame;
   }

   public WaveFilter(int amplitude, int frequency)
   {
      this.amplitude = amplitude;
      this.frequency = frequency;
   }

   public void setDimensions(int width, int height)
   {
      int x;
      owidth     = width;
      oheight    = height;
      nheight   = height+(amplitude*2);
      intPixels = new int[owidth * nheight];

      sineArray = new int[width];
      for(x=0; x < width; ++x) {
         sineArray[x] =
            ((int)(amplitude*Math.sin(((double)(x)) /
               ((double)frequency) - 0.05f * frame)));
      }
      consumer.setDimensions(width, nheight);
   }

   public void setHints(int hints)
   {
      int newHints = 0;
      consumer.setHints(newHints | SINGLEPASS);
   }

   public void setPixels(int x, int y, int w, int h,
                           ColorModel cm, int pixels[],
                           int offset, int scansize)
   {
      int index, destY, destIndex = 0;

      for(int row=0; row < h; row++) {
         for(int col=0; col < w; col++) {
            destY        = y + row + amplitude + sineArray[col];
            destIndex    = (destY*w) + x + col;
            index       = offset + row*scansize + col;

            intPixels[destIndex] = cm.getRGB(pixels[index]);
         }
      }
   }

   public void setPixels(int x, int y, int w, int h,
                              ColorModel cm, byte pixels[],
                              int offset, int scansize)
   {

      int index, destY, destIndex = 0;

      for(int row=0; row < h; row++) {
         for(int col=0; col < w; col++) {
            destY        = y + row + amplitude + sineArray[col];
            destIndex    = (destY*w) + x + col;
            index       = offset + row*scansize + col;

            intPixels[destIndex] =
               cm.getRGB(pixels[index] & 0x0ff);
         }
      }
   }
   
   public void imageComplete(int status)
   {
      if(status == IMAGEERROR || status == IMAGEABORTED)
      {
         consumer.imageComplete(status);
         return;
      }

      consumer.setPixels(0,0,owidth,nheight,
                        defaultRGB,intPixels,0,owidth);

      consumer.imageComplete(status);
   }
}
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Does that make sense 2u?
I geuss it must as you haven't asked any questions.
Always happy to help.
Sorry that I haven't replied here yet.. Work keeps me busy.. =)

You were right.. =) Thanx for all help..
No worries.
Thanks for the points  :)