My problem is following:
I wrote a code and managed to display an image when i click on a rectangle (with the loadImage-fuction). The rectangle serves as a button that I want to replace with an image later.
But i actually don't just want an image to be displayed when the button is clicked. I want to call a code, to copy an image onto another:
public static int SQUARE_WIDTH = 30;
public static int SQUARE_HEIGHT = 30;
PImage img1,img2, img3;
void setup() {
size(670, 943);
img1 = loadImage("white.png");
img2 = loadImage("hase.jpg");
img3= loadImage("ohrring.jpg");
image(img1,0,0);
}
void draw() {
if(mousePressed)
copy(img2,
constrain(mouseX-SQUARE_WIDTH/2,0,width),
constrain(mouseY-SQUARE_HEIGHT/2,0,height),
SQUARE_WIDTH,SQUARE_HEIGHT,
constrain(mouseX-SQUARE_WIDTH/2,0,width),
constrain(mouseY-SQUARE_HEIGHT/2,0,height),
SQUARE_WIDTH,SQUARE_HEIGHT);
}
The copy-code doesn't simply copy an image, it uses the mouse as a brush! When you "draw" on an area, the image shows with the "strokes" of the brush pixel after pixel!
processing.org/reference/copy_.html
I happen to have huge problems when I want to combine this one with my main code:
int rectX, rectY;
int rectSize = 90;
boolean rectOver = false;
color rectHighlight;
color currentColor, baseColor;
color rectColor;
public static int SQUARE_WIDTH = 30;
public static int SQUARE_HEIGHT = 30;
PImage img1,img2, img3;
void setup() {
size(670, 943);
rectColor = color(0);
rectX = width/2-rectSize-10;
rectY = height/2-rectSize/2;
baseColor = color(102);
currentColor = baseColor;
img1 = loadImage("frida.jpg");
img2 = loadImage("hase.jpg");
img3 = loadImage("white.png");
background(img3);
}
void draw() {
update(mouseX, mouseY);
if (rectOver) {
fill(rectHighlight);
} else {
fill(rectColor);
}
stroke(255);
rect(rectX, rectY, rectSize, rectSize);
}
void update(int x, int y) {
if ( overRect(rectX, rectY, rectSize, rectSize) ) {
rectOver = true;
}else {
rectOver = false;
}
}
void mousePressed() {
if (rectOver) {
background(img2);
}
}
boolean overRect(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}
Theoretically I got the tip to set a boolean in mousePressed() to do the copy-operation in draw(), and then to check this boolean in draw(): if set (true) it shall do the copy. But I'm unfortunately not the brightest star in the programming-sky , so could anybody show me what this part is supposed to look like? Of course, I'm open to other suggestions how to solve this problem!
Thank you!
I hope this is what you are looking for. If you want to copy an image you don't need to call a function to copy an image, you can simply invoke the = sign and the image will be copied.
In my example code buttonImage is the image on the button. Whenever you don't want an image on the button assign it the following way:
buttonImage = null;
If you want to have an image instead of the rectangle do the following:
buttonImage = yourImage;
buttonImage.resize(w, h); //fit it on the button.
I think this is what you want to achieve?
PImage buttonImage;
void setup()
{
}
void draw()
{
if(buttonImage == null || buttonImage.width < 2) rect(x, y, w, h);
else image(buttonImage, x, y);
}
void mouseReleased()
{
if(mouseX > x && mouseX < x + w && mouseY > y && mouseY < y + h)
{
//copy any image onto the buttonImage
buttonImage = loadImage("newPath.png"); //update / overwrite image
buttonImage.resize(w, h); //fit it on the button
}
}
x and y are the position of the button, w and h are the width and the height of the button in my example.
EDIT:
Ok, so basically you want to have a white background and you want to scrap it using your tool so an image appears? I'm still not 100% sure of what you're asking, but if that is the case try this:
I used img.get() instead of img.copy(), because it has less parameters to deal with. I really hoped i understood this correctly, if not maybe link a video to something similar? I have a hard time understanding what you want.
The toolSelected integer is a counter to which tool you are using. Depending on its value, it is executing a different code.
My code:
PImage img1;
int toolSelected = 0; //Normal tool;
int widthOfBrush = 20; //Now you are drawing 20x20
int buttonX = 200;
int buttonY = 200;
int buttonW = 40;
int buttonH = 20;
void setup()
{
size(640, 480);
background(255);
img1 = loadImage("yourImg.png");
img1.resize(width, height); //Fit it on processing screen
}
void draw()
{
if(toolSelected == 0) {}//other tool
//Instead of using copy we will be using buttonImage.get(x, y, w, h) --> makes more sense
if(toolSelected == 1 && mousePressed)
{
float yourX = mouseX;
float yourY = mouseY;
yourX -= floor(widthOfBrush / 2);
yourY -= floor(widthOfBrush / 2);
//scale & copy:
PImage brushImage = img1.get((int)yourX, (int)yourY, widthOfBrush * (width / img1.width), widthOfBrush * (width / img1.width)); //Draw the image at your destination
image(brushImage, mouseX, mouseY);
}
stroke(0);
fill(255);
rect(buttonX, buttonY, buttonW, buttonH);
}
void mouseReleased()
{
if (mouseX > buttonX && mouseX < buttonX + buttonW && mouseY > buttonY && mouseY < buttonY + buttonH)
{
//copy any image onto the buttonImage
//buttonImage = loadImage("newPath.png"); //update / overwrite image
toolSelected = 1; //Our tool is the image brush now.
}
}
Related
I am new to processing and I am creating this small game where these stick men try to avoid the attacker. I have added a moving stick man. It goes from bottom to top, but when it reaches the top, it doesn't come back up from the bottom side again, it just disappears. I was wondering what I could do to make this change. Picture for the stick man moving up This is what happens when the stick man go off the screen they don't return back from the bottom
void setup()
{
size(800,400);
stick2 = new Stick(10, 200, 2);
stick3 = new Stick(150,200, 3);
}
void draw()
{
background(240);
stick2.render();
stick2.move();
stick3.render();
stick3.move();
}
class Stick
{
//members?
int x, y;
int speedX = 2;
int speedY = 2;
int animationcounter = 0; //animation
PImage img1, img2;
//constructor - load images
Stick(int x, int y, int speed)
{
this.x = x;
this.y = y;
this.speedX = speed;
img1 = loadImage("stick1.png");//loads from .pde source code directory
img2 = loadImage("stick2.png");
}
void render()
{
//cycle through images, and back to image1
if (animationcounter >0 & animationcounter <=8)
{ image(img1,this.x,this.y); }
else if (animationcounter >8 & animationcounter <=20)
{image(img2,this.x,this.y); }
else
{
image(img2,this.x,this.y);
}
animationcounter = animationcounter+1;
if (animationcounter>32)
animationcounter = 0;
}
void move()
{
this.y = this.y - speedY; //move rightwards
if (this.y>height)
this.y = +img1.height;
}
}
The problem is that you're not actually checking if the stickman goes above the screen.
You're checking if its y value is higher than height, in other words, if it's below the screen.
Also, it would be nice if the image goes completely off the screen before it appears on the other side.
To achieve this, your move function should look like this
void move()
{
this.y = this.y - speedY;
//image goes above the screen
if (this.y < 0 - img1.height) //subtract the image height so the image completely disappears before it moves down
this.y = height + img1.height;
//image goes below the screen
if (this.y > height + img1.height)
this.y = -img1.height;
}
I was steered over to this forum when I asked my lecturer for advice on a piece of code for a group project. The general idea is that there are two images on top of each other, the user can wipe the top image away to reveal the one underneath.
Using some other projects from this forum, I have managed to get the basics running, however I am struggling to get the code to the starting point once the user lets go of the mouse.
I would also appreciate any advice regarding how to convert this to using a touch screen. I have looked at the multitouch code within the processing app, however it does not allow me to add images to this, and if I try and use the computer software it does not seem to like the multitouch. Is there any way around this?
The code I currently have is below, I will be greatful so any advice or input- thanks in advance!
PImage img, front;
int xstart, ystart, xend, yend;
int ray;
void setup()
{
size(961, 534);
img = loadImage("back.jpg");
front = loadImage("front.jpg");
xstart = 0;
ystart = 0;
xend = img.width;
yend = img.height;
ray = 50;
}
void draw()
{
{
img.loadPixels();
front.loadPixels();
// loop over image pixels
for (int x = xstart; x < xend; x++)
{
for (int y = ystart; y < yend; y++ )
{
int loc = x + y*img.width;
float dd = dist(mouseX, mouseY, x, y);
// pixels distance less than ray
if (mousePressed && dd < 50)
{
// set equal pixel
front.pixels[loc] = img.pixels[loc];
}
else
{
if (!mousePressed)
{
// reset- this is what I have not been able to work as of yet
front.pixels[loc] = ;
}
}
}
}
img.updatePixels();
front.updatePixels();
// show front image
image(front, 0, 0);
}
}
I recommend to use a mask instead of changing the pixels of the image. Create an empty image and associated it as mask to the the image:
img = loadImage("back.jpg");
front = loadImage("front.jpg");
mask = createImage(img.width, img.height, RGB);
img.mask(mask);
If you now draw both images, then you can only "see" the front image:
image(front, 0, 0);
image(img, 0, 0);
Set the color of the mask (255, 255, 255) instead of changing the pixel of front:
mask.pixels[loc] = color(255, 255, 255);
and reapply the mask to the image
img.mask(mask);
When the mouse button is released, the pixels of the mask have to be changed back to (0, 0, 0) or simply create a new and empty mask:
mask = createImage(img.width, img.height, RGB);
See the example where I applied the suggestions to your original code:
PImage img, front, mask;
int xstart, ystart, xend, yend;
int ray;
void setup() {
size(961, 534);
img = loadImage("back.jpg");
front = loadImage("front.jpg");
mask = createImage(img.width, img.height, RGB);
img.mask(mask);
xstart = 0;
ystart = 0;
xend = img.width;
yend = img.height;
ray = 50;
}
void draw() {
img.loadPixels();
front.loadPixels();
// loop over image pixels
for (int x = xstart; x < xend; x++) {
for (int y = ystart; y < yend; y++ ) {
int loc = x + y*img.width;
float dd = dist(mouseX, mouseY, x, y);
if (mousePressed && dd < 50) {
mask.pixels[loc] = color(255, 255, 255);
}
else {
if (!mousePressed) {
//mask = createImage(img.width, img.height, RGB);
mask.pixels[loc] = color(0, 0, 0);
}
}
}
}
mask.updatePixels();
img.mask(mask);
// show front image
image(front, 0, 0);
image(img, 0, 0);
}
Currently, there is a disconnect between where I click and the coordinates that are printed to terminal. It seems it is basing the coordinates off of the center GridPane but not the image itself of the imageView.
Previously, I would not resize the images in this application but rather in an automated photoshop process and the click/coordinates would be in sync.
Here is where I make an arrayList of resized Images which will be displayed in the GridPane
//Makes imageView arraylist from all images in a given directory
private ArrayList<ImageView> makeImageViewArr(File imagesDir) {
//transer file names from directory folder to string array
File[] strImageList = imagesDir.listFiles();
myMouseHandler mouseHandler = new myMouseHandler();
//instantiate imageview arraylist
arrImageList = new ArrayList<ImageView>();
//get files from folder & start at 1 to ignore ds.Store
for(int count = 1; count < strImageList.length; count++) {
ImageView imgView =
new ImageView(strImageList[count].toURI().toString());
imgView.setFitHeight(360);
imgView.setFitWidth(640);
imgView.setPreserveRatio(true);
imgView.setSmooth(true);
imgView.setOnMouseClicked(mouseHandler);
arrImageList.add(imgView);
}
return arrImageList;
}//END METHOD
Here is the class where I handle the actual click on the imageView
//inner class for mouse input
public class myMouseHandler implements EventHandler<MouseEvent>
{
/* Method which handles & executes mouse clicks
*
* #param e KeyEvent the code from the mouse click
*
* returns none
*/
#Override
public void handle(MouseEvent e)
{
//reset image to erase previous box
pane.setCenter(arrImageList.get(index));
//get image that was clicked on and pixel reader from image
Image clickedImg = arrImageList.get(index).getImage();
PixelReader pxlRdr = clickedImg.getPixelReader();
//get image height/width for copy
int clickedImgW = (int) clickedImg.getWidth();
int clickedImgH = (int) clickedImg.getHeight();
//get x and y coordinates from click
int xCord = (int) e.getX();
int yCord = (int) e.getY();
nudgeX = xCord;
nudgeY = yCord;
//create writeable image and pixelwriter to draw click region
WritableImage outlineImg = new WritableImage(pxlRdr,
clickedImgW, clickedImgH);
PixelWriter pxlWrtr;
pxlWrtr = outlineImg.getPixelWriter();
//draws region
drawRegion(pxlWrtr, xCord, yCord);
//display image with click boundary and link mouseHandler
//to refresh on next click
ImageView tempImg = new ImageView(outlineImg);
tempImg.setFitHeight(360);
tempImg.setFitWidth(640);
tempImg.setPreserveRatio(true);
tempImg.setSmooth(true);
myMouseHandler mouseHandler = new myMouseHandler();
tempImg.setOnMouseClicked( mouseHandler );
pane.setCenter( tempImg );
//print relevant info about click region
System.out.println("xCord: " + xCord);
System.out.println("yCord: " + yCord + "\n");
}//END METHOD
}//END INNER CLASS
This simply draws a region to show where the click has occurred.
//Draws region boundary after user clicks on image
private void drawRegion(PixelWriter pxlWrtr, int xCord, int yCord) {
Image clickedImg = arrImageList.get(index).getImage();
PixelReader pxlRdr = clickedImg.getPixelReader();
//get image height/width for copy
int clickedImgW = (int) clickedImg.getWidth();
int clickedImgH = (int) clickedImg.getHeight();
//draw right vert boundary
for( int yTrack = (yCord + 1); yTrack > (yCord - regionSize ); yTrack--) {
if((yTrack > 0 && yCord < clickedImgH - 1)
&& ( xCord < clickedImgW - 1 )) {
pxlWrtr.setColor(xCord + 1, yTrack, Color.RED);
}
}
//draw left vert boundary
for( int yTrack = (yCord + 1); yTrack > (yCord - regionSize); yTrack--) {
if((yTrack > 0 && yCord < clickedImgH - 1)
&& (xCord - regionSize) >= 0) {
pxlWrtr.setColor(xCord - regionSize, yTrack, Color.RED);
}
}
//draw bottom boundary
for(int xTrack = (xCord + 1); xTrack >= (xCord - regionSize); xTrack--) {
if(xTrack > 0 && yCord < clickedImgH - 1) {
pxlWrtr.setColor(xTrack, yCord + 1, Color.RED);
}
}
//draw top boundary
for(int xTrack = (xCord + 1); xTrack >= (xCord - regionSize); xTrack--) {
if(xTrack >= 0 && (yCord - regionSize) >= 0 ) {
pxlWrtr.setColor(xTrack, yCord - regionSize, Color.RED);
}
}
}//END METHOD
According to the documentation for preserveRatio:
…the dimensions of this node as reported by the node's bounds will be equal to the size of the scaled image…
So you can use that to scale the MouseEvent coordinates:
double x = e.getX();
double y = e.getY();
ImageView view = (ImageView) e.getSource();
Bounds bounds = view.getLayoutBounds();
double xScale = bounds.getWidth() / view.getImage().getWidth();
double yScale = bounds.getHeight() / view.getImage().getHeight();
x /= xScale;
y /= yScale;
int xCord = (int) x;
int yCord = (int) y;
I'm trying to make a hex board with hex images (720x835 GIF) on a scroll-able JPanel. I've overridden the paintComponent method to draw the tiles at different specific locations and used a timer to call repaint at each tick.
When repaint() is called, doDrawing is called. When doDrawing is called, choseTile is called to draw the tiles with drawImage.
For some reason, the tiles are not being drawn and I'm left with an empty black panel. Why are my images not being drawn? Is it because the images are too large? The panel is too large?
public class MapPanel extends JPanel {
// Images for the tiles
Image tile1;
Image tile2;
//etc
// measurements for the tiles
int tileX = 720;
int tileY = 835;
int dimensionX = 14760;
int dimensionY = 14613;
//Use this to keep track of which tiles goes where on a 20x20 board
public int[][] hexer;
/**
* Create the panel.
*/
public MapPanel(int[][] hexMap) {
hexer = hexMap;
setPreferredSize(new Dimension(dimensionX, dimensionY));
setBackground(Color.black);
setFocusable(true);
loadImages();
Timer timer = new Timer(140, animatorTask);
timer.start();
}
//getting the images for the tiles
private void loadImages() {
// Setting the images for the tiles
ImageIcon iid1 = new ImageIcon("/Images/tiles/tile1.gif");
tile1 = iid1.getImage();
ImageIcon iid2 = new ImageIcon("/Images/tiles/tile2.gif");
tile2 = iid2.getImage();
//etc
}
// Drawing tiles
private void choseTile(Graphics g, int x, int y, int id) {
switch (id) {
case 1:
g.drawImage(tile1, x, y, this);
break;
case 2:
g.drawImage(tile2, x, y, this);
break;
//etc
}
}
// repainting stuff
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
private void doDrawing(Graphics g) {
int actualX;
int actualY;
//set the painting coordinates and image ID then call the method to draw
for (int x = 0; x < 20; x++) {
for (int y = 0; y < 20; y++) {
if ((y + 1) % 2 == 0) {
actualX = x * tileX + 720;
} else {
actualX = x * tileX + 360;
}
if((x + 1) % 2 == 0){
actualY = (y/2) * 1253 + 418;
}else{
actualY = (y+1)/2 * 1253 + 1044;
}
if(hexer[x][y] != 0)
choseTile(g, actualX, actualY, hexer[x][y]);
}
}
}
private ActionListener animatorTask = new ActionListener() {
public void actionPerformed(ActionEvent e) {
repaint();
}
};
}
Edit: I've already checked to make sure the images aren't null.
Following Andrew Thompson's suggestion; I used ImageIO. I was able to figure out that the way I was accessing the image files was faulty thanks to thrown errors by ImageIO.
Hi I need to make some widgets with Processing, for which I'm considering wrapping things together with a customized subclass of PGraphics. Then I'll be able to drag them around.
The current problem is, how do I get the position of a PGraphics object?
PGraphics widg;
void setup(){
widg=createGraphics(50,50);
drawWidg();
image(widg,10,10);
}
void draw(){
}
void mouseClicked(){
//PGraphics doesn't have x, y properties. How to get the position of widg?
if(mouseX-widg.x>0 && mouseX-widg.x<widg.width && mouseY-widg.y>0 && mouseY-widg.y<widg.height){
println("clicked!");
}
}
void drawWidg(){
widg.beginDraw();
...
widg.endDraw();
}
PGraphic doesn't have coordinates really, but you got to use some to display it, right? So those are yours coordinates. In the code above they would be (10,10) as used in the call to image() together with PGraphic width/height.
And the code in mousePressed would be:
void mouseClicked(){
if(mouseX > 10 && mouseX < 10 + widg.width &&
mouseY > 10 && mouseX < 10+ widg.height){
println("clicked!");
}
}
Now this is not really good. As it has those hard numbers. So to avoid that you could use a PVector to store those positions like:
PGraphics widg;
PVector widgCoord;
void setup(){
widgCoord = new PVector(10, 10);
widg=createGraphics(50, 50);
drawWidg();
image(widg,widgCoord.x, widgCoord.y);
}
void draw(){
}
void mouseClicked(){
if(mouseX > widgCoord.x && mouseX < widgCoord.x + widg.width &&
mouseY > widgCoord.y && mouseX < widgCoord.y + widg.height){
println("clicked!");
}
}
void drawWidg(){
widg.beginDraw();
widg.background(255,0,0);
widg.endDraw();
}
Or, as you mentioned, you could create a Widget class with a PGraphics, a PVector and what else you need. Something like:
Widget one;
void setup() {
one = new Widget(10, 10, 50, 50);
one.drawWidg();
}
void draw() {
background(0);
one.display();
}
void mouseClicked() {
if (one.isOver()) {
println("clicked!");
}
}
class Widget {
PGraphics widg;
PVector wCoord;
color c = color(255, 0, 0);
Widget(float x, float y, int w, int h) {
wCoord = new PVector(x, y);
widg = createGraphics(w, h);
}
void drawWidg() {
widg.beginDraw();
widg.background(c);
widg.endDraw();
}
void display() {
image (widg, wCoord.x, wCoord.y);
}
boolean isOver() {
return mouseX > wCoord.x && mouseX < wCoord.x + widg.width &&
mouseY > wCoord.y && mouseX < wCoord.y + widg.height;
}
}