×

Discussion Board

Results 1 to 10 of 10
  1. #1
    Registered User
    Join Date
    Aug 2009
    Posts
    6

    Mask a portion of an image on pointerPressed

    Hi,
    I'm rather new with J2ME... I need to mask a portion of an image, according to where the screen is touched by the user.
    I thought about drawing a circle (or using a png) on x,y which masks the image below.

    I don't even know if it's possible to make masks, actually, and I couldn't find any satysfying solution on the web...

    This is the effect I need to reproduce
    (sorry, it's in italian: click on the screen 4-5 times until the ghost is gone, then try drawing on the "dust": it will be wiped away).

    Thanks!
    Valentina

  2. #2
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Mask a portion of an image on pointerPressed

    Hmmm... you can certainly do this.

    One way to do it:

    Load the background image as one object... let's call this "image A".

    Create another Image object of the same size. Let's call this "image B".

    Draw "image A" onto "image B".

    Draw the "dust" on top of "image B".

    In the Canvas paint() method, draw "image B" onto the screen.

    When the Canvas is touched, copy the corresponding area of "image A" into "image B". This is easy with a square area, using drawRegion(). Several calls to drawRegion() could be used to produce a reasonable approximation of a circle. Then call repaint() to update the screen with the updated "image B".

    Does that help?

    Graham.

  3. #3
    Registered User
    Join Date
    Aug 2009
    Posts
    6

    Re: Mask a portion of an image on pointerPressed

    The idea seems very good!
    I'm trying to apply it, but for some reasons drawRegion() doesn't work...

    Any idea of where the problem is?

    Code:
     
    class IntroPresentazioni extends GameCanvas implements DataListener, Runnable {
        private final Image dust;
        private final Image new_bg;
        private int[] maskX = new int[100];
        private int[] maskY = new int[100];
        private int contaTocco = 0;
    
    [...]
    
    void draw() { // there's an animation thread, it repaints over and over ;)
    
    [...]
    
        graphics.drawImage(dust, 0, 0, Graphics.TOP | Graphics.LEFT);
        if (contaTocco > 0) {
             for (int i = 0; i <= contaTocco; i++) {
                  graphics.drawRegion(new_bg, maskX[i], maskY[i], 50, 50, Sprite.TRANS_NONE, maskX[i], maskY[i], Graphics.TOP | Graphics.LEFT);
             }
        }
    }
    
    
    public void pointerPressed(int Px, int Py) {
         maskX[contaTocco] = Px;
         maskY[contaTocco] = Py;
         ++contaTocco;
    }

    I'm pretty sure it's drawRegion() because I've tried to comment everything else (the arrays, the for cicle, the "dust" image) and those are not the problem ù_u
    If it's not enough code to know what's going on, please tell me!

    Thanks!

  4. #4
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Mask a portion of an image on pointerPressed

    Hmmm... nothing stands out as wrong. What exactly is the problem?

    Some things I notice:

    Quote Originally Posted by ellyna View Post
    Code:
    for (int i = 0; i <= contaTocco; i++) {
    That looks like it should be "<", not "<=" (which would also mean you can remove the enclosing "if").

    Quote Originally Posted by ellyna View Post
    Code:
    graphics.drawRegion(new_bg, maskX[i], maskY[i], 50, 50, Sprite.TRANS_NONE, maskX[i], maskY[i], Graphics.TOP | Graphics.LEFT);
    Watch out that the x,y,w,h don't cause you to draw off the edge of the image, or you'll get an IllegalArgumentException.

    Oh, I'd suggest you use Canvas, not GameCanvas, it's less problematic.

    I thought I'd try too, because it looks quite cool I came up with this:

    PHP Code:
    import javax.microedition.lcdui.*;
    import javax.microedition.lcdui.game.*;
    import javax.microedition.midlet.*;

    public class 
    Dusty extends MIDlet {
        private 
    Displayable d;
        
        public 
    void startApp() {
            if (
    == null) {
                try {
                    
    Image img Image.createImage("/Dusty.jpg");
                    
    = new DustCanvas(img);
                } catch (
    Exception e) {
                    
    Form f = new Form("Error");
                    
    f.append(e.toString());
                    
    f;
                }
            }
            
    Display.getDisplay(this).setCurrent(d);
        }

        public 
    void pauseApp() {
            
    // empty
        
    }

        public 
    void destroyApp(boolean must) {
            
    // empty
        
    }

        private static class 
    DustCanvas extends Canvas {
            private static final 
    int SIZE 25;
            private 
    int width;
            private 
    int height;
            private 
    Image background;
            private 
    Image foreground;
            
            public 
    DustCanvas(Image bg) {
                
    background bg;
                
    width bg.getWidth();
                
    height bg.getHeight();
                
    foreground Image.createImage(widthheight);
                
    Graphics g foreground.getGraphics();
                
    g.drawImage(bg00Graphics.LEFT Graphics.TOP);

                
    // paint "dust" on top of foreground - this is not an optimal implementation!
                
    int[] dust = new int[] { 0xc0808080 };
                for (
    int y 0heighty++) {
                    for (
    int x 0widthx++) {
                        
    g.drawRGB(dust01xy11true);
                    }
                }
            }
            
            protected 
    void paint(Graphics g) {
                
    g.drawImage(foreground00Graphics.LEFT Graphics.TOP);
            }

            protected 
    void pointerPressed(int xint y) {
                
    Graphics g foreground.getGraphics();

                
    int px SIZE;
                
    int py SIZE;
                
    int w SIZE 2;
                
    int h SIZE 2;
                if (
    px 0) {
                    
    += px;
                    
    px 0;
                }
                if (
    py 0) {
                    
    += py;
                    
    py 0;
                }
                if (
    px width) {
                    
    width px;
                }
                if (
    py height) {
                    
    height py;
                }

                
    g.drawRegion(backgroundpxpywhSprite.TRANS_NONEpxpyGraphics.LEFT Graphics.TOP);
                
    repaint();
            }

            protected 
    void pointerDragged(int xint y) {
                
    pointerPressed(xy);
            }
        }

    This breaks too, if the image is smaller than the screen and you touch the screen much outside the area of the image, but otherwise it works OK. It doesn't look much different to your code.

    Graham.

  5. #5
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Mask a portion of an image on pointerPressed

    Hmmm... nothing stands out as wrong. What exactly is the problem?

    Some things I notice:

    Quote Originally Posted by ellyna View Post
    Code:
    for (int i = 0; i <= contaTocco; i++) {
    That looks like it should be "<", not "<=" (which would also mean you can remove the enclosing "if").

    Quote Originally Posted by ellyna View Post
    Code:
    graphics.drawRegion(new_bg, maskX[i], maskY[i], 50, 50, Sprite.TRANS_NONE, maskX[i], maskY[i], Graphics.TOP | Graphics.LEFT);
    Watch out that the x,y,w,h don't cause you to draw off the edge of the image, or you'll get an IllegalArgumentException.

    Oh, I'd suggest you use Canvas, not GameCanvas, it's less problematic.

    I thought I'd try too, because it looks quite cool I came up with this:

    PHP Code:
    import javax.microedition.lcdui.*;
    import javax.microedition.lcdui.game.*;
    import javax.microedition.midlet.*;

    public class 
    Dusty extends MIDlet {
        private 
    Displayable d;
        
        public 
    void startApp() {
            if (
    == null) {
                try {
                    
    Image img Image.createImage("/Dusty.jpg");
                    
    = new DustCanvas(img);
                } catch (
    Exception e) {
                    
    Form f = new Form("Error");
                    
    f.append(e.toString());
                    
    f;
                }
            }
            
    Display.getDisplay(this).setCurrent(d);
        }

        public 
    void pauseApp() {
            
    // empty
        
    }

        public 
    void destroyApp(boolean must) {
            
    // empty
        
    }

        private static class 
    DustCanvas extends Canvas {
            private static final 
    int SIZE 25;
            private 
    int width;
            private 
    int height;
            private 
    Image background;
            private 
    Image foreground;
            
            public 
    DustCanvas(Image bg) {
                
    background bg;
                
    width bg.getWidth();
                
    height bg.getHeight();
                
    foreground Image.createImage(widthheight);
                
    Graphics g foreground.getGraphics();
                
    g.drawImage(bg00Graphics.LEFT Graphics.TOP);

                
    // paint "dust" on top of foreground - this is not an optimal implementation!
                
    int[] dust = new int[] { 0xc0808080 };
                for (
    int y 0heighty++) {
                    for (
    int x 0widthx++) {
                        
    g.drawRGB(dust01xy11true);
                    }
                }
            }
            
            protected 
    void paint(Graphics g) {
                
    g.drawImage(foreground00Graphics.LEFT Graphics.TOP);
            }

            protected 
    void pointerPressed(int xint y) {
                
    Graphics g foreground.getGraphics();

                
    int px SIZE;
                
    int py SIZE;
                
    int w SIZE 2;
                
    int h SIZE 2;
                if (
    px 0) {
                    
    += px;
                    
    px 0;
                }
                if (
    py 0) {
                    
    += py;
                    
    py 0;
                }
                if (
    px width) {
                    
    width px;
                }
                if (
    py height) {
                    
    height py;
                }

                
    g.drawRegion(backgroundpxpywhSprite.TRANS_NONEpxpyGraphics.LEFT Graphics.TOP);
                
    repaint();
            }

            protected 
    void pointerDragged(int xint y) {
                
    pointerPressed(xy);
            }
        }

    This breaks too, if the image is smaller than the screen and you touch the screen much outside the area of the image, but otherwise it works OK. It doesn't look much different to your code.

    Graham.

  6. #6
    Registered User
    Join Date
    Aug 2009
    Posts
    6

    Re: Mask a portion of an image on pointerPressed

    Thanks a lot for the code, but for some reasons I still cannot make it work
    I'm using GameCanvas cause I have Sprites (the code is quite long and I have little time, so it'd be kind of problematic to change everything now).
    And I'm using PNGs (while you created images with drawRGB).

    The app doesn't exactly breaks, it freezes in the moment I call the drawRegion() function. I don't understand if it depends on the order I call the images or what else.

    So, my background is actually a Sprite. But I guess I don't really care about it.
    All my images are as big as the screen, so I shouldn't have any problems with that.

    I'm painting dust and a portion of foreground (same image of the background) in my draw() function (which is recalled over and over to repaint everything).
    I cannot paint it in the class constructor because I need it only at some point in the game.

    I don't understand why it doesn't work ;_; It should just paint a portion of the foregounrd image... I've looked at other codes that use drawRegion() and they don't seem to do anything different from me.

    Couldn't just be a memory error? I read somewhere that drawRegion() sometimes takes a lot of memory.


    I report the code, this time I'll try to put all the envolved elements!
    (I'm not even using pointerPressed right now, I'm just trying to make it work).

    Code:
     
    class IntroPresentazioni extends GameCanvas implements DataListener, Runnable {
        private final Image dust;
        private final Image new_bg;
        private final Background bg;
    
        IntroPresentazioni(SpookMIDlet midlet) {    
            super(true);   // suppress key events for game keys
            this.midlet = midlet;
            this.setFullScreenMode(true);
            graphics = getGraphics();
    
            bg = new Background();
    
            dust = SpookMIDlet.createImage("media/dust.png");
            new_bg = SpookMIDlet.createImage("media/bg.jpg");
    
            layerManager = new LayerManager();
            layerManager.append(bg);
    
        public synchronized void start() {
            type_int = true;
            setStopped(false);
            animationThread = new Thread(this);
            animationThread.start();
    
            startTime = System.currentTimeMillis() - gameDuration;
        }
    
    public void run() {
            Thread currentThread = Thread.currentThread();
    
            try {
                
                while (currentThread == animationThread) {
                    
                    long startTime = System.currentTimeMillis();
                    
                    if (isShown()) {
                        tick();
                        draw();
                        flushGraphics();
                    }
                    long timeTaken = System.currentTimeMillis() - startTime;
                    if (timeTaken < MILLIS_PER_TICK) {
                        synchronized (this) {
                            wait(MILLIS_PER_TICK - timeTaken);
                        }
                    } else {
                        currentThread.yield();
                    }
                }
            } catch (InterruptedException e) {
                // won't be thrown
            }
        }
    
    
    [...]
    
    void draw() { // there's an animation thread, it repaints over and over ;)
    
            layerManager.paint(graphics, 0, 0);
    
    [...]
    
        graphics.drawImage(dust, 0, 0, Graphics.TOP | Graphics.LEFT);
        graphics.drawRegion(new_bg, 120, 120, 50, 50, Sprite.TRANS_NONE, 120, 120, Graphics.TOP | Graphics.LEFT);
    }

  7. #7
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Mask a portion of an image on pointerPressed

    Quote Originally Posted by ellyna View Post
    The app doesn't exactly breaks, it freezes in the moment I call the drawRegion() function. I don't understand if it depends on the order I call the images or what else.
    It's very unlikely that the call to drawRegion() freezes. More likely, an exception is being thrown, which is causing the run() method of the thread to terminate, making it look like the app has frozen. Wrap it in a try..catch to see what happens.

    Quote Originally Posted by ellyna View Post
    Code:
    if (contaTocco > 0) {
             for (int i = 0; i <= contaTocco; i++) {
                  graphics.drawRegion(new_bg, maskX[i], maskY[i], 50, 50, Sprite.TRANS_NONE, maskX[i], maskY[i], Graphics.TOP | Graphics.LEFT);
             }
        }
    This is definitely not right. It should be:

    Code:
         for (int i = 0; i < contaTocco; i++) {
              graphics.drawRegion(new_bg, maskX[i], maskY[i], 50, 50, Sprite.TRANS_NONE, maskX[i], maskY[i], Graphics.TOP | Graphics.LEFT);
         }
    Graham.

  8. #8
    Registered User
    Join Date
    Aug 2009
    Posts
    6

    Re: Mask a portion of an image on pointerPressed

    Even without the for doesn't work...

    If I add the try/catch, it doesn't freeze because it doesnt draw the region :P

    I've tried this:

    Code:
    void draw() { 
        [...]
    
        graphics.drawImage(dust, 0, 0, Graphics.TOP | Graphics.LEFT);
                try {
                    graphics.drawRegion(new_bg, 120, 120, 100, 100, Sprite.TRANS_NONE, 120, 120, Graphics.TOP | Graphics.LEFT);
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
    }

    PS: btw, thanks a lot for the help!

  9. #9
    Registered User
    Join Date
    Aug 2009
    Posts
    6

    Re: Mask a portion of an image on pointerPressed

    OMG I'm an idiot....
    ...I misspelled the image filename........ >_____>

    I'm so sorry! Thanks a lot for the help in anycase ù_u

  10. #10
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Mask a portion of an image on pointerPressed

    Quote Originally Posted by ellyna View Post
    If I add the try/catch, it doesn't freeze because it doesnt draw the region :P
    That's because the catch() was swallowing the NullPointerException that drawRegion() was throwing. If adding a try..catch makes a difference, then an exception is being thrown.

    Quote Originally Posted by ellyna View Post
    Code:
            dust = SpookMIDlet.createImage("media/dust.png");
            new_bg = SpookMIDlet.createImage("media/bg.jpg");
    Filenames passed to Image.createImage() should start with a "/", and be the complete, absolute path in the JAR.

    I'm guessing you've written your own method, something like:

    Code:
    public static Image createImage(String s) {
        Image img = null;
        try {
            img = Image.createImage(s);
        } catch (Exception e) {
            // make exception go away
        }
        return img;
    }
    This is a common practice, because it saves you the annoyance of dealing with exceptions. But: the exceptions are there for a reason. They're there to help you. An exception was being thrown to tell you that the image wasn't being loaded. If you hadn't made it go away, the program would have told you why it wasn't working, saving you a day of debugging.

    Variables left set at null are really unhelpful. The best you can expect them to do is throw a NullPointerException. Since NPE's can come from almost anywhere, they're really hard to track down. Worse, they'll usually come much later in the code than the actual problem (the exception that you made go away, that left the variable set to null in the first place). Never set local variables to null, unless you really, really, want them to be null.

    Occasionally, it's OK just to make an exception disappear, like InterruptedException from a sleep(). But as a rule, catch exceptions only when you're going to do something useful with them.

    Graham.

Similar Threads

  1. load image problem
    By Pmarcoen in forum Mobile Java Media (Graphics & Sounds)
    Replies: 2
    Last Post: 2009-08-23, 06:19
  2. Image mask problem
    By valdonas in forum Symbian
    Replies: 3
    Last Post: 2008-10-27, 16:31
  3. Drawing Lines on an Image (image graphics object returns null)
    By nicenouman in forum Mobile Java General
    Replies: 4
    Last Post: 2006-09-21, 10:15
  4. Replies: 0
    Last Post: 2003-05-12, 17:38
  5. Loading Image data from 'raw' bytes
    By LongSteve in forum Mobile Java General
    Replies: 2
    Last Post: 2002-11-20, 17:38

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×