crop image

edited June 2016 in How To...

Hello,

I need to crop an image but the form of croping should be rounded.i dont have a clue to do it. Thanks for any help.:)

Answers

  • edited June 2014 Answer ✓

    Perhaps the example in the thread below can give ya some ideas on how to do it: *-:)
    http://forum.processing.org/two/discussion/598/mousewheel-syntax-question-solved

  • edited June 2014 Answer ✓

    Then that's not cropping, that's masking. There are lot of topics on mask() and friends.

    [EDIT] For the record, it was indeed cropping, because the wanted result must have exactly the size of the circle (masking makes the pixels outside the masked area transparent, it doesn't remove them). I misunderstood the question.

  • @GoToLoop Thanks for you reply :)...but i dont understatnd how i can do the same thing with a image and copy what is inside the circle.

    @PhiLho tnx!but were i can find it? u can please put a link? :)

  • Answer ✓

    ... how i can do the same thing with a image and copy what is inside the circle.

    Just createImage(), then copy every pixel from the original PImage which is within the radius area!
    Take a look at eraseCanvas() function there. And adapt it to copy the selected pixels within radius!

  • edited June 2014

    @GoToLoop thanks!! i try to do it but i ran into some problems.i try to do it but i have a bug:"syntax error maybe missing a semicolon", i dont undrstand why?... i try to do 2 things :

    1.when i'm clicking with the left mouse i need to copy the pixels that are inside the circle to a new image and draw it to the (0,0) pixels.

    2.when i'm clicking with the left mouse i need to blur the pixels that are inside the circle.

    i'll really appreciate your help!! i dont know how to resolve it..

    this your example code that i try to use with some change of my:

            PGraphics canvas;
            PImage bg;
            PImage flower;// the image that i try to do the changes
            int diam = 50;
    
        void setup() {
          size(640, 360);
          frameRate(50);
          noLoop();
          noFill();
         flower=loadImage("flower.jpg");
          canvas = createGraphics(width, height);
    
          canvas.beginDraw();
          canvas.smooth();
          canvas.strokeWeight(diam);
          canvas.endDraw();
    
          bg = createBG(0150);
    
          mouseX = width  >> 1;
          mouseY = height >> 1;
    
          mouseButton = CENTER;
          mousePressed();
        }
    
        void draw() {
          background(flower);
          image(canvas, 0, 0);
          canvas.image(flower,0,0); 
          ellipse(mouseX, mouseY, diam, diam);
        }
    
        void keyPressed() {
          canvas.clear();
          canvas.endDraw();
    
          redraw();
        }
    
        void mousePressed() {
          if (mouseButton != CENTER)  return;
    
          final color c = (color) random(#000000);
    
          stroke(c);
    
          canvas.stroke(c);
          canvas.endDraw();
          if (mouseButton == LEFT)  eraseCanvas();
    
          redraw();
        }
    
        void mouseMoved() {
          redraw();
        }
    
        /*void mouseDragged() {
          if (mouseX < 0 | mouseX >= width
            | mouseY < 0 | mouseY >= height)  return;
    
          if (mouseButton == LEFT)  drawCanvas();
          else                      eraseCanvas();
    
          redraw();
        }*/
    
        void mouseWheel(MouseEvent me) {
          final int inc = keyPressed & keyCode == CONTROL ? -1 : -5;
          diam = constrain(diam + me.getCount()*inc, 1, 100);
    
          canvas.strokeWeight(diam);
          canvas.endDraw();
    
          redraw();
        }
    
        /*void drawCanvas() {
          canvas.line(mouseX, mouseY, pmouseX, pmouseY);
          canvas.endDraw();
        }*/
    
        void eraseCanvas() {
          final int cp[] = canvas.pixels, cw = canvas.width;
          final int rad  = diam>>1, radSq = rad*rad;
          final int mx = mouseX, my = mouseY;
          PImage des= createImage(50, 50, RGB);
          des.loadPixels();
          final int xStart, yStart, xEnd, yEnd;
    
          xStart = max(mx - rad, 0);
          xEnd   = min(mx + rad, cw);
    
          yStart = max(my - rad, 0);
          yEnd   = min(my + rad, canvas.height);
    
          /*
          for (int x = xStart; x != xEnd; x++)
           for (int y = yStart; y != yEnd; y++)
           if (sq(mx - x) + sq(my - y) <= radSq)   cp[x + y*cw] = 0;
           */
    
          for (int y = yStart; y != yEnd; y++) {
            final float myySq = sq(my - y);
    
            for (int cwy = cw*y,x = xStart, i=0 ; x != xEnd, i < des.pixels.length; x++, ,i++)
              if (sq(mx - x) + myySq <= radSq)   cp[cwy + x] = des.pixels[i];
          }
    
          canvas.updatePixels();
          des.updatePixels();
          image(des,0,0);
        }
    
        PImage createBG(int div) {
          int i = div = constrain(div, 1, 0400);
    
          final PGraphics pg = createGraphics(width, height);
          final int wdiv = width/div, grey = 0400/div;
    
          pg.beginDraw();
          pg.noStroke();
    
          while (i-- != 0) {
            pg.fill(i*grey);
            pg.rect(map(i, div, 0, width, 0), 0, wdiv, height);
          }
    
          pg.endDraw();
          return pg.get();
        }
    
  • edited June 2014 Answer ✓

    @keren_m, as I've tipped you already, you should start by looking at eraseCanvas() 1st. And try to adapt it to your need.

    For example, eraseCanvas() uses the current mouse coordinates to determine the point of origin.
    I believe you would want the point of origin to be the center of the PImage instead, right?

    Another issue is that eraseCanvas() expects that variables canvas & diam to pre-exist as global fields.
    I think it'd be better to pass those as parameters instead.

    The name eraseCanvas() isn't appropriate for what you intend to do now.
    Change it to something like PImage cropImageCircle(PImage img, int diam).

    The premise of the original eraseCanvas() is to erase pixels within a radius.
    But you gotta make it copy pixels to another clean 100% transparent PImage at the same coordinates instead.

  • _vk_vk
    edited June 2014 Answer ✓

    PhiLo means:

    mask() site:processing.org

    http://bit.ly/1mt8CHB

    or

    mask() site:forum.processing.org

    http://bit.ly/1kPJkrs

  • edited June 2014

    @GoToLoop i try do do this but it's not working. i can't figure out why.u can please take a look? :)

    PGraphics canvas;
    PImage bg;
    PImage flower;
    final static float inc = .05;
    float zoom = 1;
    PImage des;
    int diam = 50;
    
    void setup() {
    
      size(640, 360);
      frameRate(50);
      noLoop();
      noFill();
    
     flower=loadImage("flower.jpg");
      canvas = createGraphics(width, height);
    
      canvas.beginDraw();
      canvas.smooth();
      canvas.strokeWeight(diam);
      canvas.endDraw();
    
      bg = createBG(0150);
    
      mouseX = width  >> 1;
      mouseY = height >> 1;
    
      mouseButton = CENTER;
      mousePressed();
    }
    
    void draw() {
      background(flower);
      image(canvas, 0, 0);
    
      ellipse(mouseX, mouseY, diam, diam);
    }
    
    void keyPressed() {
      canvas.clear();
      canvas.endDraw();
    
      redraw();
    }
    
    void mousePressed() {
      if (mouseButton != CENTER)  return;
    
      final color c = (color) random(#000000);
    
      stroke(c);
    
      canvas.stroke(c);
      if (mouseButton == LEFT)  {
      canvas.scale(zoom);
      canvas.image(cropImageCircle(des,diam),0,0);
      zoom=1;
    }
      canvas.endDraw();
    
      redraw();
    }
    
    void mouseMoved() {
      redraw();
    }
    
    
    
    void mouseWheel(MouseEvent me) {
      final int inc = keyPressed & keyCode == CONTROL ? -1 : -5;
      diam = constrain(diam + me.getCount()*inc, 1, 100);
    
      canvas.strokeWeight(diam);
      canvas.endDraw();
    
      redraw();
    }
    
    /*void drawCanvas() {
      canvas.line(mouseX, mouseY, pmouseX, pmouseY);
      canvas.endDraw();
    }*/
    
    PImage cropImageCircle(PImage des, int diam) {
    
      flower.loadPixels();
      final int mx = mouseX, my = mouseY;
    
      final int xStart, yStart, xEnd, yEnd;
      final int pWidth, pHeight; 
      xStart = constrain(mx-diam,0,flower.width);
      xEnd   = constrain(mx+diam,0, flower.width);
    
      yStart = constrain(my+diam,0,flower.height);
      yEnd   = constrain(my-diam,0,flower.height);
    
      pWidth = yStart - yEnd;
      pHeight = xEnd - xStart;
      des=createImage(pWidth, pHeight, RGB);
      des.loadPixels();
      /*
      for (int x = xStart; x != xEnd; x++)
       for (int y = yStart; y != yEnd; y++)
       if (sq(mx - x) + sq(my - y) <= radSq)   cp[x + y*cw] = 0;
       */
    
       for (int x=xStart; x<xEnd; x++) {
        for (int y=yStart; y<yEnd; y++ ) {
          float distance = dist(x, y, mx, my);
          if (distance <= diam) {
            int loc = x + y*canvas.width;
            des.pixels[loc] =canvas.pixels[loc];
          }
        }
      }
    
      canvas.updatePixels();
      des.updatePixels();
      flower.updatePixels();
      return des;
    }
    
    PImage createBG(int div) {
      int i = div = constrain(div, 1, 0400);
    
      final PGraphics pg = createGraphics(width, height);
      final int wdiv = width/div, grey = 0400/div;
    
      pg.beginDraw();
      pg.noStroke();
    
      while (i-- != 0) {
        pg.fill(i*grey);
        pg.rect(map(i, div, 0, width, 0), 0, wdiv, height);
      }
    
      pg.endDraw();
      return pg.get();
    }
    
  • edited June 2014

    @_vk tnx!but i don't understand how masking is helping me? :)

  • _vk_vk
    Answer ✓
    PImage img;
    PGraphics mask;
    
    void setup(){
      size (200, 249);
      img = loadImage("http" + "://i43.tower.com/images/mm111692348/juvenile-justice-karen-m-hess-hardcover-cover-art.jpg");
      mask = createGraphics(width, height);
      background(40);
    }
    
    void draw(){
      background(0);
      mask.beginDraw();
      mask.noStroke();
      mask.fill(255);
      mask.ellipse(width/2, height/2 +30, 100, 100);
      mask.endDraw();
      if (frameCount > 200)
      img.mask(mask);
      image(img, 0 ,0);
    }
    

    ;)

  • edited June 2014

    @_vk tnx for your reply!!..but the new image is on the size of the circle or it's the size of the origin image?because i need it to b on the size of the circle...and there is away that i can also blur the pixels that are inside the circle without putting all black screen, just leave the image and bluring just the pixels that are inside the circle in a way that fits with the image,like photoshop? ;)

    tnx! :)

  • _vk_vk
    edited June 2014 Answer ✓

    There is not a new image really. You could do one though. What I've done, was to just display the masked image over the canvas. You still with a 200x249 rectangle, only that all, but the masked circle area, are transparent pixels… So the origin to the image still being the top left corner of the original image. You can use image call instead of background, blur it, and overlay the unblurred one… Or the opposite. You might need another PGraphics maybe.

    I think you may dig into those links, there are issues and also another way, which I'm not familiar with, of doing this. With PShape and texture() i think. I think those are faster. There are examples of that among those posts.

    Anyway here is the idea.

    PImage img ;
    PGraphics mask, blur;
    
    void setup(){
      size (200, 249);
      img = loadImage("http" + "://i43.tower.com/images/mm111692348/juvenile-justice-karen-m-hess-hardcover-cover-art.jpg");
    
      blur = createGraphics(width, height);
      mask = createGraphics(width, height);
    
      mask.beginDraw();
      mask.background(0);
      mask.noStroke();
      mask.fill(255);
      mask.ellipse(width/2, height/2 +30, 100, 100);
      mask.endDraw();
      mask.beginDraw();
    
      blur.beginDraw();
      blur.image(img, 0,0);
      blur.filter(BLUR, 6);
      blur.endDraw();
    
    }
    
    void draw(){
      image(blur, 0 ,0);
    
      img.mask(mask);
      image(img, 0 ,0);
    }
    
  • Answer ✓

    Little l8 for the party now... Anyways, just finished adapting eraseCanvas() into cropImageCircle()! #:-S
    And as a bonus, there's a built-in trim feature too! The output PImage's dimensions match the diameter parameter! \m/

    /**
     * Crop Round Image (v1.0)
     * by GoToLoop (2014/Jun)
     *
     * forum.processing.org/two/discussion/5618/crop-image
     */
    
    static final String URL = "https://" + "upload.wikimedia.org/";
    static final String FOLDER = "wikipedia/en/c/ca/";
    static final String FILE = "Luigi_vacuum", EXT = ".jpg";
    
    static final int DIAM = 0400, MARGIN = 050;
    PImage rectImg, roundImg;
    
    void setup() {
      size(800, 600, JAVA2D);
      noLoop();
      smooth(4);
      imageMode(CORNER);
    
      //rectImg = loadImage(FILE + EXT);
      rectImg = loadImage(URL + FOLDER + FILE + EXT);
    
      roundImg = cropImageCircle(rectImg, DIAM);
    
      println("Original Image Dimensions: "
        + rectImg.width + ", " + rectImg.height);
      println("Rounded  Image Dimensions: "
        + roundImg.width + ", " + roundImg.height);
    }
    
    void draw() {
      background(0100);
      set(MARGIN, height-rectImg.height >> 1, rectImg);
      image(roundImg, width-roundImg.width-MARGIN, height-roundImg.height >> 1);
    }
    
    PImage cropImageCircle(final PImage inputImg, int diam) {
      final int rad = (diam = abs(diam)) >> 1, radSq = rad*rad;
    
      final color[] p = inputImg.pixels;
      final int w = inputImg.width, h = inputImg.height;
      final int cx = w>>1, cy = h>>1;
    
      final PImage outputImg = createImage(diam, diam, ARGB);
      final color[] q = outputImg.pixels;
    
      final int minX = max(cx - rad, 0);
      final int maxX = min(cx + rad, w);
    
      final int minY = max(cy - rad, 0);
      final int maxY = min(cy + rad, h);
    
      for (int y = minY; y != maxY;) {
        final float cySq = sq(cy - y);
        final int rw1 = w*y, rw2 = diam*(y++ - minY);
    
        for (int x = minX; x != maxX; x++)
          if (sq(cx - x) + cySq <= radSq)  q[rw2 + x - minX] = p[rw1 + x];
      }
    
      outputImg.updatePixels();
      return outputImg;
    }
    
  • edited June 2014

    @_vk tnx!! i'll c what i can do with that.

    @GoToLoop Amazing!tnx!!there is a chance to do it with mousex,mousey to be the center of the circle and not the center of the image? :)

  • line 43: insert mouseX and mouseY

  • edited June 2014

    Variables cx & cy represent the center of the cropped circle, its point of origin.

    Rather than insert mouseX & mouseY back as @Chrisir said and how it was in the original eraseCanvas(),
    let's make it more flexible and declare cx & cy as the method's parameters:

    PImage cropImageCircle(final PImage inputImg, final int cx, final int cy, int diam) {

    And pass mouseX & mouseY as the arguments for cx & cy: *-:)

    roundImg = cropImageCircle(rectImg, mouseX, mouseY, DIAM);

    Of course, comment out line #43 after that change: //final int cx = w>>1, cy = h>>1;. :-j

    P.S.: For mouseX & mouseY to work as cx & cy, the source inputImage gotta be displayed at (0, 0) coordinates I'm afraid! 8-|

  • yes, much better, thank you, gotoloop

    ;-)

  • i did it but it's not display the crop image.any idea?

  • static final String URL = "https://" + "upload.wikimedia.org/";
    static final String FOLDER = "wikipedia/en/c/ca/";
    static final String FILE = "Luigi_vacuum", EXT = ".jpg";
    boolean drawp; 
    static final int DIAM = 100, MARGIN = 050;
    PImage rectImg, roundImg;
    
    void setup() {
      size(800, 600, JAVA2D);
      noLoop();
      smooth(4);
      imageMode(CORNER);
     drawp=false;
      //rectImg = loadImage(FILE + EXT);
      rectImg = loadImage(URL + FOLDER + FILE + EXT);
    
    //  roundImg = cropImageCircle(rectImg, DIAM);
    
      println("Original Image Dimensions: "
        + rectImg.width + ", " + rectImg.height);
     /* println("Rounded  Image Dimensions: "
        + roundImg.width + ", " + roundImg.height);*/
    }
    
    void draw() {
     background(0100);
      set(MARGIN, height-rectImg.height >> 1, rectImg);
      if(drawp==true){
        rect(0,50,50,100);
        image(roundImg, width-roundImg.width-MARGIN, height-roundImg.height >> 1);
    
      }
      //
    }
    
    PImage cropImageCircle(final PImage inputImg,final int cx,final int cy, int diam) {
      final int rad = (diam = abs(diam)) >> 1, radSq = rad*rad;
    
      final color[] p = inputImg.pixels;
      final int w = inputImg.width, h = inputImg.height;
      //final int cx = w>>1, cy = h>>1;
    
      final PImage outputImg = createImage(diam, diam, ARGB);
      final color[] q = outputImg.pixels;
    
      final int minX = max(cx - rad, 0);
      final int maxX = min(cx + rad, w);
    
      final int minY = max(cy - rad, 0);
      final int maxY = min(cy + rad, h);
    
      for (int y = minY; y != maxY;) {
        final float cySq = sq(cy - y);
        final int rw1 = w*y, rw2 = diam*(y++ - minY);
    
        for (int x = minX; x != maxX; x++)
          if (sq(cx - x) + cySq <= radSq)  q[rw2 + x - minX] = p[rw1 + x];
      }
    
      outputImg.updatePixels();
      return outputImg;
    }
    
    void mouseReleased() {
    
        roundImg = cropImageCircle(rectImg,mouseX,mouseY, DIAM);
        drawp=true;
    
    }
    
  • Answer ✓

    where do you call cropImageCircle at all?

    you need to call it....

    probably in draw()

  • edited June 2014 Answer ✓

    roundImg = cropImageCircle(rectImg, mouseX, mouseY, DIAM);

  • line 66:when i'm clicking i call it...

  • Answer ✓

    don't noLoop in 10 pls

  • Answer ✓

    also line 29 is not helpful

  • edited June 2014 Answer ✓

    there is a small (rad) offset though to the right

  • edited October 2017 Answer ✓

    Lo & behold the latest "Crop Round Image" (version 2.0): \m/

    /**
     * Crop Round Image (v2.0.1)
     * by GoToLoop (2014/Jun)
     *
     * forum.Processing.org/two/discussion/5618/crop-image#Item_26
     */
    
    static final String URL = "https://" + "upload.Wikimedia.org/";
    static final String FOLDER = "wikipedia/en/c/ca/";
    static final String FILE = "Luigi_vacuum", EXT = ".jpg";
    
    static final int MARGIN_X = 050, STEP = 8, FPS = 30;
    static final color BG = 0100;
    
    PImage rectImg, roundImg;
    int iw, ih, marginY, diam = 0400;
    
    void setup() {
      size(900, 700);
      noLoop();
      frameRate(FPS);
      smooth(3);
      imageMode(CORNER);
    
      //rectImg = loadImage(FILE + EXT);
      rectImg = loadImage(URL + FOLDER + FILE + EXT);
    
      iw = rectImg.width;
      ih = rectImg.height;
      marginY = height-ih >> 1;
    
      //roundImg = cropImageCircle(rectImg, diam);
      roundImg = cropImageCircle(rectImg, iw>>1, ih>>1, diam);
    
      println("Original Image Dimensions: " + iw + ", " + ih);
      println("Rounded  Image Dimensions: " + roundImg.width + ", " + roundImg.height);
    }
    
    void draw() {
      background(BG);
      set(MARGIN_X, marginY, rectImg);
      image(roundImg, width-roundImg.width-MARGIN_X, height-roundImg.height >> 1);
    }
    
    void mouseMoved() {
      roundImg = cropImageCircle(rectImg, mouseX-MARGIN_X, mouseY-marginY, diam);
      redraw();
    }
    
    void mouseWheel(final MouseEvent e) {
      final int inc = keyPressed & keyCode == CONTROL ? -1 : -STEP;
      diam = constrain(diam + e.getCount()*inc, 0, abs(iw - ih)<<1);
      print(diam + "\t");
      mouseMoved();
    }
    
    //PImage cropImageCircle(final PImage inputImg, int diam) {
    PImage cropImageCircle(final PImage inputImg, final int cx, final int cy, int diam) {
      final int rad = (diam = abs(diam))>>1, radSq = rad*rad;
    
      final color[] p = inputImg.pixels;
      final int w = inputImg.width, h = inputImg.height;
      //final int cx = w>>1, cy = h>>1;
    
      final PImage outputImg = createImage(diam, diam, ARGB);
      final color[] q = outputImg.pixels;
    
      final int minX = max(cx - rad, 0);
      final int maxX = min(cx + rad, w);
    
      final int minY = max(cy - rad, 0);
      final int maxY = min(cy + rad, h);
    
      for (int y = minY; y < maxY;) {
        final float cySq = sq(cy - y);
        final int rw1 = w*y, rw2 = diam*(y++ - minY);
    
        for (int x = minX; x < maxX; x++)
          if (sq(cx - x) + cySq <= radSq)  q[rw2 + x - minX] = p[rw1 + x];
      }
    
      outputImg.updatePixels();
      return outputImg;
    }
    
  • edited June 2014

    @Chrisir tnx 4 your helps :)

    @GoToLoop really tnx it's was very helpful your code!!! =D>

Sign In or Register to comment.