Is there a way to visually stretch a processing sketch?

Hi,

Is there a way to stretch a Processing sketch? Either in a vertical or horizontal direction? This is a general question and something I would like to apply to several Processing sketches I’m working on, either in 2D or 3D.

What I mean is, if we were to stretch something in a horizontal direction everything would get longer horizontally, eventually everything would just look like horizontal lines if stretched far enough.

I am guessing the entire output would have to be put through some kind of filter or effect to be able to do this. If anyone has any ideas how to approach this please let me know.

thanks, Nick

1 Like

You mean the output on the screen, or while animating? You could get() it into a PImage and then resize using the width/height parameters.

1 Like

Hi noel,

Thanks for the suggestion.

I’ve never used get() before.

Is this how you would use it?

  int xstretch = width;      // how much I want to stretch the width
  int ystretch = height;     // how much I want to stretch the height
  PImage screen;
  
 screen =  get(xstretch, ystretch);

I see there’s an object called copy() too. Maybe I will look into that too.

No, you use screen = get(xstartpoint, ystartpoint, desired_width, desired_height); to get what you desire which is on screen and than use screen.resize(desired_width, desired_height); to ‘stretch’.

3 Likes

@noel,

Thanks for the insight into that. I was able to get some results. It seems a little slow and buggy though. And one time I received an error that said with my graphics card I cant go above 15000 for the screen dimentions. I guess what I am going for is an extreme stretch where the shapes just become lines.

I am posting my code. I am using a midi controller and sending OSC messages into Processing, so that’s what some of this code is related to.

If anyone has an idea to improve upon this let me know.

import oscP5.*;

//OSC receive
OscP5 oscP5;


float desired_width = width;

float  desired_height = height;
PImage screen;

void setup() {

  fullScreen(P2D, 2);  
  //size(800, 800, P3D);
  oscP5 = new OscP5(this, 12000);

}


void oscEvent(OscMessage theOscMessage) {  

  float value1 = theOscMessage.get(0).floatValue();

  if (theOscMessage.checkAddrPattern("/dw")) {
    if (value1 > 0) {
      desired_width = value1;
    } else {
      desired_width = width;
    }
  }

  float value2 = theOscMessage.get(0).floatValue();

  if (theOscMessage.checkAddrPattern("/dh")) {
    if (value2 > 0) {
      desired_height = value2;
    } else {
      desired_height = height;
    }
  }
}

void draw() {

  strokeWeight(50);
  stroke(50, 50, 200);
  fill(150, 50, 20);

  ellipse ( width/2, height/2, 500, 500);

  screen = get(0, 0, (int)desired_width, (int)desired_height);
  
  //  screen = get(0, 0, width, height);   i tried this too

  screen.resize((int)desired_width, (int)desired_height);
  
  image(screen, 0, 0);

  println(desired_width);


}

1 Like

I confess I’m confused and I need some help to understand this
In draw() you are taking a print with get() using desired_width and desired_height.
And than you paste/resize it with same values. How will the oscEvent synchronize in the middle of a frame?

1 Like

@noel THank you for taking a look.

I was using println() just to make sure the OSC information was making it into Processing. I am trying to stretch this project in real time.
Here’s a few images so you can see what’s happening

here’s the code. I tried a few different approaches for displaying the image like:
image(screen, 0, 0, (int)desired_width, (int)desired_height );

and

image(screen, 0, 0, width, height );

It’s not really doing much to the height dimension. Maybe this is a crazy idea. I can do it pretty easily in some video software, like Jitter, so I figured it would be easy to accomplish. Maybe there is a better approach.

import oscP5.*;

//OSC receive
OscP5 oscP5;


float desired_width = width;

float  desired_height = height;
PImage screen;

void setup() {

  fullScreen(2);  
  //size(800, 800, P3D);
  oscP5 = new OscP5(this, 12000);
}


void oscEvent(OscMessage theOscMessage) {  

  float value1 = theOscMessage.get(0).floatValue();

  if (theOscMessage.checkAddrPattern("/dw")) {
    if (value1 > 0) {
      desired_width = value1;
    } else {
      desired_width = width;
    }
  }

  float value2 = theOscMessage.get(0).floatValue();

  if (theOscMessage.checkAddrPattern("/dh")) {
    if (value2 > 0) {
      desired_height = value2;
    } else {
      desired_height = height;
    }
  }
}

void draw() {

  strokeWeight(50);
  stroke(50, 50, 200);
  fill(150, 50, 20);

  ellipse ( width/2, height/2, 500, 500);

  screen = get(0, 0, (int)desired_width, (int)desired_height);

  screen.resize((int)desired_width, (int)desired_height);

  image(screen, 0, 0, (int)desired_width, (int)desired_height );
  
  //  image(screen, 0, 0, width, height );
  
  println(desired_height);
}

1 Like

I’ll have to make another topic/question before I can comment.

You could have a look at pixelDensity() if you have a High Definition Display. You can check wether you have one with the displayDensity() method. It‘ll return 2 if you have one, Else 1. You can probably just Print it out to check.

I have to say though, that i never used it, so i don‘t know if that‘s really gonna do something for you…

1 Like

Since I don’t have enough skills to look into the Proccessing’s core code, I searched in the documents and found what I’d read before.

Key presses and mouse movements are stored until the end of draw(), where they can take action that won’t disturb drawing that’s currently in progress.

Since this document is from 2014 I searched for changes in the later released version 3.0 here , but could not find anything related. But in the back of my mind I’ve some memory that somewhere I saw something has changed.
Now if the quote above is also true for oscP5 events your code could not work, but as you have outcome I searched in the OscP5 lib docs where is said.

oscP5 locates functions inside your sketch and will link incoming OSC message to matching functions automatically

Now I don’t know if you can write one line getting the image, and immediately a line following setting the image with the same parameters. In my logic there is no orderly synchronizing.
But as this is obviously a beginner question I leave it up to the experts to guide you.

2 Likes

@Lexyth thanks for the reply. It looks like I have a pixel density of 2. Even if I have a low quality version of what I am trying to do that would be fine with me, just trying to get that effect.

@noel thank you for looking into that for me. The OSC stuff works really well. You can get the OSC data in a void oscEvent() code, then assign it to a global variable in void draw(). It works great. In previous attempts I have examined every pixel and it’s pretty cpu intensive. I was trying to see if there was a way to just grab everything and stretch it. Stretching the screen dimentions is exactly what I wanted to do. But it is slow and stuttery. I think processing is still trying to draw everything with the stretched dimentions. Maybe I need a new block of code called void stretch() after draw where all the screen stretching takes place. Thank you everyone for looking into this.

2 Likes

No, the get() function makes a pixel array of the selected area. It does not redraw shapes, but does the math to calculate neighbour pixels when resized. I would like to know how this is done, but could not find a tutorial about this until now… I am going to do some tests to verify the speed of such strech transformations… Are you still using the same code as posted above with some reasonable results? Because this would prove an immediate exchange of variable values within one frame, differently then mouse and key input.

Maybe… just an idea to work with… To overcome the problem of getting, resizing and setting the image in one frame you could set them further apart in time, by using even and odd frameCounts.
Like

  if(frameCount % 2 == 0) get and resize
  if(frameCount % 2 != 0) set

This in reality would set your frame rate visually to 30, but would still be good enough.

The idea suggested above is not a good idea.
Better is using a boolean switching on/off on each trigger event, to set get() and image() apart in time. If you use in one frame get() and image() with a mouse event, code will not work. So the mouse event will really wait for a new frame start. (However I noticed that once in a while it does resize, so that is not that accurate.)
The code below is an example of using a boolean to separate get() and image() in one frame. You will also notice of course, that a positive resizing, will blur the image . So if you don’t have too much shapes it is better to resize each individual shape with a factor on each event.
I would like to know where I can find documentation to find out if all other events other then mouse and key, like for instance Serial, will receive variable changes within a frame. Maybe @jeremydouglass ?
I have no equipment to try the OscP5,( but while writing this I remember that I can try it with a Bluetooth event from another phone, I’ll try this later.)

Edit: I have my answers now. When I looked into the core java files (also serial) a year ago I found it very complex, but now I think it’s not that hard, and it’s well documented. Nice feeling that I had progress.

PImage pi;
int stretch = 500, old_stretch = 500;
boolean ch = false, mp = true, dnc = true;
// dnc is for not constantly draw in draw()

void setup() {
  size(500, 500);
  background(255);
  stroke(255, 0, 0);
  strokeWeight(20);
  fill(0, 0, 255);
  ellipse(250, 250, 400, 400);
}  

void draw() {
  if (!mp && dnc) {
    background(255);
    pi.resize(width, stretch);
    image(pi, 0, 0);
    dnc = false;
    old_stretch = stretch;
  } else if(mp && dnc){  
    pi = get(0, 0, width, old_stretch);
    dnc = false;
  }  
}   


void mousePressed() {
  if (stretch > 450) ch = false;
  if (!ch) stretch -= 50;
  else stretch += 50;
  if (stretch < 100) ch = true; 
  mp =! mp;
  dnc = true;  
} 
2 Likes

Looked at this post, and tried something. No idea if this is helpful, just wanted to share.

int xst;
int yst;
PImage screen;
boolean firstFrame=true;

void setup() {
  size(700,500);
    fill(#2ACCF2);
  rect(100,75,500,325);
  fill(255,0,0);
  circle(width/2,height/2,150);
  fill(0,0,255);
  circle(width/2,height/2,110);
}

void draw() {
  if(firstFrame==true) {
    screen = get(0,0,width,height);
  }
  if(frameCount>1) {
    firstFrame=false;}
      xst=500+2*frameCount;
      if(350-2*frameCount>10) {
  yst=350-2*frameCount;
      }
  screen.resize(xst,yst);
  background(205);
  imageMode(CENTER);
  image(screen,width/2,height/2,xst,yst);
   
}










2 Likes

You could use a PShader to do this, although their use can get quite advanced. https://processing.org/tutorials/pshader/

Another option: You can draw to a PGraphics pg rather than the canvas, then use texture(pg) + vertex() to texture the result onto an arbitrary polygon (such as a rectangle with any aspect ratio, including one bigger than the sketch canvas). The only catch is that you must use an OpenGL renderer in size() – P2D or P3D.

Here is a brief example:

/**
 * StretchSketch
 * 2019-12 Jeremy Douglass - Processing 3.4
 * draw to a buffer; texture result onto a (stretchable) shape
 */
PGraphics pg;

void setup() {
  size(480, 480, P2D); // requires P2D or P3D for texture()
  
  // set up sketch drawing buffer
  PImage pi = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Processing_3_logo.png/480px-Processing_3_logo.png");
  pg = createGraphics(width, height);
  pg.beginDraw();
  pg.image(pi, 0, 0);
  pg.strokeWeight(5);
  pg.endDraw();
}

void draw() {
  background(128);

  // draw onto the sketch graphics buffer -- not the canvas
  pg.beginDraw();
  pg.stroke(random(255), 128);
  pg.line(random(pg.width), random(pg.height), random(pg.width), random(pg.height));
  pg.endDraw();

  // time-based stretching coordinates
  float x = (cos(TWO_PI*((frameCount)%300)/300.0) + 1) * width/2.0;
  float y = (cos(TWO_PI*((frameCount)%235)/235.0) + 1) * height/2.0;

  // stretch an image texture onto a PShape displayed on canvas
  beginShape();
  texture(pg);
  vertex(x, y, 0, 0);
  vertex(width-x, y, pg.width, 0);
  vertex(width-x, height-y, pg.width, pg.height);
  vertex(x, height-y, 0, pg.height);
  endShape(CLOSE);
  
  // show preview window of drawing buffer
  image(pg, 5, 5, 100, 100);
}

StretchSketch--screenshot

3 Likes

Thanks.Really fantastic!

Hi @noel and @unique_username. Thank you for your responses. Those might not work for me as I have to have my shapes in draw and not setup, but they do look cool.

@jeremydouglass Wow! great idea to use the image as a texture onto another polygon. The patch you made is definitely the way to pursue. Thank you so much for looking into that.

Great to hear! Let us know if you tried it and it solved your problem.