Pixelated Video with Processing - java

I'm trying to load a video and then display it in a pixelated manner. It worked one time after loading for very long time, but then it stopped working - just a black screen and nothing comes up and without error message I wonder what goes wrong. Thanks.
import processing.video.*;
Movie movie;
int videoScale = 8;
int cols, rows;
void setup() {
size(640, 360);
background(0);
movie = new Movie(this, "movie.mp4");
movie.loop();
cols = width / videoScale;
rows = height / videoScale;
}
void draw() {
movie.loadPixels();
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
int x = i * videoScale;
int y = j * videoScale;
color c = movie.pixels[i + j * movie.width];
fill(c);
noStroke();
rect(x, y, videoScale, videoScale);
}
}
}
// Called every time a new frame is available to read
void movieEvent(Movie movie) {
movie.read();
}

You may be sampling from the wrong place here:
color c = movie.pixels[i + j * movie.width];
First off, i is your cols counter, which is the x dimension, the j is the rows counter, y dimension.
Secondly, you probably want to sample at the same scale, and therefore need to multiply by videoScale. You already have the x,y variables for that, so try sampling like this:
color c = movie.pixels[y * movie.width + x];
Alternatively, you can use a PGraphics instance as a frame buffer to draw into at a smaller scale (resample), then draw the small buffer at a larger scale:
import processing.video.*;
Movie movie;
int videoScale = 8;
int cols, rows;
PGraphics resized;
void setup() {
size(640, 360);
background(0);
noSmooth();//remove aliasing
movie = new Movie(this, "transit.mov");
movie.loop();
cols = width / videoScale;
rows = height / videoScale;
//setup a smaller sized buffer to draw into
resized = createGraphics(cols, rows);
resized.beginDraw();
resized.noSmooth();//remove aliasing
resized.endDraw();
}
void draw() {
//draw video resized smaller into a buffer
resized.beginDraw();
resized.image(movie,0,0,cols,rows);
resized.endDraw();
//draw the small buffer resized bigger
image(resized,0,0,movie.width,movie.height);
}
// Called every time a new frame is available to read
void movieEvent(Movie movie) {
movie.read();
}

Related

Whack-a-mole in Processing

I am working on a school project in Processing (Java Mode). We have a picture of how the game should look like.
So the task is to create a grid out of squares. Random squares should light up in red. If a red square is clicked, it should change colors to green and stay green.
What my code looks like at the moment:
Square[][] grid;
int cols = 20;
int rows = 20;
void setup() {
size(400, 400);
grid = new Square[cols][rows];
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
grid[i][j] = new Square(i*20, j*20, 20, 20);
}
}
}
void draw() {
background(0);
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
grid[i][j].display();
if (grid[i][j].x<mouseX && mouseX < grid[i][j].x + grid[i][j].w && grid[i][j].y<mouseY && mouseY < grid[i][j].y + grid[i][j].h && mousePressed) {
color col = color(0,204,0);
grid[i][j].update(col);
}
}
}
}
Class for squares:
class Square {
float x, y;
float w, h;
color c;
Square(float tempX, float tempY, float tempW, float tempH) {
x = tempX;
y = tempY;
w = tempW;
h = tempH;
c = color(0);
}
void display() {
stroke(0);
fill(c);
rect(x, y, w, h);
}
void update(color c) {
this.c = c;
}
}
So at the moment, every square you click turns green. I am not sure how to write the code, so that random squares change color to red and shuffle every 5 seconds.
Do you have any tips on how to proceed with the code or which thinking steps to take to be able to solve this task?
First, take your task:
So the task is to create a grid out of squares. Random squares should light up in red. If a red square is clicked, it should change colors to green and stay green.
and break it down:
create a grid out of squares: nicely done already !
Random squares should light up in red
If a red square is clicked
change colors to green and stay green
How do you use random numbers in Processing ?
The simplest method is using the random() method: you can pass two values and you'll get back a random number between those values.
Let's say you want to flip a coin so there's a (roughly) 50-50 change you get heads or tails. You could so something like:
if(random(0, 100) > 50){
println("head");
}else{
println("tails");
}
Could even be random(0.0, 1.0) > 0.5 for example, the idea is the same.
You could think of throwing a dice or a number of dices, etc.
Remember these are pseudo-random and in your own time can explore other pseudo random related methods such as randomGauss() and noise().
random() may be good enough for now, part 2 done :)
You're almost done with part 3:
if (grid[i][j].x<mouseX && mouseX < grid[i][j].x + grid[i][j].w && grid[i][j].y<mouseY && mouseY < grid[i][j].y + grid[i][j].h && mousePressed) {
but you need to also check if the clicked square is red.
Would nice to have some red squares to begin with. Let's assume color(204, 0, 0) is your red, you could simply add an additional check:
if(grid[i][j].c == color(204, 0, 0)){
println("red block clicked");
grid[i][j].c = color(0, 204, 0);
}
Which roughly turns your sketch into:
Square[][] grid;
int cols = 20;
int rows = 20;
final color RED = color(204, 0, 0);
final color GREEN = color(0, 204, 0);
void setup() {
size(400, 400);
grid = new Square[cols][rows];
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
grid[i][j] = new Square(i*20, j*20, 20, 20);
// roughly 50 - 50 % change a grid square will be red
if (random(0, 100) > 50) {
grid[i][j].update(RED);
}
}
}
}
void draw() {
background(0);
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
grid[i][j].display();
if (grid[i][j].x<mouseX && mouseX < grid[i][j].x + grid[i][j].w && grid[i][j].y<mouseY && mouseY < grid[i][j].y + grid[i][j].h && mousePressed) {
// if the square is red
if (grid[i][j].c == RED) {
// change colour to GREEN
grid[i][j].update(GREEN);
}
}
}
}
}
class Square {
float x, y;
float w, h;
color c;
Square(float tempX, float tempY, float tempW, float tempH) {
x = tempX;
y = tempY;
w = tempW;
h = tempH;
c = color(0);
}
void display() {
stroke(0);
fill(c);
rect(x, y, w, h);
}
void update(color c) {
this.c = c;
}
}
In terms of shuffling colours every 5 seconds I recommend:
for every 5 seconds you could use millis()
above there is an example of shuffling done in setup() though you might want to encapsulate a nested loop like that with the random condition in a void shuffle() function for example which you could easily call every 5 seconds.
note that this approach will reset green blocks to red, you might want an else in that condition to reset blocks to black (otherwise, with time, most will turn red), etc.
Have fun!
P.S. I tend to separate state data from representation. For example I would add a variable to keep track of each square state (e.g. OFF, INTERACTIVE, ACTIVATED), update a basic finite state machine, then render colours accordingly. What you have above is a tight coupling between the colour of a Square and it's state. For the homework you've got that's ok, but in the future, for more complex projects you might want to consider data flows through your program and how you represent it.

node's are not intersection while using loops inside of an array?

My problem is wherever i click a node appears and for the second click another node appears with connected edge...so i want that When i click at any location, the node should be generated at the closest grid intersection point. I tried using loops.
and i'm trying to do that without "class"
int n_partition=10;
int length = 101;
PVector[] position = new PVector[length];
int BallNum;
void setup() {
size(600, 360);
background(255);
}
void draw() {
fill(255);
grid();
fill(0);
}
void mousePressed(){
stroke(0);
BallNum++;
position[BallNum]= new PVector(mouseX, mouseY);
circle(position[BallNum].x, position[BallNum].y, 10);
if (BallNum > 1) {
line(position[BallNum].x,position[BallNum].y,position[BallNum-
1].x,position[BallNum-1].y);
line(position[1].x,position[1].y,position[BallNum].x,position[BallNum] .y);
}
for (int i = 0; i < position[BallNum].length; ++ i) {
position[BallNum] = position[BallNum].get(i);
position[BallNum] = position[BallNum].get((i+1) % position[BallNum].length);
line(position[BallNum].x, position[BallNum].y,
position[BallNum].x, position[BallNum].y);
}
}
I EXPECT THE NODE SHOULD GO TO THE CLOSEST INTERSECTION.
You've to calculate the nearest position of the mouse to a point on the grid. For that you've to know the width (tile_width) and the height (tile_height) of cell.
The index of the cell can be calculated by the dividing the mouse position to the size of a tile and round() the result to an integral value (e.g. round(mouseX / (float)tile_width)).
Don't draw anything in int the mousePressed callback. The only thing you've to do there is to add a pint to the list:
void mousePressed(){
int tile_width = width / n_partition; // adapt this for your needs
int tile_height = height / n_partition;
int x = round(mouseX / (float)tile_width) * tile_width;
int y = round(mouseY / (float)tile_height) * tile_height;
position[BallNum]= new PVector(x, y);
BallNum++;
}
All the drawing has to be done in draw(). Draw the lines and points in separate loops:
void draw() {
background(255);
grid();
// draw the lines in a loop
strokeWeight(3);
stroke(0, 0, 255);
for (int i = 0; i < BallNum; ++ i) {
int i2 = (i+1) % BallNum;
line(position[i].x, position[i].y, position[i2].x, position[i2].y);
}
// draw balls in a loop
strokeWeight(1);
stroke(0, 0, 0);
fill (255, 0, 0);
for (int i = 0; i < BallNum; ++i) {
circle(position[i].x, position[i].y, 10);
}
}
Note, the scene is consecutively redrawn in every frame. Before the scene is drawn, the entire window has to be "cleared" by background().
See the result:

Recalculate X and Y Coordinates From New Screensize

I'm trying to display tiles from an array I have so that they always fill the size of the screen when drawn together. I am ignoring aspect ratio for now.
Here's how my code works. I have tile objects that are passed on to a tileset (class for managing an array of tile objects), and then I iterate through the tileset array, returning each tile object id and rendering a subimage of my tileset image based on said ids.
Here's my mapUpdate method, which is called on every JFrame resize event:
public synchronized void mapUpdate(Screen screen) {
factorX = (float)(screen.getWidth() / scW);
factorY = (float)(screen.getHeight() / scH);
for (int i = 0; i < tileset.getRows(); i++) {
for (int j = 0; j < tileset.getCols(); j++) {
int x = tileset.getTile(i, j).getX();
int y = tileset.getTile(i, j).getY();
tileset.getTile(i, j).setX((int)(x * factorX));
tileset.getTile(i, j).setY((int)(y * factorY));
}
}
mapTiles.clear();
for (int i = 0; i * 70 < mapImage.getWidth(); i++) {
mapTiles.add(mapImage.getSubimage(70 * i, 0, 70, 70).getScaledInstance(screen.getWidth() / 10, screen.getHeight() / 10, Image.SCALE_SMOOTH));
}
}
mapTiles is an ArrayList of Images, and on each resize event it resets the arraylist, scales my subimages to 1/10th width and height, and then re-adds the newly sized images for me to pull out for rendering (the tileset image is only 3 tiles with an original size of 70x70).
And here is the componentResized method if you were curious:
public void componentResized(ComponentEvent e) {
canvas.setSize(app.getContentPane().getWidth(), app.getContentPane().getHeight());
if (level1 != null) {
level1.mapUpdate(this);
}
}
As you can see in my mapUpdate method, I attempt to get a float to multiply each current x and y value by to receive the new correct values (it will round the integers), but this doesn't work at all.
Is there any solution to easily re-calculate my X and Y coordinates so that the tiles are drawn correctly?
Your factorX should not be a float. It should be an int. If you use a float you will get rounding, so occasionally you will have a pixel gap between tiles because of rounding. If you just use an int then you don't have to worry about this. Then the location is just the factor * the index value of the for loop.
On the other hand the easiest solution is to just use a JPanel with a GridLayout. Then you can add a JLabel with an Image icon. The GridLayout will resize each component equally.
You can then even use the Stretch Icon and the images will be dynamically resized as the frame is resized.
SOLUTION courtesy of #MadProgrammer - The solution was to simply calculate the new X and Y "origins" for each tile. I still need to implement adjusting the position for tiles that have moved based on the newly calculated origins, but this solution works for tiles that do not move (again, simply recalculate the X and Y origin positions).
public synchronized void mapUpdate(Screen screen) {
int originX = screen.getWidth() / 10;
int originY = screen.getHeight() / 10;
for (int i = 0; i < tileset.getRows(); i++) {
for (int j = 0; j < tileset.getCols(); j++) {
tileset.getTile(i, j).setX((originX * j));
tileset.getTile(i, j).setY((originY * i));
}
}
mapTiles.clear();
for (int i = 0; i * 70 < mapImage.getWidth(); i++) {
mapTiles.add(mapImage.getSubimage(70 * i, 0, 70, 70).getScaledInstance(screen.getWidth() / 10, screen.getHeight() / 10, Image.SCALE_SMOOTH));
}
}

Slow map in java

I'm making a game in java, is a rpg, however, only with the map the game is slow.
The map is made ​​in TiledMap Editor, therefore, an XML that is read and loaded into an ArrayList. My PC is a dual-core 3.0, 4GB RAM, 1GB Video.
The do the rendering is done as follows:
//method of tileset class
public void loadTileset(){
positions = new int[1 + tilesX * tilesY][2];
int yy = 0;
int xx = 0;
int index = 0;
// save the initial x and y point of each tile in an array named positions
// positions[tileNumber] [0] - X position
// positions[tileNumber] [1] - Y position
for(int i = 1 ; i < positions.length; i++){
if(index == tilesX ){
yy += tileHeight;
xx = 0;
index = 0;
}
positions[i][0] = xx;
positions[i][1] = yy;
xx += tileWidth;
index++;
}
}
//method of map class
public void draw(Graphics2D screen){
//x and y position of each tile on the screen
int x = 0; int y = 0;
for(int j = 0; j < 20 ; j++){
for(int i = initialTile ; i < initialTile + quantTiles ; i++){
int tile = map[j][i];
if(tile != 0){
screen.drawImage(tileSet.getTileImage().getSubimage(tileSet.getTileX(tile), tileSet.getTileY(tile),tileSet.getTileWidth(), tileSet.getTileHeight()),x,y,null);
}
x += tileSet.getTileWidth();
}
x = 0;
y += tileSet.getTileHeight();
}
}
Am I doing something wrong?
Note: I'm new to the forum and to make matters worse I do not understand very much English, so excuse any mistake.
First of all, you should not create the subimages for the tiles during each call. Strictly speaking, you should not call getSubimage at all for images that you want to paint: It will make the image "unmanaged", and this can degrade rendering performance by an order of magnitude. You should only call getSubimage for images that you do not want to render - for example, when you are initially creating individual images for the tiles.
You obviously already have a TileSet class. You could add a bit of functionality to this class so that you can directly access images for the tiles.
Your current code looks like this:
screen.drawImage(
tileSet.getTileImage().getSubimage(
tileSet.getTileX(tile),
tileSet.getTileY(tile),
tileSet.getTileWidth(),
tileSet.getTileHeight()),
x,y,null);
You could change it to look like this:
screen.drawImage(tileSet.getTileImage(tile), x,y,null);
The getTileImage(int tile) method suggested here could then obtain tiles that have been stored internally.
I'll sketch a few lines of code from the tip of my head, you'll probably be able to transfer this into your TileSet class:
class TileSet
{
private Map<Integer, BufferedImage> tileImages;
TileSet()
{
....
prepareTileImages();
}
private void prepareTileImages()
{
tileImages = new HashMap<Integer, BufferedImage>();
for (int tile : allPossibleTileValuesThatMayBeInTheMap)
{
// These are the tiles that you originally rendered
// in your "draw"-Method
BufferedImage image =
getTileImage().getSubimage(
getTileX(tile),
getTileY(tile),
getTileWidth(),
getTileHeight());
// Create a new, managed copy of the image,
// and store it in the map
BufferedImage managedImage = convertToARGB(image);
tileImages.put(tile, managedImage);
}
}
private static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
// This is the new method: For a given "tile" value
// that you found at map[x][y], this returns the
// appropriate tile:
public BufferedImage getTileImage(int tile)
{
return tileImages.get(tile);
}
}

How do I flip an image upside-down?

I was wondering if I could find some help on this problem. I was asked to use an image ("corn.jpg"), and flip it entirely upside down. I know I need to write a program which will switch pixels from the top left corner with the bottom left, and so on, but I wasn't able to get my program to work properly before time ran out. Could anyone provide a few tips or suggestions to solve this problem? I'd like to be able to write my code out myself, so suggestions only please. Please note that my knowledge of APImage and Pixel is very limited. I am programming in Java.
Here is what I managed to get done.
import images.APImage;
import images.Pixel;
public class Test2
{
public static void main(String [] args)
{
APImage image = new APImage("corn.jpg");
int width = image.getImageWidth();
int height = image.getImageHeight();
int middle = height / 2;
//need to switch pixels in bottom half with the pixels in the top half
//top half of image
for(int y = 0; y < middle; y++)
{
for (int x = 0; x < width; x++)
{
//bottom half of image
for (int h = height; h > middle; h++)
{
for(int w = 0; w < width; w++)
{
Pixel bottomHalf = image.getPixel(h, w);
Pixel topHalf = image.getPixel(x, y);
//set bottom half pixels to corresponding top ones?
bottomHalf.setRed(topHalf.getRed());
bottomHalf.setGreen(topHalf.getGreen());
bottomHalf.setBlue(topHalf.getBlue());
//set top half pixels to corresponding bottom ones?
topHalf.setRed(bottomHalf.getRed());
topHalf.setGreen(bottomHalf.getGreen());
topHalf.setBlue(bottomHalf.getBlue());
}
}
}
}
image.draw();
}
}
Thank you for your help!
See Transforming Shapes, Text, and Images.
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class FlipVertical {
public static BufferedImage getFlippedImage(BufferedImage bi) {
BufferedImage flipped = new BufferedImage(
bi.getWidth(),
bi.getHeight(),
bi.getType());
AffineTransform tran = AffineTransform.getTranslateInstance(0, bi.getHeight());
AffineTransform flip = AffineTransform.getScaleInstance(1d, -1d);
tran.concatenate(flip);
Graphics2D g = flipped.createGraphics();
g.setTransform(tran);
g.drawImage(bi, 0, 0, null);
g.dispose();
return flipped;
}
FlipVertical(BufferedImage bi) {
JPanel gui = new JPanel(new GridLayout(1,2,2,2));
gui.add(new JLabel(new ImageIcon(bi)));
gui.add(new JLabel(new ImageIcon(getFlippedImage(bi))));
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) throws AWTException {
final Robot robot = new Robot();
Runnable r = new Runnable() {
#Override
public void run() {
final BufferedImage bi = robot.createScreenCapture(
new Rectangle(0, 660, 200, 100));
new FlipVertical(bi);
}
};
SwingUtilities.invokeLater(r);
}
}
Whenever you're swapping variables, if your language doesn't allow for simultaneous assignment (and Java doesn't), you need to use a temporary variable.
Consider this:
a = 1;
b = 2;
a = b; // a is now 2, just like b
b = a; // b now uselessly becomes 2 again
Rather than that, do this:
t = a; // t is now 1
a = b; // a is now 2
b = t; // b is now 1
EDIT: And also what #vandale says in comments :P
If you are able to use the Graphics class, the following may be of use:
http://www.javaworld.com/javatips/jw-javatip32.html
And the Graphics class documentation:
http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html
Instead of using
Pixel bottomHalf = image.getPixel(h, w);
Pixel topHalf = image.getPixel(x, y);
//set bottom half pixels to corresponding top ones?
bottomHalf.setRed(topHalf.getRed());
bottomHalf.setGreen(topHalf.getGreen());
bottomHalf.setBlue(topHalf.getBlue());
//set top half pixels to corresponding bottom ones?
topHalf.setRed(bottomHalf.getRed());
topHalf.setGreen(bottomHalf.getGreen());
topHalf.setBlue(bottomHalf.getBlue());
You should have stored the bottomHalf's RGB into a temporary Pixel and used that to set topHalf after replacing bottomHalf's values (if you follow). You could have also really used something like this.... assuming your pixel operates on integer rgb values (which would have improved your main method).
private static final Pixel updateRGB(Pixel in, int red, int green, int blue) {
in.setRed(red); in.setGreen(green); in.setBlue(blue);
}
You want to flip the image upside down, not swap the top and bottom half.
The loop could look like this.
int topRow = 0;
int bottomRow = height-1;
while(topRow < bottomRow) {
for(int x = 0; x < width; x++) {
Pixel t = image.getPixel(x, topRow);
image.setPixel(x, topRow, image.getPixel(x, bottomRow));
image.setPixel(x, bottomRow, t);
}
topRow++;
bottomRow--;
}

Categories