Link to home
Start Free TrialLog in
Avatar of lomidien
lomidien

asked on

RGBImageFilter

I'm using double-buffering in my applet to paint my image to an offscreen image before posting to the screen.  After the offscreen image is assembled, I'm running it through an RGBImageFilter in order to change the pixel values to greyscale.  I've attached the whole code below, but the RGBImageFilter code is at the bottom if that is all you need.  It seems as though the image is not being filtered at all, however, my animated box disappears if I'm using that method on the offscreen image.  If I remove the call to the filter, the image animates correctly.

I can change the method which alters the pixel value...for instance, to swap blue and red values and then the animatin works again and the screen changes, however the code to change the pixel values to greyscale do nothing except make the animation disappear.

Thanks,
David

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;

import java.awt.image.RGBImageFilter;

public class GameApplet extends Applet implements Runnable, KeyListener {
    public boolean paused = false;
    private int maxWidth , maxHeight ; // animation boundary
    private int currX , currY ; // left,top (x,y) of the animating rectangle
    private int currXVelocity , currYVelocity ; // pixels per move
    private int imageHeight , imageWidth ; // size of animating rectangle
   
    // new stuff for dbl-buffering
    Graphics offscreen ;
    Image imageForOffscreen ;
   
    // This method is called once by the browser when it starts the applet.
    public void init() {
       
        this.addKeyListener(this); //add keylistener to trap P key
       
        Color c = Color.blue;
        setBackground(c) ;
        maxWidth = 500 ;
        maxHeight = 500 ;
        imageHeight = 25 ;
        imageWidth = 40 ;
        currXVelocity = 3 ;
        currYVelocity = 3 ;
   
        // set up random positions to start the images
        currX = (int)( ( Math.random() * 80 ) + 1 );
        currY = (int)( ( Math.random() * 80 ) + 10 );
   
        // new stuff for dbl-buffering
        imageForOffscreen = createImage( maxWidth , maxHeight );
        offscreen = imageForOffscreen.getGraphics();
   
        Thread animator = new Thread( this );
        animator.start();
       
       
    }
   
    // This method is called whenever the page containing this applet is made visible.
    public void start() {      
    }    
    // This method is called whenever the page containing this applet is not visible.
    public void stop() {
    }    
    // This method is called once when the browser destroys this applet.
    public void destroy() {
    }    
    // Runnable contract
    public void run() {
        // Generic Game Loop
        while ( !paused )
        {
            try
            {
                Thread.sleep( 50 );
            }
            catch ( InterruptedException e )
            {
            }
            currX = currX + currXVelocity ;
            currY = currY + currYVelocity ;
   
            if ( ( currX + imageWidth ) >= maxWidth )
            {
                currXVelocity = -3 ;
            }
            else if ( currX <= 0 )
            {
                currXVelocity = 3 ;
            }  
           
            if ( ( currY + imageHeight ) >= maxHeight )
            {
                currYVelocity = -3 ;
            }
            else if ( currY <= 0 )
            {
                currYVelocity = 3 ;
            }    
            repaint();
        }
    }
   
    // This method is called whenever this applet needs to repaint itself.
    public void paint(Graphics g) {
       
        // first do what the update would have done --
        //erase the background of the offscreen Graphics surface
        offscreen.setColor( getBackground() );
        offscreen.fillRect( 0 ,0 ,maxWidth , maxHeight );
   
        // paint the rectangle onto the offscreen surface
        // If there were more images to be painted, it would
        // all happen here. Paint ALL images at this step
        offscreen.setColor( Color.black );
        offscreen.drawRect( currX , currY , imageWidth , imageHeight );
       
        // Create the filter
        ImageFilter filter = new GetRedFilter();
        FilteredImageSource filteredSrc = new FilteredImageSource(imageForOffscreen.getSource(), filter);

        // Create the filtered image
        imageForOffscreen = Toolkit.getDefaultToolkit().createImage(filteredSrc);
           
        // then blast that final image to the screen
        g.drawImage( imageForOffscreen , 0 , 0 , this );

    }
   
    // override update to prevent it from erasing the background
    public void update( Graphics g ) {
        paint( g );
    }
       
    // KeyListener contract
    public void keyTyped(KeyEvent e) {
       
    }
    public void keyReleased(KeyEvent e) {
       
    }
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
       
        //change paused status
        if(key == KeyEvent.VK_P) {
            if(paused){
                paused = false;
                //restart game loop
                Thread animator = new Thread( this );
                animator.start();
            }
            else if(!paused){
                paused = true;
            }
            //force repaint
            this.repaint();
        }
    }
   
    // This filter removes all but the red values in an image
    class GetRedFilter extends RGBImageFilter {
        public GetRedFilter() {
            // work with pixels whose indices are into a color table
            canFilterIndexColorModel = true;
        }
       
        public int filterRGB(int x, int y, int rgb) {
                                   
            int r = (rgb & 0x00ff0000) >> 16;
            int g = (rgb & 0x0000ff00) >> 8;
            int b = (rgb & 0x000000ff);

            rgb = (int) (0.2989*r + 0.5870*g + 0.1140*b);  // NTSC formula
           
            if (x == -1) {
                // The pixel value is from the image's color table rather than the image itself
            }
            // Return only the red component
            return rgb;
        }      
    }    
}
Avatar of Mick Barry
Mick Barry
Flag of Australia image

>    rgb = (int) (0.2989*r + 0.5870*g + 0.1140*b);  // NTSC formula

try:

   rgb = (int) (0.2989*(double)r + 0.5870*(double)g + 0.1140*(double)b);  // NTSC formula
Avatar of lomidien
lomidien

ASKER

Ok, I made that change and it appears to be doing the same as before.  I.E. no pixel color changes and the animation is still not visible.  I'm really wondering why the call to the filter eliminates my animation, however does not do anything else.  hmmm

No errors are reported and the code executes just fine....just with undesired results.  :(

And thanks for your suggestion to try image filtering....it set me off in the hunt through the api and got me to this point.


Thanks,
David
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
Objects, thanks for all your help in this matter...spanning a week or more!  

I'm posting below the altered code which appears to work as I need.  I'll test it with a more advanced picture, but it works for this example.

David


The following code works in place of the filterRGB method posted above:

// find out the red, green and blue color components
            int r = (rgb >> 16) & 0xff;
            int g = (rgb >> 8)  & 0xff;
            int b = (rgb)       & 0xff;

            // calculate the grayscale value
            int gray = (r*30 + g*59 + b*11)/100;

            // return the color code of the new color
            return (rgb & 0xff000000) | (gray<<16) | (gray<<8) | (gray);
Same post time.  I'll try your suggestion....and thanks again!