Extracting an image from an array in Processing - arrays

Does anyone have any suggestions on what might be going wrong with this code? I'm trying to load tiles of images into a large array and then display them. Later on I'll shuffle the pieces. The issue I'm running into is seen near the bottom. I have a for loop that should plug the value of i into the output array and display the relevant image at that index value. Instead I get a null pointer exception. If I replace the letter i with an integer it works perfectly. What could be preventing processing from passing that value if i into the array? Any thoughts? Thanks.
int tileSize = 100;
PImage out; PImage sample;
PImage img;
PImage img2;
String[] imageNames = {"arctic_fox.jpg", "bbridge_in_the_am.jpg", "Kali2.jpg"};
PImage[] images = new PImage[imageNames.length];
//PImage[] output = new PImage[((1440/tileSize)*imageNames.length)*(900/tileSize)];
PImage[] output = new PImage[2000];
int tintScale = 200;
void setup() {
fullScreen();
for (int i=0; i < imageNames.length; i++) {
String imageName = imageNames[i];
images[i] = loadImage(imageName);
}
out = createImage(width, height, RGB);
noLoop();
println("test");
}
void draw() {
background(0);
println(width, height);
println(output.length);
int counter=0;
for (int i = 0; i < imageNames.length; i++) {
img = loadImage(imageNames[i]);
img.resize(0,900);
for (int y=0; y<img.height; y+=tileSize) {
for (int x=0; x<img.width; x+=tileSize/3) {
sample = img.get(x, y, tileSize, tileSize);
output[counter] = sample;
tint(255, tintScale);
counter++;
//println(counter);
//image(out, random(0, width-img_x), random(0, height-img_y));
}
//image(output[i],30,30);
}
}
for (int i=0;i<output.length;i++){
image(output[30],i*tileSize,i*tileSize);
}
//for (int y=0; y<out.height; y+=tileSize) {
// for (int x=0; x<out.width; x+=tileSize) {
// i = 800;
// //tint(255, tintScale);
// image(output[i], x, y);
// }
//}
}

I hope you solved it, but this is the problem:
PImage[] output = new PImage[2000];
You are initializing the array with 2000 null values, and then enter less then 300 tiles. That's why you get a null pointer error. You have to calculate how large your array will be before you initialize it. Or perhaps better, use an arraylist:
ArrayList<PImage> output = new ArrayList<PImage>();
//to add a tile:
output.add(sample);
//to draw all tile:
for(int i = 0; i< output.size();i++)
{
image(output[i],i*tileSize,i*tileSize);
}
You can read more about arraylists here
Final note: as Kevin Workman says, loadImage() and this process of dividing into tiles does not belong in 'void draw()'. It should be in setup() or in a separate function, called from setup().

Related

How to avoid object overlapping and overtaking?

I am trying to draw circles from same y coordinate.
and creating arrays for xPos. I put the speed and xPos random, how to make sure they are not overlapping and the one behind it match the speed to the front one so it wouldn't overtake?
I have retried the code, but it still overlapping for some reason that I couldn't find out?
OK now I initialise the k with i+1, so whichever behind it.
and I ran flow chart as well, the logic looks alright, still not doing what it should being doing.
int Num=10;
float dia=50;
float[] xPos= new float[Num];
float[] xSpeed=new float[Num];
void setup() {
size(300, 300);
for (int i= 0; i<xPos.length; i++) {
xPos[i]=random(-dia*Num);
xSpeed[i]=3;
boolean overlapping=false;
for(int k=;k<xPos.length;k++){
float newPos=xPos[k];
float dist=(newPos-xPos[i]);
if(dist<dia+50){
overlapping=true;
break;
}
}
if(!overlapping){
draw();
}
}
}
void draw() {
background(255);
drawBall();
moveBall();
reset();
}
void drawBall() {
for (int i= 0; i<xPos.length; i++) {
circle(xPos[i], 50, 50);
}
}
void moveBall() {
for (int i= 0; i<xPos.length; i++) {
xPos[i]+=xSpeed[i];
}
}
void reset() {
for (int i= 0; i<xPos.length; i++) {
if (xPos[i]>width) {
xPos[i]=0;
}
}
}
how to make sure they are not overlapping
For this, you could naively check if the new position has already been taken by another such as follows (I haven't run the code, so i probably has bugs, think of it more as a pseudocode):
boolean isItTaken(float[] xPos, float newPos) {
for (int i= 0; i<xPos.length; i++) {
if (abs(newPos - xPos[i]) < circleSize) return true;
}
return false;
}
for (int i= 0; i<xPos.length; i++) {
float newPos = random(-50);
while (isItTaken(xPos, newPos)) {
newPos = random(-50);
}
}
I'm sure there are better methods though. Also I think using ArrayList is better than using a simple array.
and the one behind it match the speed to the front one so it wouldn't overtake?
You could set it as a constant number? If you want it to be random, but slower than the previous one, you could set the upper limit of the random function to be the speed of the previous one such as(again, probably buggy):
ArrayList<Float> xSpeed = new ArrayList<Float>;
for (int i= 0; i < Num; i++) {
xSpeed.push(random(2, xSpeed.get(xSpeed.length - 1)));
}

How can I fix this error : 'Cannot invoke loadPixels() on the array type PImage[]'?

I'm kind of a beginner with Processing and I've been having difficulty with my pixel array. I have 10 images numbered from 0-9 that are being shown one after another... What I am trying to do on top of that is take each image and change its brightness level, turning it either white or black.
I've already tried to just change the brightness using one image, so not an array of images which works perfectly! But when joining those two together it doesn't work for me.
int maxImages = 10; // The number of frames in the animation
int imageIndex = 00; //initial image to be displayed first
PImage[] picture = new PImage[maxImages]; //the image array
void setup() {
size(500, 500); //size of sketch
frameRate(1); //frames processed per second
//loading images with numbered files into the array
for (int i = 0; i< picture.length; i++) {
picture[i] = loadImage("spast_" + i + ".jpg");
}
}
void draw() {
image(picture[imageIndex], 0, 0); //dispaying one image
loadPixels(); //accessing pixels
picture.loadPixels(); //accessing the image pixels too
//THIS is where it stops me and gives me 'Cannot invoke loadPixels() on the array type PImage[]'
for (int x = 0; x < width; x++) { //loops through every single x value
for (int y = 0; y < height; y++) { //loops through every single y value
int loc = x + y*width; // declare integer loc
float b = brightness(picture.pixels[loc]); //give me the brightness of pixels
if (b < 150) { //if the pixel is lower than 150
pixels[loc] = color(0); //then make those pixels black
} else { //otherwise
pixels[loc] = color(255); //make pixels white
}
}
}
imageIndex = (imageIndex + 1) % picture.length; //increment image index by one each cycle
updatePixels(); //when finished with the pixel array update the pixels
}
I'm expecting as each image is displayed it brightness value is changed and then it goes on to image 2 and so on...
Your picture variable is an array of PImage instances. You can't call loadPixels() on the array itself. You have to get a PImage at a specific index of the array, and then call the loadPixels() function on that instance.
Here's an example:
picture[0].loadPixels();
This line of code gets the PImage at index 0 and calls the loadPixels() function on it.
Note that you're already doing something pretty similar with this line:
image(picture[imageIndex], 0, 0);
Shameless self-promotion: here is a tutorial on arrays in Processing.
This is the updated and working code:
int maxImages = 10; // The number of frames in the animation
int imageIndex = 0; //initial image to be displayed first
PImage[] picture = new PImage[maxImages]; //the image array
void setup() {
size(500, 500); //size of sketch
frameRate(1); //frames processed per second
//loading images with numbered files into the array
for (int i = 0; i< picture.length; i++) {
picture[i] = loadImage("spast_" + i + ".jpg");
}
}
void draw() {
loadPixels(); //accessing pixels
image(picture[imageIndex], 0, 0); //dispaying one image
imageIndex = (imageIndex + 1) % picture.length; //increment image index by one each cycle
picture[imageIndex].loadPixels(); //accessing the image pixels in the array
for (int x = 0; x < width; x++) { //loops through every single x value
for (int y = 0; y < height; y++) { //loops through every single y value
int loc = x + y*width; // declare integer loc
float b = brightness(picture[imageIndex].pixels[loc]); //give me the brightness of pixels
if (b < 150) { //if the pixel is lower than 150
pixels[loc] = color(0); //then make those pixels black
} else { //otherwise
pixels[loc] = color(255); //make pixels white
}
}
}
updatePixels(); //when finished with the pixel array update the pixels
}

get position of 2D array of JLabels

First post here but long time reader, been searching through but cant find a post that exactly helps my problem.
I am trying to create 2D grid of JLabels with mouselisteners and retrieve the X / Y position of the clicked JLabel but cant find a way to do it. I have tried a few ways I found out on this site but nothing is working.
currently I have the following....
pcenter.setLayout(new GridLayout(game.getXSize(), game.getYSize()));
pcenter.setBorder(new EmptyBorder(8,8,8,8));
pcenter.setPreferredSize(new Dimension((game.getXSize() * 30), (game.getYSize() * 30)));
gamegrid = new JLabel[game.getXSize()][game.getYSize()];
for ( int i = 0; i < game.getXSize(); i++) {
for (int j = 0; j < game.getYSize(); j++) {
gamegrid[i][j] = new JLabel();
gamegrid[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
gamegrid[i][j].addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
}
});
pcenter.add(gamegrid[i][j]);
}
}
'game' is an object that houses a 2D array of objects for which i want to pass in the same co-ordinates of the JLabel clicked. E.G clicking on gamegrid[2][5] will contact game.plots[2][5].
whenever i try and make a variable to store 2 and 5 it wants to make the method FINAL, and if I put the method inside the MouseAdapter() it wants to make 'i' or 'j' FINAL.
please help :) thanks in advance.
Just figured it out! I'll post here just encase someone else would like to know.
I created 3 other variables in the class:
private static Object source;
private static int currentX, currentY;
then the current MouseListener, where it is now, I added the following:
for ( int i = 0; i < game.getXSize(); i++) {
for (int j = 0; j < game.getYSize(); j++) {
gamegrid[i][j] = new JLabel();
gamegrid[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
gamegrid[i][j].addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
source = e.getSource(); //added this to get the mouseevent object.
XYsource(); // this is a method to turn the object source
into X and Y coords.
}
});
pcenter.add(gamegrid[i][j]);
}
}
and finally the following method to turn the Object source into the X and Y co-ordinates
public static void XYsource() {
int maxX = game.getXSize();
int maxY = game.getYSize();
for(int i = 0; i < maxX; i++) {
for(int j = 0; j < maxY; j++){
if (gamegrid[i][j] == source) {
currentX = i;
currentY = j;
}
}
}
updateXY(); // this is just a method to set text on the screen showing
the X and Y coordinates to test the MouseListener
}

Array of text don't fade out until the last one is appended

I want to make a group of array fade out until the last array in this group was appended. for example, I use append to create zoog[0], zoog[1], zoog[2], and I want these three objects not fadeout until zoog[2] is created and wait for a second, the same situation with zoog[3], zoog[4],zoog[5], these three objects don't fadeout until zoog[5] is created. But now what I can do is make each object fadeout as soon as it is created.
Zoog[]zoog = new Zoog[1];
float count=0;
int xpos =0;
int ypos =0;
String message="haha";
int ntextsize = 20;
int nopacity =200;
int thistime = 0;
int thiscount = 0;
//Zoog zoog;
void setup() {
size(400, 400);
xpos = int(random(width/2-200, width/2+40));
ypos = int(random(height/2, height/2-40));
zoog[0] = new Zoog(xpos,ypos,message,nopacity);
}
void draw(){
background(255,255,255);
for(int i=0; i<zoog.length; i++){
// if(millis()-thistime>4000){
// zoog[i].disappear();
// }
zoog[i].jiggle();
zoog[i].display();
}
}
void mousePressed(){
count = count + 1;
// int thiscount = 0;
if(count%3 ==0){
xpos=int(random(30, width-30));
ypos=int(random(10, height-10));
}
else{
ypos = ypos+50;
// thiscount = thiscount +1;
// thistime = millis();
// }
}
nopacity = int(random(100,255));
// text(message, xpos, ypos);
Zoog b = new Zoog(xpos,ypos,message,nopacity);
zoog =(Zoog[]) append(zoog,b);
}
Zoog class
class Zoog {
int x;
int y;
String thatmessage;
int opaci =0;
Zoog(int xpo, int ypo, String thismessage, int opa) {
x = xpo;
y = ypo;
thatmessage = thismessage;
opaci = opa;
}
void jiggle() {
x = x+int(random(-2, 2));
y = y+int(random(-2, 2));
}
void display() {
fill(0, opaci);
text(thatmessage, x, y);
print("x position is "+ x);
print("y position is "+y);
}
void disappear() {
for (int j=0; j<255; j++) {
opaci = opaci -j;
}
}
}
If I understand correctly you want to make 3 zoogs and then start fading those three out until they're gone. If this is correct there are a couple of ways I'd go about doing this.
First, I wouldn't use an array especially if you're dynamically updating the amount inside it. If you want to do that I'd use, arraylists. Here's the javadocs reference. Basically you'd initialize an arraylist of Zoogs and put the zoog.add(new Zoog...) in the mousepressed. The good thing about arraylists is that they have a number of member functions that can help you manipulate them. For instance, you can check the size of the arraylist in your draw function instead of the time. Once you're above 3 start fading the first 3 out until they're dead (using a Zoog member function to say they're dead). You can check that "isDead" member function in your draw loop and remove the correct dead Zoog while in your for loop.
Here's a rough implementation, assuming you created an isDead function in your Zoog class that just returns whether the opacity is greater than 0:
void Draw()
{
for (Zoog zoog : zoogs) //for each statement simplifying the code -
//says for each Zoog in zoogs do
{
zoog.jiggle();
zoog.display();
}
if(zoogs.size() >= 3) {
for(int i = 0; i < 3; i++) {
zoogs.get(i).disappear();
}
}
if (zoogs.get(0).isDead() && zoogs.get(1).isDead() && zoogs.get(2).isDead()) {
zoogs.remove(2);
zoogs.remove(1);
zoogs.remove(0);
}
}
This is by no means a perfect example but it shows how to remove 3 zoogs at a time by lessening their opacity and checking whether they are dead. If you're clicking a million times then it will take a while for each chain of three to die.

Float / Array error reading from CSV

I'm missing something fundamental here but I can't seem to find out what from all my research.
I have imported a csv file, split the string into floats, and now wish to connect all points to all other points with a line. My code is as follows:
String [] data;
void setup () {
size(300, 300);
background(255);
data = loadStrings("points.csv");
for (int i = 0; i < data.length; i++) {
String [] fields = split(data[i], ',');
float t = float(fields[0]);
float n = float(fields[1]);
float x = float(fields[2]);
float y = float(fields[3]);
ellipse(x, y, 10, 10);
line(x, y, x[i], y[i]);
}
}
The error message is "The type of expression must be an array type but it resolved to float"
I'm sure this is extremely basic but, I dont understand why x[i] or y[i] are not seen as an array type.
I would really appreciate any help with this. Many thanks in advance.
Sam
*UPDATE***
An exract from the points.csv file is as follows:
219185750 rabih_takkoush 20.88521 19.49821
219185716 MoustaphaAjram 100.870896 59.515259
219185709 jinanejghosh 56.886441 35.489087
219185557 MoustaphaAjram 34.870904 78.515243
219185555 Mohammad8Itani 12.8946 49.48179
What I am trying to accomplish is plotting the various geolocations (whereby col 3 = x, col 4 = y) and then connecting all points with all other points with a line.
The following script works plotting all locations specified in the array within the script:
float[] x = { 50, 100, 150, 200,20,20 };
float[] y = { 10, 30, 20, 250,20,90 };
void setup () {
size(300, 300);
background(255);
}
void draw() {
for (int i = 0; i < x.length; i++) {
ellipse(x[i], y[i], 10, 10);
for (int j = 0; j < x.length; j++) {
line(x[j], y[j], x[i], y[i]);
}
}
}
What I wish to do is do the same, but reading columns 3 and 4 of the csv file.
You're splitting your data into iteration-scoped floats, then you try to access them as if they're both floats as well as arrays in your line() call. Try this:
String[] data;
float[] x, y, t, n;
void setup () {
size(300, 300);
data = loadStrings("points.csv");
int len = data.length;
x = new float[len];
x = new float[len];
t = new float[len];
n = new float[len];
for (int i=0; i<len; i++) {
String line = data[i];
String[] fields = split(line, ',');
t[i] = float(fields[0]),
n[i] = float(fields[1]),
x[i] = float(fields[2]),
y[i] = float(fields[3]);
}
// don't put draw instructions in setup,
// put them in draw. if you want to run once,
// issue a noLoop() so that happens.
noLoop();
}
void draw() {
float prevx = x[0], prevy = y[0];
for (int i=0, last=x.length; i<last; i++) {
ellipse(x[i], y[i], 10, 10);
line(prevx,prevy, x[i],y[i]);
prevx=x[i];
prevy=y[i];
}
}
Now we're storing the data from CVS in linked arrays that we can access throughout the sketch, rather than throwing them away after setup().
ok so if you go with the first code you made, you only need to change a few things, here is what you can do:
float[] x;
float[] y;
string[] data;
void setup () {
size(300, 300);
background(255);
data = loadStrings("points.csv");
x = new float[data.length];
y = new float[data.length];
for (int i = 0; i < data.length; i++) {
String [] fields = split(data[i], ',');
float t = float(fields[0]);
float n = float(fields[1]);
float x = float(fields[2]);
float y = float(fields[3]);
}
}
void draw() {
for (int i = 0; i < x.length; i++) {
ellipse(x[i], y[i], 10, 10);
for (int j = 0; j < x.length; j++) {
line(x[j], y[j], x[i], y[i]);
}
}
}
As you can see nothing really new, it's a mix between your initial code and the one you made for the csv.
And actually you mainly needed to declare your x and y variables as float[] instead of just float. But also there were some changes to make in the loop.
In this code you load the data in your arrays first (exactly like you did by declaring array's values in your code, but this time you read these values from your file), and then call your draw method as before.
hope it works now

Resources