We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Take part of image using mouse
Pages: 1 2 
Take part of image using mouse (Read 3453 times)
Take part of image using mouse
Mar 16th, 2010, 11:15am
 
Hi all!
Is there a way to let users select a part of a loaded image
using a rectangle-selection or something,

and to let the selected part of the loaded image
appear elsewhere?

Greetings!
Vincent
Re: Take part of image using mouse
Reply #1 - Mar 16th, 2010, 12:07pm
 
Yep...use get and set.....

http://processing.org/reference/get_.html
http://processing.org/reference/set_.html

Get into a PImage ...set to draw the image somewhere else.

Use mousePressed() to set the starting coordinates, mouseReleased() to set the end coordinates of the area to get. You can also have an if(mousePressed) block in draw() to draw the selection rectangle....
Re: Take part of image using mouse
Reply #2 - Mar 16th, 2010, 12:54pm
 
thanks a lot for the help but,
i can't get the get and set to work,
how to make them grab the pixels selected by the rect?

is there anybody who can post a code?
i will learn a lot from it very quickly,
please?

Greetings,
Vincent!
Re: Take part of image using mouse
Reply #3 - Mar 16th, 2010, 3:11pm
 
OK... try this Smiley

Left click and drag to select an area. Right click to paste that area into the image. (You'll have to put your own "test.jpg" image sized to 640x480 in the sketch directory to run this). Any questions, anything you don't understand, please ask....

(NOTE - just modified code as there was a mistake).

Code:
PImage backgrnd;
PImage selection;
float startX, startY;

void setup()
{
  size(640, 480);
  noFill();
  backgrnd= loadImage("test.jpg");
  set(0, 0, backgrnd);
}


void draw()
{
 background(backgrnd);
 if(mousePressed)
 {
   noFill();
   strokeWeight(1);
   stroke(255, 100);
   rectMode(CORNER);
   rect(startX, startY, mouseX-startX, mouseY-startY); //draw    transparent rectangle when dragging
 }
 
}

void mousePressed()
{
 startX= mouseX;
 startY=mouseY;
}

void mouseReleased()
{
 if(mouseButton==RIGHT && selection!=null)
 {  
   set(mouseX, mouseY, selection);
   backgrnd=get();
 }
 else selection=get((int)startX, (int)startY, (int)(abs(startX-mouseX)), (int)(abs(startY-mouseY)));
 
}


Re: Take part of image using mouse
Reply #4 - Mar 16th, 2010, 3:27pm
 
Note - only works when dragging down and to the right - I'll let you fix it up so it works wherever you drag to and from (e.g. up and to left).
Re: Take part of image using mouse
Reply #5 - Mar 16th, 2010, 3:52pm
 
Just fixed it myself actually...and a couple of other things - such as allowing dragging to create the selection to occur only with the left button... (it was bugging me so I thought I would just fix it).
Hope you find this useful.

Code:
PImage backgrnd;
PImage selection;
float startX, startY;

void setup()
{
  size(640, 480);
  noFill();
  backgrnd= loadImage("test.jpg");
  set(0, 0, backgrnd);
}


void draw()
{
 background(backgrnd);
 if(mousePressed &&mouseButton==LEFT)
 {
   noFill();
   strokeWeight(1);
   stroke(255, 100);
   rectMode(CORNER);
   rect(startX, startY, mouseX-startX, mouseY-startY); //draw transparent rectangle when dragging
 }
 
}

void mousePressed()
{
 if(mouseButton==LEFT)
 {
   startX= mouseX;
   startY=mouseY;
 }
}

void mouseReleased()
{
 if(mouseButton==RIGHT && selection!=null)
 {  
   set(mouseX, mouseY, selection);
   backgrnd=get();
 }
 else
 {
   selection=get((int)min(mouseX, startX), (int)min(mouseY, startY), (int)abs(mouseX-startX), (int)abs(mouseY-startY));
 }
}
Re: Take part of image using mouse
Reply #6 - Mar 17th, 2010, 9:30am
 
Hi Giles! Wink Thank you so much for your code!
It's wonderful!  Cheesy

Could you take a look at my program?  Undecided
(The program works with a "test.jpg" image in the sketch directory).

Here is the code: (I added some remarks in the code as to where
                      i think the code should be written.)  Shocked

Code:
int venster = 0;
int volgendvenster = 0;
int geslacht = 0;
PFont lettertype1;
PImage backgrnd;
PImage selection;
float startX, startY;

void setup () {
   textAlign(CENTER);
   imageMode(CENTER);
   size(500,500);
   background(255);
   lettertype1 = createFont("Verdana", 20);
   textFont(lettertype1);
   backgrnd = loadImage("test.jpg");}
   
void mousePressed(){
 if((mouseButton==LEFT) && (venster == 0) && (mouseX>=215) && (mouseX<=285) &&
    (mouseY>=235) && (mouseY<=265)) {
  volgendvenster = 1;}
 
 if((mouseButton==LEFT) && (venster == 1) && (mouseX>=145) && (mouseX<=215) &&
    (mouseY>=235) && (mouseY<=265)) {
  volgendvenster = 1;
  geslacht = 1;}
 
  if((mouseButton==LEFT) && (venster == 1) && (mouseX>=285) && (mouseX<=355) &&
    (mouseY>=235) && (mouseY<=265)) {
  volgendvenster = 1;
  geslacht = 2;}

  if((mouseButton==LEFT) && (venster == 2) && (mouseX>=68) && (mouseX<=432) &&
    (mouseY>=201) && (mouseY<=299)) {
  volgendvenster = 1;
 
 
// when if is true, i think the user should be able to start to select a part of the test.jpg here


  }}

void mouseReleased(){
 if((mouseButton==LEFT) && (venster == 0) && (mouseX>=215) && (mouseX<=285) &&
    (mouseY>=235) && (mouseY<=265)) {
  volgendvenster = 2;}

  if((mouseButton==LEFT) && (venster == 1) && (geslacht == 1) &&
(mouseX>=145) && (mouseX<=215) && (mouseY>=235) && (mouseY<=265)) {
  volgendvenster = 2;}
 
  if((mouseButton==LEFT) && (venster == 1) && (geslacht == 2) &&
(mouseX>=285) && (mouseX<=355) && (mouseY>=235) && (mouseY<=265)) {
  volgendvenster = 2;
  geslacht = 2;}
 
 if((mouseButton==LEFT) && (venster == 2) && (mouseX>=68) &&
    (mouseX<=432) && (mouseY>=201) && (mouseY<=299) &&
    (volgendvenster == 1)) {
   volgendvenster = 2;
   
   
   // when if is true, i think the selected part of the test.jpg should be decided and saved here
   
   
}}
   
void draw() {

 if (venster == 0) {
   background(255);
   fill (0);
   rect(215,235,70,30);
   text("Welcome to the Body-program.",250,450);
   fill (255);
   text("Start",250,257);}
 if ((venster == 0) && (volgendvenster == 2)) {
   venster = 1;
   volgendvenster = 0;}
   
  if (venster == 1) {
   background(255);
   fill (0);
   rect(145,235,70,30);
   rect(285,235,70,30);
   text("First choose your gender.",250,450);
   fill (255);
   text("M",180,257);
   text("F",320,257);}
  if ((venster == 1) && (volgendvenster == 2)) {
   venster = 2;
   volgendvenster = 0;}
   
  if (venster == 2) {
   background(255);
   fill (0);
   rect (0,0,0,0);
   text("Now select your head.",250,450);
   image (backgrnd,250,250,364,98);}
  if ((venster == 2) && (volgendvenster == 2)) {
   venster = 3;
   volgendvenster = 0;}

   if (venster == 3) {
   background(255);
   text("Is this the head you wanted?",250,450);
   
   
   // when if is true, i think the selected part of the test.jpg should appear here
   
   
}}


Visually speaking the remarks inside the code mean:

  - The user should be able to select a part of the test.jpg
  when the 'Now select your head.' screen
  is shown.

  - Then the selected part of the the test.jpg should appear
  when the 'Is this the head you wanted?.'      
  screen is shown.  Cool

Giles, you really kick ass for helping me out man!!!  Cool
I really mean that!  Wink
Re: Take part of image using mouse
Reply #7 - Mar 17th, 2010, 10:34am
 
Hi Vincent.....

No problem...glad to help.

If you're just selecting heads, and they are just small images that are part of a larger image, it's probably simpler to just cut them out (in photoshop, or something), and load them in as separate images at the start. You then just detect where the user clicks and then show them the appropriate, preloaded head image.  Or, if want the user to be able to select anything they like as a head, then use the method I showed you above.....

What are venster, volgendvenster and geslacht?

Anyway, jump in and apply what I have shown you, and try to get it to work. If you can't, post the non-working code here and I will have another look at it....
Re: Take part of image using mouse
Reply #8 - Mar 17th, 2010, 11:15am
 
Hey Giles, thanks for you reply man! You're number 1.  Cheesy

I think the most fun would be to let the users decide what they want as a head. Meaning: implement your code into my program.
But I might need to understand the following parts of your code a bit more though. Is it possible to explain what the following codes mean exacly?

Code:

{
   set(mouseX, mouseY, selection);
   backgrnd=get();
}


Code:

{
   selection=get((int)min(mouseX, startX), (int)min(mouseY, startY),
  (int)abs(mouseX-startX), (int)abs(mouseY-startY));
}


As for my program-code:

- 'venster' is an int wich determines what a new screen should
 load. (venster starts at 0, wich means loading the 'welcome'-screen.)

 (new screens can only be achieved by reaching the  
 appropriate volgendvenster-value.)

- 'volgendvenster' will determine wether it is ok to move to the next
 screen. (sometimes there first needs to be clicked and/or released
 on something to change volgendvenster.)

- 'geslacht' determines the gender of the virtual body where the head  
 will be placed upon later on. (geslacht 1 will load a male body
 picture, 2 will load a female body picture)

Thanks for the help! Wink  Smiley
Re: Take part of image using mouse
Reply #9 - Mar 17th, 2010, 12:41pm
 
OK....

   set(mouseX, mouseY, selection);
   
This draws the PImage called "selection" at mouseX, mouseY.
you could also use image(selection, mouseX, mouseY), but set is  supposed to be faster.


  backgrnd=get();

This just gets the whole image on the screen and puts it into the PImage called "backgrnd". So the background image which is drawn every frame is updated with what is on the screen. This is really useful - get without any parameters just gets the whole screen.....

  selection=get((int)min(mouseX, startX), (int)min(mouseY, startY),
  (int)abs(mouseX-startX), (int)abs(mouseY-startY));

This gets what is inside the selection rectangle and puts it in the PImage called "selection". By choosing the mimimum (min) of mouseX and startX, and mouseY and startY, we allow for the fact that the dragging might have occurred in any direction... because if we drag from left to right we want the selection area to start at startX, but if we drag from right to left we want int to start at mouseX...so we need to use the minimum of these two values. The width is the absolute value (abs) of the difference between these two values. Abs just makes sure it is positive.

I think if you declare startX and startY as ints rather than floats you can get rid of the (int)s which are necessary to convert the floats to ints for the get function.

Another thing I have noticed in my program is that you get a little bit of the dragging white rectangle in the selection. It's subtle, but you can see it. If you wanted to avoid this, you could copy the screen into another buffer image on mousePressed - and then get the selection from this buffer rather than from the screen.....or...there might be a better way, but this is the idea that occurs to me....


Good luck, let me know how it goes....
Re: Take part of image using mouse
Reply #10 - Mar 18th, 2010, 7:08am
 
Tadaaa! The code has been implemented!  Cool

The only problem i have is that my original klas.jpg
is 1454 x 387 pixels, but in the program the klas.jpg gets loaded
364 x 98 pixels, because otherwise the image would not fit on
all screens.

Because of this, my selection image
is taken from this 364 x 98 pixels image, and is very pixelated.
Wich is not good, it's making the heads inrecognizable.  Sad

Does anyone know a solve to this problem?  Smiley

Giles, would you run my program with a 1454 x 387 pixels
klas.jpg? You will surely notice my problem.

Cheers! Tongue

Code:
int venster, start, geslacht, startX, startY; PFont lettertype1; PImage klas; PImage selectie;
void setup () {textAlign(CENTER); imageMode(CENTER); size(500,500);
lettertype1 = createFont("Verdana", 20); textFont(lettertype1); klas = loadImage("klas.jpg");}
   
void mousePressed(){
  if((mouseButton==LEFT) && (venster == 2) && (mouseX>=68) && (mouseX<=432) &&
    (mouseY>=201) && (mouseY<=299)) {start = 1; startX = mouseX; startY = mouseY;}}

void mouseReleased(){
 if((mouseButton==LEFT) && (venster == 0) && (mouseX>=215) && (mouseX<=285) &&
    (mouseY>=235) && (mouseY<=265)) {venster = 1;}
 
  if((mouseButton==LEFT) && (venster > 0) && (mouseX>=30) && (mouseX<=100) &&
    (mouseY>=30) && (mouseY<=60)) {start = 0; venster = venster - 1;}
 
  if((mouseButton==LEFT) && (venster == 1) && (mouseX>=145) &&
(mouseX<=215) && (mouseY>=235) && (mouseY<=265)) {geslacht = 1; venster = 2;}
 
  if((mouseButton==LEFT) && (venster == 1) && (mouseX>=285) &&
(mouseX<=355) && (mouseY>=235) && (mouseY<=265)) {geslacht = 2; venster = 2;}
 
 if((mouseButton==LEFT) && (venster == 2) && (mouseX<68) ||
    (mouseX>432) || (mouseY<201) || (mouseY>299) && (start == 1)) {start = 0;}
 
  if((mouseButton==LEFT) && (venster == 2) && (mouseX>=68) &&
    (mouseX<=432) && (mouseY>=201) && (mouseY<=299) &&
    (start == 1)) {background (255);image (klas,250,250,364,98);
  selectie=get(min(mouseX, startX), min(mouseY, startY), abs(mouseX-startX), abs(mouseY-startY));venster = 3;}}
   
void draw() {
 if (venster > 0) {background(255);fill (255);rect(30,30,70,30);fill (0);text("<-",65,53);}

 if (venster == 0) {background(255);fill (0);rect(215,235,70,30);
   text("Welcome to the Body-program.",250,450);fill (255);text("Start",250,257);}
   
 if (venster == 1) {fill (0);rect(145,235,70,30);rect(285,235,70,30);
   text("First choose your gender.",250,450);fill (255);text("M",180,257);text("F",320,257);}
   
 if (venster == 2) {fill (0);rect (0,0,0,0);
   text("Now select your head.",250,450);image (klas,250,250,364,98);}
 
 if ((venster == 2) && (start == 1)) {fill(255,50);rect(startX, startY, mouseX-startX, mouseY-startY);}
   
   if (venster == 3) {
   text("Is this the head you wanted?",250,450);image (selectie,250,250);}}

Re: Take part of image using mouse
Reply #11 - Mar 18th, 2010, 8:16am
 
Hi Vincent....

Well done getting it working!

I used my own 1454 x 387 image, but it didn't look that bad to me when reduced in size. A couple of suggestions - reduce the image in Photoshop ( or similar - Irfanview is a great free program that can resize images) to 364 x 98 and use this image instead... or... more tricky... get the selection from the original image (which is in memory), multiplying the dimensions by the right factor. The only problem with this is that when you draw the head onto the screen it will have to be shrunk back down again anyway....

But... I just used a photo (of the CN tower in Toronto) for "klas.jpg", and it looked fine when the "head" was taken out of it, not pixellated at all. So I think the problem must be with the image...not the program..... send me the image...somehow (to giles<underscore>whitaker<at>yahoo<dot>com if you like) and I will see what it looks like.

By the way, you don't need all those if(mouseButton==LEFT)s if you're not using the right mouse button for anything special....
Re: Take part of image using mouse
Reply #12 - Mar 18th, 2010, 9:33am
 
Thanks for the checking the new code out Giles!

I have sent my klas.jpg to your e-mail adress.  Smiley

Will you let me know what you think about the heads selected
from the klas.jpg? I just reduced the image size to 364 x 98
in Photoshop, and it does look a lot better indeed!
It's not pixelized any more, but the heads are pretty small..  Undecided

So I might need to start to look for a way to get the selection
from the original image, wich will be hard..

I agree on what you say about the (mouseButton==LEFT)'s, and
i will certainly take them out! Thanks man!  Wink

And thanks for keep replying to me!
Re: Take part of image using mouse
Reply #13 - Mar 18th, 2010, 10:49am
 
No problem...I've had a lot of help on here, so I like to help out too!

Yes...seems to look fine with the images you sent me. The heads are just small...because the photo has been reduced to a small size. So what you should do is use the selection from the thumbnail-sized image (364x98) to grab a full-resolution head from the full size image file which is kept in memory. This should just be a matter of multiplying the selection boundaries by the appropriate factor (the scale factor). Draw a diagram, take your time to work it all out carefully on paper.... relative position from top left of thumbnail image (NOT 0,0) maps to relative position from top-left in full-size image (which is 0,0).

On the next screen you can then show the head at small size (use image(....) rather than set as image(....) can resize the image). The head is kept in the PImage in higher resolution in
memory for use later on.
Re: Take part of image using mouse
Reply #14 - Mar 18th, 2010, 2:17pm
 
Ok thanks again Giles, you are always helpful!  Smiley
I will start the calculating now.

If i want to take as much pixels as possible on both
the big-sized image and the thumbnail,
(meaning 1454 x 387 for the big-sized image):

A division by 2 or 4 in pixels (depending on what will result
in the most sharp thumbnail) will make the pixels
be for example 193.5.

Should i choose float instead of int then, or will
this slow up my program drastically?

And if it does slows up programs,
should i just choose an int near 193.5?
(wich will make the image slightly out of proportion)
or should shrink the pixels of the big-sized image
just a bit so that i get amounts of pixels that can be divided
by 2 or by 4 and result in ints?
(wich will result in a pixel-loss and maybe also an
extra loss in sharpness because of the extra image-editing)?

Cheers!  Wink
Pages: 1 2