?
Solved

RGBImageFilter

Posted on 2005-03-08
5
Medium Priority
?
339 Views
Last Modified: 2012-06-27
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;
        }      
    }    
}
0
Comment
Question by:lomidien
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
5 Comments
 
LVL 92

Expert Comment

by:objects
ID: 13491344
>    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
0
 

Author Comment

by:lomidien
ID: 13491409
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
0
 
LVL 92

Accepted Solution

by:
objects earned 2000 total points
ID: 13491505
I think createImage() actually works asynchronously so the image may not have been completed when you are painting it to the screen. So filtering it in your paint() method probably won't work.
Instead try painting and filtering your image in your thread.

0
 

Author Comment

by:lomidien
ID: 13491507
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);
0
 

Author Comment

by:lomidien
ID: 13491520
Same post time.  I'll try your suggestion....and thanks again!
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
In this post we will learn different types of Android Layout and some basics of an Android App.
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.
This video teaches viewers about errors in exception handling.
Suggested Courses
Course of the Month11 days, 16 hours left to enroll

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question