Search code examples
javafor-loopprocessing

How do i make multiple columns of lines using a loaded image in Processing?


I've made a code in processing that uploaded an image from data and used this image to make a line in processing, kind of like how you can use an organic looking brush in photoshop, except I want the program to draw the line for me.

I want to be able to have the program draw up to 16 lines, but I'm testing with only five lines drawn right now. To do this, I used a nested for loop. However, all that happens is that 4 lines are produced and only two are complete.

here is the code.

PImage brush;

void setup() {

    size(1000, 800);

    brush = loadImage("verticalOrganic.png");
    //load the file verticalOrganic from data. this is our "brush head".


    float i;
    float j;
    float distance;
    brush.resize(7, 0);
    for (j = 0; j < width; j += width / 5) { //this should create five rows, by updating j by 1/5 of 1000
        for (i = 0; i < height; i += distance) {  //distance determines the new position of the brush going down
            //the column.
            image(brush, j, i);  //when j updates, it should create a new column....should.

            distance = random(-10, (brush.height) * 3 / 4);

        }
        println("FINISHED"); //i thought what may be wrong was that j was not updating, so this tests that.
    }

}

Here is the file for the brush head/(if you want to use it, you will have to change it to png. because imgur.)


Solution

  • My hunch is increment for the inner loop with the i counter (distance) is problematic.

    First of, it's defined as float distance; and has no initial value (defaults to 0), so the first time around i will remain 0.

    The second, and larger problem is the value distance gets assigned to:

    distance = random(-10, (brush.height) * 3 / 4);
    

    This means distance can (and will) have values smaller than 0.

    When you apply distance as the loop increment (i += distance) that means you can move in the wrong direction (distance will be subtracted from i rather than added) which either you'd go over the same i values or even worse potentially getting stuck never exiting the loop as small (even negative values) of i will never satisfy the loop exit condition: i < height;

    I'd recommend keeping distance to a positive value:

    distance = random((brush.height) * 3 / 4);
    

    Here's a slightly modified version of your program with an extra variable to count the number of i iterations called iCount (and using the jpg instead of the png):

    PImage brush;
    
    void setup() {
    
        size(1000, 800);
    
        brush = loadImage("uHrk2.jpg");
        //load the file verticalOrganic from data. this is our "brush head".
    
    
        float i;
        float j;
        float distance;
        brush.resize(7, 0);
        
        int iCount = 0;
        
        for (j = 0; j < width; j += width / 5) { //this should create five rows, by updating j by 1/5 of 1000
            for (i = 0; i < height; i += distance) {  //distance determines the new position of the brush going down
                //the column.
                image(brush, j, i);  //when j updates, it should create a new column....should.
    
                distance = random((brush.height) * 3 / 4);
                iCount++;
            }
            
            println(iCount, "i iterations, column index", j, "FINISHED"); //i thought what may be wrong was that j was not updating, so this tests that.
            iCount = 0;
        }
    
    }
    

    Notice the number iCount has per column when it uses positive numbers only and try changing that back to distance = random(-10, (brush.height) * 3 / 4); and notice how many more iterations are needed for i to reach height.

    From an aesthetics point of view, maybe you do want the Y-axis (i) inner loop to oscillate between exiting and forever iterating ? If so, you might want to think of visual ways of emphasising that. Currently as each repetition occurs the latest image rendered at i will be drawn on top of any previous image rendered around that i position (erasing it's history).

    There are probably multiple options, but here are two simple ways:

    1. using blendMode(): these are very similar to layer blend modes in Photoshop. In this case DIFFERENCE, EXCLUSION and REPLACE (if your png has an alpha channel).
    2. using tint() to add transparency (e.g. tint(255, 32); this would set 32/255 opacity (%12.5))

    This should be easy to do after you call size():

      size(1000, 800);
      background(255);
      blendMode(EXCLUSION);
    

    and produce a more glitchy look:

    exclusion blend mode demonstrating overlapping image

    Simply using:

      size(1000, 800);
      background(255);
      tint(255, 32);
    

    will produce something like:

    12.5% opacity applied via tint to highlight overlapping repeating images

    I'd added a minor x offset so the columns are centred:

    PImage brush;
    
    void setup() {
    
      size(1000, 800);
      background(255);
      tint(255, 32);
    
      brush = loadImage("uHrk2.jpg");
    
      //load the file verticalOrganic from data. this is our "brush head".
      
    
      float i;
      float j;
      float distance;
      brush.resize(14, 0);
      println(brush.height);
    
      int iCount = 0;
      
      int offsetX = width / 10;
      
      for (j = 0; j < width; j += width / 5) { //this should create five rows, by updating j by 1/5 of 1000
        for (i = 0; i < height; i += distance) {  //distance determines the new position of the brush going down
          //the column.
          image(brush, offsetX + j, i);  //when j updates, it should create a new column....should.
    
          distance = random(-10, (brush.height) * 3 / 4);
          iCount++;
        }
    
        println(iCount, "i iterations, column index", j, "FINISHED"); //i thought what may be wrong was that j was not updating, so this tests that.
        iCount = 0;
      }
    
    
      save("fade.jpg");
    }
    

    Notice how the areas where i goes back and forth (because of negative distance values) become darker. If you were to switch to distance = random(-10, (brush.height) * 3 / 4); there will less darker areas:

    12.5% opacity overlapping images with less repeating i positions