A program to mask an image - Android.

edited January 2017 in Android Mode

Hello, This is my first program to write a code to mask an image and show portion of background image only on mousepress event. The Java code works just fine on desktop(In Java mode). Whereas in Andriod mode, I don't know what I am missing or where the mistake is, but the background image is displayed and the pg object paints itself over and over - how do I correct this? Although mousepress events work just fine. Thanks!!

 PGraphics pg;
    PImage bgimage;
    void setup()
 {
      size(640, 480);
      bgimage = loadImage("background.jpg");
      bgimage.resize(640,480);  

      pg = createGraphics(640, 480);
      pg.beginDraw();
      pg.background(0);
      pg.smooth();
      pg.noStroke();
      pg.fill(255);
      pg.endDraw();
    }
    void draw()
    { 
      image(bgimage,640,480);

      pg.beginDraw();
      if (mousePressed)
      pg.ellipse(mouseX, mouseY, 100, 100);
      pg.endDraw();

      bgimage.mask(pg);
      image(bgimage,0,0);
    }
Tagged:

Answers

  • Based on your java code,you need to set mouseReleasedEndEffect to NO_UPDATE_AFTER_RELEASE in the code below. I included two other modes just for completeness.

    I will look into the PGraphics to see why it doesn't work in Android mode. Here I present an alternative.

    Kf

    PImage srcImage;
    PImage bgImage, currMask;
    
    boolean pre=false;
    
    
    //Definitions of effects after an event: mouse released.
    //Press the "menu" button in your device to shuffle 
    //through the different possible effects. 
    //NOTE: It could take an extra event for the new effect
    //to take place.
    //
    final int NO_UPDATE_AFTER_RELEASE=0;
    final int ONLY_BGBLACK_AFTER_RELEASE =1;
    final int RESET_MASK_AND_BGBLACK_AFTER_RELEASE=2;
    
    
    int mouseReleasedEndEffect=NO_UPDATE_AFTER_RELEASE;
    
    
    void settings() {
      size(640, 480);
      orientation(PORTRAIT);
      noSmooth();
    }
    
    void setup() {
    
      srcImage = loadImage("imgg.jpg");
      srcImage.resize(width, height);  
      currMask=createImage(width, height, RGB);
      initMask();
      bgImage=currMask.get();
    
    
      background(0);
      fill(255);
      noStroke();
      textSize(32);
      textAlign(CENTER, CENTER);
    }
    
    void draw()
    { 
    
      if (pre==true) {
    
        bgImage=srcImage.get();
    
        //Draws current mask and records mouse position (aka. updates mask)
        set(0, 0, currMask);
        ellipse(mouseX, mouseY, 100, 100);
        currMask=get(); 
    
        bgImage.mask(currMask);
        image(bgImage, 0, 0);
    
    
        text("Rel Mode="+mouseReleasedEndEffect, width*0.8, height*0.9);
      }
    }
    
    void mousePressed() {
      pre=true;
    }
    
    
    void mouseReleased() {
      pre=false;
    
      switch(mouseReleasedEndEffect) {
      case NO_UPDATE_AFTER_RELEASE:
        //Nothing to do
        break;
      case ONLY_BGBLACK_AFTER_RELEASE:
        background(0);
        break;
      case RESET_MASK_AND_BGBLACK_AFTER_RELEASE:
        background(0);
        initMask();
        break;
      }
    }
    
    void keyPressed() {
    
      if (key == CODED) {
        if (keyCode == MENU) {
          mouseReleasedEndEffect++;
          if (mouseReleasedEndEffect>RESET_MASK_AND_BGBLACK_AFTER_RELEASE)
            mouseReleasedEndEffect=NO_UPDATE_AFTER_RELEASE;
        }
      }
    }
    
    void initMask() {
      currMask.loadPixels();
      for (int i=0; i<width*height; i++)
        currMask.pixels[i]=0x0;
      currMask.updatePixels();
    }
    
  • @kfrajer=== your code works, of course:: you are not using Graphics, and that was the question... i have not got time enough to look more precisely to that and i'll do asap; now i think that it could be also a problem with mousePressed and so on but we shall see!

  • @akenaton

    I got it working with PGraphics. I also optimized the code a bit as there were many ineffective calls in draw.

    PGraphics pg;
    PImage bgimage, cp;
    
    void setup()
    {
      size(640, 480);
      bgimage = loadImage("imgg.jpg");
      bgimage.resize(640, 480);  
    
      pg = createGraphics(640, 480);
      pg.beginDraw();
      //pg.background(0);
      //pg.smooth();
      pg.noStroke();
      pg.fill(255);
      pg.loadPixels();
      pg.endDraw();
      cp=bgimage.get();
    }
    void draw() {
    
      if (mousePressed) {
        bgimage=cp.get();
        pg.beginDraw();
        pg.background(0);
        pg.ellipse(mouseX, mouseY, 100, 100);
        pg.endDraw();
        bgimage.mask(pg);
        image(bgimage, 0, 0);
      }
    }
    

    the problem in Android mode arises with the mask() call. In the original code I get the following warning msg:

    The pixel array has a length of 307200 but it should be at least 500000

    I trace this back to https://github.com/processing/processing-android-archive/blob/master/core/src/processing/opengl/Texture.java#L326
    where the function returns prematurely. Without going any further in the source code, using line bgimage=cp.get(); solves the problem.

    Kf

  • edited January 2017

    @kfrajer===

    It seems that Graphics cannot work as a mask without (using get()) in androidMode; same problem it seems also with JavaScript mode (see here:: https://forum.processing.org/two/discussion/91/masking-works-in-java-but-not-javascript - Why??? i cannot answer as for now... As for the code, i have taken yours and made it more simple (why "loadPixels()??? - It could be only useful if there was an int[] as param for mask) (why twice get???, for bgimage and cp???... Details...

        PGraphics pg;
        PImage bgimage, cp;
    
        void setup()
        {
          size(640, 480);
          bgimage = loadImage("background.jpg");
          bgimage.resize(640, 480);  
    
          pg = createGraphics(640, 480);
          pg.beginDraw();
          //pg.background(0);
          //pg.smooth();
          pg.noStroke();
          pg.fill(255);
          pg.endDraw();
    
    
    
        }
        void draw() {
    
          if (mousePressed) {
        cp=bgimage.get();
            pg.beginDraw();
           // pg.background(0);
            pg.ellipse(mouseX, mouseY, 100, 100);
            pg.endDraw();
            cp.mask(pg);
    
            image(cp, 0, 0);
          }
        }
    
  • @akenaton

    You are right, you don't need loadPixels(). I forgot to remove it before posting, as I was trying to modify the pixels manually in setup when I was doing some experimentation. Thanks for pointing that out.

    In regards to the copy object, I believe it is a bit of an inefficient way to do it but it works. When you apply the mask to PImage multiple times, it seems that the PImage gets added. Until few frames, the PImage becomes white. My approach is this. In setup, I load the image bgimage that is immutable aka. final in nature. Then before you apply a mask, you transfer the image to the cp object. The mask is applied to a fresh new buffer. PGrahpics pg keeps track of the mouse presses and bgimage acts as a back up of the image.

    Kf

  • I tried using cp.mask(pg.get()); and removing references to a backup image and it didn't work. So my trick is still the only option for now. It is either caused by the mask function or the nature of PGraphics/PImage objects in android mode.

    Kf

Sign In or Register to comment.