OutOfMemory when manipulating images - processing

This produces an OutOfMemory exception after running for a few seconds. Any ideas?
PGraphics img;
void setup() {
size(500, 500);
img = createGraphics(width, height, JAVA2D);
// this is here just for the testcase because else I get a
// NullPointerException too (probably a harmless Processing bug)
img.beginDraw(); img.endDraw();
}
void draw() {
PGraphics tmpImg = createGraphics(img.width, img.height, JAVA2D);
tmpImg.beginDraw();
tmpImg.image(img, 0, 0);
tmpImg.endDraw();
tmpImg.dispose();
}

Mat's right, you're not supposed to instantiate a new PGraphics each frame.
You could simply do something like this:
PGraphics img;
void setup() {
size(500, 500);
img = createGraphics(width, height, JAVA2D);
// this is here just for the testcase because else I get a
// NullPointerException too (probably a harmless Processing bug)
img.beginDraw(); img.endDraw();
}
void draw() {
image(img, 0, 0);
}
because PGraphics extends PImage.
Typically you'd use the basic PImage API, but if you'd need to draw shapes onto a bitmap or fake 'layers', you could use PGraphics in conjunction with PImage, but just don't allocate a new PGraphics 30 to 60 times a second.

Related

Processing P3D not rendering properly

I tried to make a simple 3d spinning cube in processing.
int size = 100;
float angle = 0;
void setup() {
size(500, 500, P3D);
}
void draw() {
lights();
translate(width/2, height/2, 0);
rotateY(angle);
rotateX(angle);
background(0);
box(size);
angle+=0.05;
}
When i run it, i got a nice spinning cube but there is some problem in rendering.
Found a similar thread with no answer:-
Processing P3D Animation leaving artifacts behind
Image Depicting the problem
Although I could not found the reason for this weird effect. But here is a quick hack which worked out for me.
Instead of using the background function to fill the background, simply draw a filled rectangle every frame.
int size = 100;
float angle = 0;
void setup() {
size(500, 500, P3D);
}
void draw() {
//black
fill(0);
//rectangle to fill the canvas
rect(0,0,width,height);
lights();
fill(255);
translate(width/2, height/2, 0);
rotateY(angle);
rotateX(angle);
box(size);
angle+=0.05;
}

How to create a mask from Polygons (processing)?

I am trying to create from a custom shape a mask for an image.
In processing I came up with this:
Image img;
PImage img2;
PGraphics mGraphic;
void setup(){
img = loadImage("mask.jpg");
img2 = loadImage("test.jpg");
mGraphic = createGraphics(1024,1024, JAVA2D);
size(img.width, img.height);
}
void draw(){
background(255);
mGraphic.beginDraw();
mGraphic.background(0);
mGraphic.ellipse(mouseX, mouseY, 400, 400);
mGraphic.endDraw();
img2.mask(mGraphic);
image(img2,0,0);
}
Above code will create a ellipse that will be the mask of the image.
I would like to achieve the same with a custom shape generated by Polygons:
import java.awt.Polygon;
PImage img;
PImage img2;
PGraphics mGraphic;
CustomShape myShape = new CustomShape();
void setup(){
img = loadImage("mask.jpg");
img2 = loadImage("test.jpg");
mGraphic = createGraphics(1024,1024, JAVA2D);
myShape.addPoint(25, 25);
myShape.addPoint(275, 25);
myShape.addPoint(275, 75);
myShape.addPoint(175, 75);
myShape.addPoint(175, 275);
myShape.addPoint(125, 275);
myShape.addPoint(125, 75);
myShape.addPoint(25, 75);
smooth();
// img2.filter(INVERT);
size(img.width, img.height);
}
void draw(){
background(255);
stroke(0);
myShape.display();
img2.mask(myShape);
image(img2,0,0);
}
class CustomShape extends Polygon {
void display() {
stroke(0);
fill(0);
beginShape();
for (int i=0; i<npoints; i++) {
vertex(xpoints[i], ypoints[i]);
}
endShape(CLOSE);
}
}
Unfortunately, this code will give me an error: The method mask(int[]) in the type PImage is not applicable for the arguments (Masking_image_1.CustomShape)
Is this even possible to get the same result as my first code, but then with the use of a custom shape? And how can I solve that?
If there are any questions left, please let me know. Above code will work inside Processing.
Well, your error says it all: the mask() function does not know what to do with a CustomShape parameter. The parameter needs to be a PImage or a mask array. More info can be found in the reference.
To use your custom shape, what you want to do is draw that custom shape to a PGraphics (which is a subclass of PImage), and then use that PGraphics as the mask. You'd do that using the createGraphics() function. Again, more info can be found in the reference.

why is the ball not in the center of the window?

The code:
class Attractor {
PVector location;
float mass;
Attractor() {
location = new PVector(width/2, height/2);
mass = 5;
}
void display() {
stroke(0);
fill(125);
ellipse(location.x, location.y, mass*10, mass*10);
}
}
Attractor a = new Attractor();
void setup()
{
size(640, 360);
}
void draw()
{
background(255);
a.display();
}
The location of the ball is in Attractor object, that is, PVector(width/2, height/2).
So I wonder why when I run the code, it's not in the center but on the right and up side of the window.
It's because you create your Attractor before the setup() function is called. The width and height haven't been set yet, so they're at the default of 100.
To fix this, just make sure you create your Attractor after you call the size() function:
Attractor a;
void setup()
{
size(640, 360);
a = new Attractor();
}

Re-sizing screen not the expected size

int displayX, displayY;
final int screenX=200, screenY=200; // display size
void setup() {
background(255);
displayX=displayWidth;
displayY=displayHeight;
size(screenX, screenY);
}
void mouseClicked() {
if (width==screenX) {
frame.setSize(displayX, displayY);
setSize(displayX, displayY);
println(width +" "+height);
} else {
frame.setSize(screenX, screenY);
setSize(screenX, screenY);
println(width +" "+height);
}
}
void draw() {
fill(33, 33, 33);
rect(0, 0, screenX, screenY);
fill(77, 77, 77);
rect(0, 0, screenX-20, screenY-20);
}
full code
press b to start beta - left mouse click change the size
I want a small size on startup (screenX).
After a click it grows to the display size.
After another click it gets the small size again.
But after changing the size the sizes aren't correct.
I see that on the border. I've everywhere a border around my "star". But this is only on top and left correct.
I also tested it with a lineal.
Processing 2.2.1
Windows 7
Step one is to check out the Processing reference.
From the size() documentation:
The size() function can only be used once inside a sketch, and it cannot be used for resizing.
So, you can't use the size() function the way you're trying to use it. Instead, you can access the frame variable directly:
frame.setSize(200, 200);
You might toggle the frame's size like this:
boolean big = false;
void setup(){
size(200, 200);
}
void mouseClicked(){
if(big){
frame.setSize(200, 200); //set the window size
big = false;
}
else{
frame.setSize(400, 400); //set the window size
big = true;
}
}
void draw(){
background(0);
ellipse(mouseX, mouseY, 10, 10);
}
However, if you run that program, you might notice something like this:
The window has increased size, but the actual canvas where things get drawn hasn't. So you get a gray area, and mouse events aren't detected correctly. To fix that problem, you have to set the size of the canvas as well, by calling the setSize() function:
boolean big = false;
void setup(){
size(200, 200);
}
void mouseClicked(){
if(big){
frame.setSize(200, 200); //set the window size
setSize(200, 200); //set the canvas size
big = false;
}
else{
frame.setSize(400, 400); //set the window size
setSize(400, 400); //set the canvas size
big = true;
}
}
void draw(){
background(0);
ellipse(mouseX, mouseY, 10, 10);
}

Change object by pressing button while showing animation

I'm trying to add animation in my code. What I have so far is an object that can be changed by pressing a button. So every time you press the button, the object changes (it is a tree and I'm changing its branches). Is it possible to add some kind of animation like snow? The problem with that is that I have to put it inside the draw method so it will be called automatically and make us think that it is animation. Thus, I also have to add the background / button and everything all the time. But I can't do that with my main object (tree) as I want to change it only when you press the button.
Is there any solution to that?
Thanks in advance
To persist some objects while refreshing others, you either:
Refresh only part of the screen. Like, draw a shape (rect or whatever) with background colour erasing only part of screen
Conditionally draw selected objects. Use flags to selective draw what you need, every draw, and use background() to clear the whole screen every draw cycle.
Use layers. Erase one layer and not other as you need, display all them in draw. This is usually done with PGraphics objects. Search processing + layers to see samples. Here and/or in processing forum.
EDIT:
Here some simple examples of each approach:
1.
/**
* A very simple example of erasing just part of the screen to
* selective persist draws
**/
void setup() {
size(400, 400);
background(0);
noStroke();
}
void draw() {
fill(0);
rect(0, 0, width/2, height);
fill(120);
ellipse(width/4, frameCount%width, 100, 100);
}
void mouseMoved() {
fill(255);
ellipse(mouseX, mouseY, 10, 10);
}
2.
/**
* A very simple example of conditionally draw stuf
* to selective persist draws
**/
ArrayList <PVector> points = new ArrayList <PVector>();
boolean showBalls = true; // any key to toogle
void setup() {
size(400, 400);
background(0);
noStroke();
}
void draw() {
background(0);
fill(30);
rect(frameCount%width, 100, 200, 200);
fill(120);
ellipse(width/2, frameCount%width, 150, 150);
fill(255);
if (showBalls) {
for (PVector p : points) {
ellipse(p.x, p.y, 10, 10);
}
}
if (points.size() > 500) {
points.clear();
}
}
void mouseMoved() {
ellipse(mouseX, mouseY, 10, 10);
points.add(new PVector(mouseX, mouseY));
}
void keyPressed() {
showBalls = !showBalls;
}
3.
/**
* A very simple example of using PGraphics as layers
* to selective persist draws
**/
PGraphics layer;
void setup() {
size(400, 400);
layer = createGraphics(width, height);
layer.beginDraw();
layer.fill(255);
layer.endDraw();
background(0);
noStroke();
}
void draw() {
background(0);
fill(30);
rect(frameCount%width, 100, 200, 200);
fill(120);
ellipse(width/2, frameCount%width, 150, 150);
image(layer, 0, 0);
}
void mouseMoved() {
layer.beginDraw();
layer.ellipse(mouseX, mouseY, 10, 10);
layer.endDraw();
}

Resources