Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
TheLastManStanding
Jan 14, 2008
Mash Buttons!

Wheany posted:

Content aware scaling/liquid scaling

This is awesome, so I decided to give it a try.



Not quite as cool; I think I did a little too much content aware scaling. I also loaded the pictures in reverse which is why it makes things seems to linger. Definitely going to poke around with this.

Adbot
ADBOT LOVES YOU

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Figured out that using protection during content aware scaling can preserve the loop in gifs. Could be used to preserve other parts of time too I supposed.





TheLastManStanding
Jan 14, 2008
Mash Buttons!
If anyone else wants to join in, this is the script I wrote for processing:
Files are expected to be in png format with 3 digit numbering, stored in a folder called data.
code:
int frames = 180; //Number of frames
int count = 1;
PImage[] img = new PImage[frames];
String filename = "Seq"; //File names
int w, h;

void setup() {
  // Images must be in the "data" directory to load correctly
  img[0] = loadImage(filename + "001.png");
  w = img[0].width;
  h = img[0].height;
  size(w, frames);
}

void draw() {

  for (int y = 0; y < frames; y++) {
    img[y] = loadImage(filename + nf(y+1, 3) + ".png");
  }

  while (count < h+1) {
    for (int y=0; y<frames; y++) {
      image(img[y].get(0, count-1, w, 1), 0, y);
    }
    save("output/frame_" + nf(count, 3) + ".png");
    count++;
  }
  exit();
}



Wheany posted:

Have you ever content-aware scaled... different color channels... temporally? :2bong:

:stare: How did I not think of this?

So far I've tried motion blur, edge detection, and a few other filters, but nothing has been too interesting.

TheLastManStanding fucked around with this message at 18:59 on Apr 24, 2014

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Some more scripts for people to use.

Splits frames into red, green, and blue frames.
code:
int frames = 53; //Number of frames
int count = 1;
PImage[] img = new PImage[frames];
String filename = "Seq"; //Filename
int w, h;

void setup() {
  // Images must be in the "data" directory to load correctly
  img[0] = loadImage(filename+"001.png");
  size(img[0].width, img[0].height);
}

void draw() {
  for (int y = 0; y < frames; y++) {
    img[y] = loadImage(filename + nf(y+1, 3) + ".png");
  }

  loadPixels();

  for (int c=0; c<frames; c++) {
    //Red
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        int loc = x + y*width;
        float r = img[c].pixels[loc] >> 16 & 0xFF;
        pixels[loc] =  color(r, 0, 0);
      }
    }
    updatePixels();
    save("output/framer_"+nf(c+1, 3)+".png");
    //Green
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        int loc = x + y*width;
        float g = img[c].pixels[loc] >> 8 & 0xFF;
        pixels[loc] =  color(0, g, 0);
      }
    }
    updatePixels();
    save("output/frameg_"+nf(c+1, 3)+".png");
    //Blue
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        int loc = x + y*width;
        float b = img[c].pixels[loc] & 0xFF;
        pixels[loc] =  color(0, 0, b);
      }
    }
    updatePixels();
    save("output/frameb_"+nf(c+1, 3)+".png");
  }
  exit();
}
Combines the red, green, and blue frames back into a single frame
code:
int frames = 53;
PImage[] imgr = new PImage[frames];
PImage[] imgg = new PImage[frames];
PImage[] imgb = new PImage[frames];
String filename = "Seq";


void setup() {
  // Images must be in the "data" directory to load correctly
  imgr[0] = loadImage(filename+"r001.png");
  size(imgr[0].width, imgr[0].height);
}

void draw() {
  for (int y = 0; y < frames; y++) {
    imgr[y] = loadImage(filename + "r" + nf(y+1, 3) + ".png");
    imgg[y] = loadImage(filename + "g" + nf(y+1, 3) + ".png");
    imgb[y] = loadImage(filename + "b" + nf(y+1, 3) + ".png");
  }

  loadPixels();

  for (int c = 0; c < frames; c++) {
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        int loc = x + y*width;
        float r = imgr[c].pixels[loc] >> 16 & 0xFF;
        float g = imgg[c].pixels[loc] >> 8 & 0xFF;
        float b = imgb[c].pixels[loc] & 0xFF;
        pixels[loc] =  color(r, g, b);
      }
    }
    updatePixels();
    save("output/frame_"+nf(c+1, 3)+".png");
  }
  exit();
}
Haven't used this on a slitscan image, but I will. This is with each color channel separately content-aware scaled.



Smearing: this expects a background image numbered '000' to compare against
code:
int frames = 91; //Number of frames
int count = 1;
PImage[] img = new PImage[frames];
PImage blank;
String filename = "Seq"; //File name
int w, h;
float limit = 86; //Controls pixel rejection

void setup() {
  blank = loadImage(filename+"000.png");
  size(blank.width, blank.height);
}

void draw() {
  for (int y = 0; y < frames; y++) {
    img[y] = loadImage(filename + nf(y+1, 3) + ".png");
  }
  image(img[0],0,0); //Comment out this line to check overlays
  loadPixels();

  for (int c=0; c<frames; c++) {
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        int loc = x + y*width;
        float r = img[c].pixels[loc] >> 16 & 0xFF;
        float g = img[c].pixels[loc] >> 8 & 0xFF;
        float b = img[c].pixels[loc] & 0xFF;
        float rb = blank.pixels[loc] >> 16 & 0xFF;
        float gb = blank.pixels[loc] >> 8 & 0xFF;
        float bb = blank.pixels[loc] & 0xFF;
        float crgb = abs(r - rb) + abs(g - gb) + abs(b - bb); 
        if (crgb > limit) {
          pixels[loc] =  color(r, g, b);
        }
      }
    }
    updatePixels();
    save("output/framer_"+nf(c+1, 3)+".png");
  }
  exit();
}

TheLastManStanding
Jan 14, 2008
Mash Buttons!

PHIZ KALIFA posted:

So, I've got a question for folks about a potential Processing project: I'm looking for something I can feed a video clip to that will break it into 10-15 second chunks, rearrange it, and pass a filter over what results. Would that be feasible? My background in coding is I know how to make TI's draw ding-a-lings on the graph page.
Processing can't handle video natively and it's limited in what still image types it can use ( .gif, .jpg, .tga, .png). If you know enough about the header and frame tags for the video you could probably load the file as an object or byte array, but it would be a lot of work. I've modified videos before, but I've used a separate program to first strip the frames and then later reassemble them. It's quick enough and pretty easy.

I like this one.

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Wrote a pair of programs yesterday to help in glitching pics. The first does pixel sorting; it can load pixels by RGB or HSB, can sort individual channels, and can swap and recombine in both RBG or HSB. Sorting seems to work best on pictures with large areas of similar colors; pictures with lots of colors tend to go muddy. Cross processing from RGB to HSB tends to give good results. You can also mix input channels.




code:
// PixelSorting v141006
// By MCG
// Processing 2.1.2

PImage img;
String filename;
int w, h;
int[] a;
int[] b;
int[] c;
int step = 0;

void setup() {
  while (step < 2) {
    if (step == 0)
    {
      selectInput("Select a file to process:", "fileSelected");
      step++;
    }
  }
  img = loadImage(filename);
  w = img.width;
  h = img.height;
  size(w, h);
  a = new int[w];
  b = new int[w];
  c = new int[w];
}

void draw() {
  loadPixels();
  //colorMode(HSB); // Uncommment when outputting HSB

  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      int loc = x + y*width;

      // Uncomment secton to load RGB
      a[x] = img.pixels[loc] >> 16 & 0xFF;
      b[x] = img.pixels[loc] >> 8 & 0xFF;
      c[x] = img.pixels[loc] & 0xFF;

      // Uncomment section to load HSB
      //a[x] = int(hue(img.pixels[loc])); 
      //b[x] = int(saturation(img.pixels[loc]));
      //c[x] = int(brightness(img.pixels[loc]));
    }

    // Sorting
    a = sort(a); // Red or Hue
    b = sort(b); // Green or Saturation
    c = sort(c); // Blue or Brightness

    for (int x = 0; x < width; x++) {
      int loc = x + y*width;
      pixels[loc] =  color(a[x], b[x], c[x]); // Channels can be swapped here
    }
  }
  updatePixels();
  save(month() + nf(day(),2) + "/" + hour() + nf(minute(),2) + nf(second(),2) + ".png");
  //exit();
  noLoop();
}

void fileSelected(File selection) {
  if (selection == null) {
    println("Selection canceled.");
  } 
  else {
    filename = selection.getAbsolutePath();
    step++;
  }
}

TheLastManStanding
Jan 14, 2008
Mash Buttons!
The second is interactive. The mouse wheel is used to scroll through tools (What you're using is shown in the console), left click to use them, press 's' to save the picture. There's various line tools, cut and paste, inverting sections, posterizing sections, circles, and an eraser.




code:
Update in post below

TheLastManStanding fucked around with this message at 05:09 on Oct 10, 2014

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Updated my code; added the ability to push and pull the image, as well as stripping color channels and adding noise.
- Arrow keys control line direction
- r, g, b, & a keys select which channel is to be modified (a is all)
- [ and ] resize the tools
- The eraser is now right click
- mouse wheel changes tools
- s to save



code:
// GlitchPaint v141009
// By MCG
// Processing 2.1.2

PImage img;
PImage timg;
String filename;
StringList styleName;
int w, h;
int x, y;
int mx, my;
int[] r, g, b;
int c1, c2, c = 1; // Cut and paste points
int pLevel = 4; // Posterization amount
int size = 50; // Object Sizes
int lsize = 7; // Line width
int str = 25; // Noise strength
char dir = 'u'; // Line directions select
char channel = 'r'; // Channel select
int step = 0;
int style = 1;

void setup() {
  while (step < 2) {
    if (step == 0)
    {
      selectInput("Select a file to process:", "fileSelected");
      step++;
    }
  }
  img = loadImage(filename);
  w = img.width;
  h = img.height;
  r = new int[h*w];
  g = new int[h*w];
  b = new int[h*w];
  size(w, h);
  styleLoad();
  image(img, 0, 0);
  loadPixels();
}

void draw() {
  if (mousePressed && (mouseButton == LEFT)) {
    mx = constrain(mouseX, 0, w);
    my = constrain(mouseY, 0, h);
    switch(style) {
    case 1: // Box
      x = mx;
      y = my;
      for (int i=0; i<size; i++) {
        // x- y-
        stroke(get(x-size, y-i));
        line(x-i, y-i, x-size, y-i);
        stroke(get(x-i, y-size));
        line(x-i, y-i, x-i, y-size);
        // x+ y+
        stroke(get(x+size, y+i));
        line(x+i, y+i, x+size, y+i);
        stroke(get(x+i, y+size));
        line(x+i, y+i, x+i, y+size);
        // x+ y-
        stroke(get(x+size, y-i));
        line(x+i, y-i, x+size, y-i);
        stroke(get(x+i, y-size));
        line(x+i, y-i, x+i, y-size);
        // x- y+
        stroke(get(x-size, y+i));
        line(x-i, y+i, x-size, y+i);
        stroke(get(x-i, y+size));
        line(x-i, y+i, x-i, y+size);
      }
      break;
    case 2: // Line
      x = mx;
      y = my;
      switch(dir) {
      case 'u':
        for (int i=0-(lsize/2); i<(lsize/2)+1; i++) {
          stroke(get(x+i, y));
          line(x+i, y, x+i, y-size);
        }
        break;
      case 'd':
        for (int i=1-(lsize/2); i<(lsize/2)+1; i++) {
          stroke(get(x+i, y));
          line(x+i, y, x+i, y+size);
        }
        break;
      case 'l':
        for (int i=0-(lsize/2); i<(lsize/2)+1; i++) {
          stroke(get(x, y+i));
          line(x, y+i, x-size, y+i);
        }
        break;
      case 'r':
        for (int i=0-(lsize/2); i<(lsize/2)+1; i++) {
          stroke(get(x, y+i));
          line(x, y+i, x+size, y+i);
        }
        break;
      }
      break;
    case 3: // Line Long
      x = mx;
      y = my;
      switch(dir) {
      case 'u':
        for (int i=0-(lsize/2); i<(lsize/2)+1; i++) {
          stroke(get(x+i, y));
          line(x+i, y, x+i, 0);
        }
        break;
      case 'd':
        for (int i=1-(lsize/2); i<(lsize/2)+1; i++) {
          stroke(get(x+i, y));
          line(x+i, y, x+i, h);
        }
        break;
      case 'l':
        for (int i=0-(lsize/2); i<(lsize/2)+1; i++) {
          stroke(get(x, y+i));
          line(x, y+i, 0, y+i);
        }
        break;
      case 'r':
        for (int i=0-(lsize/2); i<(lsize/2)+1; i++) {
          stroke(get(x, y+i));
          line(x, y+i, w, y+i);
        }
        break;
      }
      break;
    case 4: // Pull pixels
      loadPixels();
      for (int i = 0; i < pixels.length; i++) {
        r[i] = pixels[i] >> 16 & 0xFF; 
        g[i] = pixels[i] >> 8 & 0xFF;
        b[i] = pixels[i] & 0xFF;
      }
      int loc = mx + my*width;
      switch(channel) {
      case 'r':
        r = append(concat(subset(r, 0, loc-1), subset(r, loc, r.length-loc)), 0);
        break;
      case 'g':
        g = append(concat(subset(g, 0, loc-1), subset(g, loc, g.length-loc)), 0);
        break;
      case 'b':
        b = append(concat(subset(b, 0, loc-1), subset(b, loc, b.length-loc)), 0);
        break;
      case 'a':
        r = append(concat(subset(r, 0, loc-1), subset(r, loc, r.length-loc)), 0);
        g = append(concat(subset(g, 0, loc-1), subset(g, loc, g.length-loc)), 0);
        b = append(concat(subset(b, 0, loc-1), subset(b, loc, b.length-loc)), 0);
        break;
      }
      for (int i = 0; i < pixels.length; i++) { 
        pixels[i] =  color(r[i], g[i], b[i]); // Channels can be swapped here
      }
      updatePixels();
      break;
    case 5: // Push pixels
      loadPixels();
      for (int i = 0; i < pixels.length; i++) {
        r[i] = pixels[i] >> 16 & 0xFF; 
        g[i] = pixels[i] >> 8 & 0xFF;
        b[i] = pixels[i] & 0xFF;
      }
      loc = mx + my*width;
      switch(channel) {
      case 'r':
        r = splice(r, pixels[loc] >> 16 & 0xFF, loc);
        break;
      case 'g':
        g = splice(g, pixels[loc] >> 8 & 0xFF, loc);
        break;
      case 'b':
        b = splice(b, pixels[loc] >> 0xFF, loc);
        break;
      case 'a':
        r = splice(r, pixels[loc] >> 16 & 0xFF, loc);
        g = splice(g, pixels[loc] >> 8 & 0xFF, loc);
        b = splice(b, pixels[loc] >> 0xFF, loc);
        break;
      }
      for (int i = 0; i < pixels.length; i++) { 
        pixels[i] =  color(r[i], g[i], b[i]); // Channels can be swapped here
      }
      updatePixels();
      break;
    case 10: // Circle
      x = mx;
      y = my;      
      noStroke();
      fill(img.get(x, y));
      ellipse(x, y, size, size);
      break;
    }
  }
}

void mouseClicked() {
  if (mouseButton == LEFT) {
    switch(style) {
    case 6: // Remove Color Channel
      switch(c) {
      case 1:
        c++;
        c1 = mx;
        c2 = my;
        println("-Point 1 taken");
        break;
      case 2:
        loadPixels();
        for (int i = 0; i < pixels.length; i++) {
          r[i] = pixels[i] >> 16 & 0xFF;
          g[i] = pixels[i] >> 8 & 0xFF;
          b[i] = pixels[i] & 0xFF;
        }
        int min = min(c1+c2*w, mx+my*w);
        int max = max(c1+c2*w, mx+my*w);
        switch(channel) {
        case 'r':
          for (int i = min; i < max; i++) {
            pixels[i] =  color(0, g[i], b[i]);
          }
          break;
        case 'g':
          for (int i = min; i < max; i++) {
            pixels[i] =  color(r[i], 0, b[i]);
          }     
          break;   
        case 'b':
          for (int i = min; i < max; i++) {
            pixels[i] =  color(r[i], g[i], 0);
          }
          break;
        default:
          break;
        }
        println("-Color Stripped");
        updatePixels();
        c=1;
        break;
      }
      break;
    case 7:  // Noise
      switch(c) {
      case 1:
        c++;
        c1 = mx;
        c2 = my;
        println("-Point 1 taken");
        break;
      case 2:
        int cx = mx;
        int cy = my;
        timg = get(min(c1, cx), min(c2, cy), abs(c1 - cx), abs(c2 - cy));
        int tw = abs(c1 - cx);
        int th = abs(c2 - cy);
        int ts = tw * th;
        for (int j = 0; j < th; j++) {
          for (int i = 0; i < tw; i++) {
            int ri = int(i + random(-4, 5));
            int rj = int(j + random(-2, 3));
            timg.pixels[i + j*tw] =  timg.pixels[constrain(ri + rj*tw, 0, ts-1)];
            //constrain((i + int(random(-10, 11)))+int(random(-4, 5))*abs(c1 - cx), 0, timg.pixels.length-1)
          }
        }
        image(timg, min(c1, cx), min(c2, cy));
        println("-Noise added");
        c=1;
        break;
      }
      break;
    case 8: // Invert
      switch(c) {
      case 1:
        c++;
        c1 = mx;
        c2 = my;
        println("-Point 1 taken");
        break;
      case 2:
        int cx = mx;
        int cy = my;
        timg = get(min(c1, cx), min(c2, cy), abs(c1 - cx), abs(c2 - cy));
        timg.filter(INVERT);   
        image(timg, min(c1, cx), min(c2, cy));
        println("-Inverted");
        c=1;
        break;
      }
      break;
    case 9: // Posterize
      switch(c) {
      case 1:
        c++;
        c1 = mx;
        c2 = my;
        println("-Point 1 taken");
        break;
      case 2:
        int cx = mx;
        int cy = my;
        timg = get(min(c1, cx), min(c2, cy), abs(c1 - cx), abs(c2 - cy));
        timg.filter(POSTERIZE, pLevel); 
        image(timg, min(c1, cx), min(c2, cy));
        println("-Posterized");
        c=1;
        break;
      }
      break;
    case 11: // Cut => Paste
      switch(c) {
      case 1:
        c++;
        c1 = mx;
        c2 = my;
        println("-Point 1 taken");
        break;
      case 2:
        c++;
        int cx = mx;
        int cy = my;
        timg = get(min(c1, cx), min(c2, cy), abs(c1 - cx), abs(c2 - cy));
        println("-Point 2 taken");
        break;
      case 3:
        image(timg, mx, my);
        println("-Pasted");
        c=1;
        break;
      }
      break;
    }
  }
  if (mouseButton == RIGHT) {
    mx = constrain(mouseX, 0, w);
    my = constrain(mouseY, 0, h);
    switch(c) {
    case 1:
      c++;
      c1 = mx;
      c2 = my;
      println("-Point 1 taken");
      break;
    case 2:
      int cx = mx;
      int cy = my;
      timg = img.get(min(c1, cx), min(c2, cy), abs(c1 - cx), abs(c2 - cy));
      image(timg, min(c1, cx), min(c2, cy));
      println("-Pasted");
      c=1;
      break;
    }
  }
}

void styleLoad() {
  styleName = new StringList();
  styleName.append("Blank");
  styleName.append("[1] Box");
  styleName.append("[2] Line Short [arrow keys]");
  styleName.append("[3] Line Long [arrow keys]");
  styleName.append("[4] Pull Pixels [r][g][b][a]");
  styleName.append("[5] Push Pixels [r][g][b][a]");
  styleName.append("[6] Remove Color Channel [r][g][b]");
  styleName.append("[7] Noise");
  styleName.append("[8] Invert");
  styleName.append("[9] Posterize");
  styleName.append("[0] Circle");
  styleName.append("[C] Cut and Paste");
  println(styleName.get(1));
}

void mouseWheel(MouseEvent event) {
  int e = event.getCount();
  if (e != 0) {
    int ps = style;
    style = constrain(style + e, 1, 11);
    if (style != ps) {
      println(styleName.get(style));
    }
    c = 1;
  }
}

void fileSelected(File selection) {
  if (selection == null) {
    println("Selection canceled.");
  } 
  else {
    filename = selection.getAbsolutePath();
    step++;
  }
}

void keyReleased() {
  if (key == CODED) {
    switch(keyCode) {
    case UP:
      dir = 'u';
      println("-Up");
      break;
    case DOWN:
      dir = 'd';
      println("-Down");
      break;
    case LEFT:
      dir = 'l';
      println("-Left");
      break;
    case RIGHT:
      dir = 'r';
      println("-Right");
      break;
    }
  } 
  else {
    switch(key) {
    case ']':
      size += 5;
      println("Brush:" + size);
      break;
    case '[': 
      size -= 5;
      size = max(size, 5);
      println("Brush:" + size);
      break;
    case 's':
      save(month() + nf(day(), 2) + "/" + hour() + nf(minute(), 2) + nf(second(), 2) + ".png");
      println("Saved!");
      break;
    case 'r': 
      channel = 'r';
      println("-Red (cyan)");
      break;
    case 'g': 
      channel = 'g';
      println("-Green (magenta)");
      break;
    case 'b': 
      channel = 'b';
      println("-Blue (yellow)");
      break;
    case 'a': 
      channel = 'a';
      println("-All channels");
      break;
    }
  }
}  

TheLastManStanding
Jan 14, 2008
Mash Buttons!

Solumin posted:

You should really throw both of these tools in a Github repository!
:effort:

I seriously hate the github interface, but I ended up making one: https://github.com/Phonocardiogram/imageTools/
Tell me if that works. I included a new version of my PixelSorter, which has a lot more options and shows an immediate result. I also updated GlitchPaint. The changes are:
- Right click now uses a brush to erase
- Greatly improved the noise math
- Changed how cut/paste worked
- Added a quick save/load feature so you can test out small changes easily
- Added 5 filters (Horizontal/Vertical blinds, quilting, random/uniform pointilisim) which are also affected by brush size
+ If anyone has suggestions for filters I'll see about adding them. Right now the only thing I can think of is a harsh jpg compression style filter.

TheLastManStanding
Jan 14, 2008
Mash Buttons!
https://github.com/Phonocardiogram/imageTools/tree/master/TimeScaler

Added a new tool. This one performs a content-aware-scale directly on the time dimension of a sequence of images. This cuts out the intermediate steps of slitscanning and using photoshop's content aware scale, and it eliminates the horizontal artifacts that the previous method produced. It also allows for more direct tuning of the intensity of the effect and greatly reduces the time required to get a result. The only side effect is that the math on this one melted my brain :psypop:



These two gifs show how the results can be tweaked.


TheLastManStanding
Jan 14, 2008
Mash Buttons!

Max posted:

There are people in this thread that absolutely must submit to this. The Tate is asking for people to openly glitch their art to display.

http://www.tate.org.uk/whats-on/tate-britain/special-event/open-call-submission-all-glitched
Cool idea, but those images they've provided aren't great.


I changed my time scale code to properly interpolate between frames, but the difference is almost unnoticeable. It got rid of hard pixel boundaries on quick changes, but also introduced a weird temporal artifact in which contrasted outlines from later frames are apparent in much earlier frames. I haven't updated the code on github yet since I plan to completely rework the order of operations as I'm not satisfied with how smooth it is yet. But have some videos:

https://www.youtube.com/watch?v=tRadBW9ZWNU

https://www.youtube.com/watch?v=VjZe_hsnMa0

Row sorting RGB:


Row sorting hue and sat:


Full sort red, row sort blue:


Progressively smaller quilting, then vertical blinds:

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Updates for https://github.com/Phonocardiogram/imageTools

GlitchPaint
- Now has a recording feature, toggle with the ` key. It saves every 5th frame just so you don't eat up space too fast. You can change that number if you want.
- Group pixel sorting, both as a tool that can be applied and as a filter.
- Scalable cut and paste as well as being able to cut/paste individual channels in both RGB and HSB.

TimeScaler
- Reordered things. It should give a better/smoother result on fast moving scenes. Haven't thoroughly tested it yet though.

PixelSorter
- Added group pixel sorting and tweaked a few things

FrameTools
- New tool which repeatedly applies a filter to a single frame and outputs each successive addition. Mostly fluff, but mode 7 (dissolves images using small group sorting) and mode 5 (repeated quilting) are really fun to watch.

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Now that's the stuff.

TheLastManStanding
Jan 14, 2008
Mash Buttons!
You need Processing

TheLastManStanding
Jan 14, 2008
Mash Buttons!
That's HTML. It shouldn't look anything like that. Did you download as a zip? I'm guessing you copy pasted it wrong.

TheLastManStanding
Jan 14, 2008
Mash Buttons!

Steak posted:

I can't for the life of me get any of Last Man Standing's scripts to work or do anything. Possibly related: my coding knowlege extends as far as copy and pasting code into notepad to make scripts for Arma.
If you're like the other people who have had trouble, it's either because you're bad at copy pasting, you aren't copy pasting every file in the folder (you need all the files for it to work), or you aren't putting your image file in the correct folder (some scripts require the file to be in a folder labeled '/data'). The easiest way to fix this is to just download the zip file.

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Update to GlitchPaint



Now with a fancy GUI :eyepop:

Other changes:
I integrated PixelSorter, so you don't have to switch back and forth. The line tool can now be used at any angle. The noise level of the noise tool is now adjustable. Paste tool has a preview. I made a very basic glitch filter.

I also added a filter which reduces the color palette with a floyd dither.
The options are a 1-bit black/white, 3-bit 4-bit 8-bit RGB, 4-bit Gameboy, NES, and an optional custom palette space.


When my glitch filter glitched out:


What value overflow does to a dither algorithm.


Random other

TheLastManStanding
Jan 14, 2008
Mash Buttons!
This is awesome. Is it a rotating brush or some mathematical squiggle used as a mask?

I also like this and it should be super simple to put into GlitchPaint.

Do you have any feedback on the new interface? Is it straightforward enough? Anything you'd like to see changed or added?

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Read the shortcuts tab or text file. '[' and ']' change the brush size by 5. '-' and '+' change it by 1. By holding the key you can go from size 1 to 100 in about a second. The mouse wheel will scroll through the tools and tab will change the mode.

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Another Update: (Download)
I've given up on github so it's a zip file with the option of running the program as a windows 64 application or running the source in processing.

Changes made:

- The window is resizeable allowing you to maximize the window.
- Added halftones in both black/white and color (it's not a true color halftone, but I might do that later).
- The amount of dither is now controllable. Negative mean less dither, positive causes it to overcompensate which leads to interesting effects.
- Mosaic with an optional gap.
- Triangles, both uniform and random.
- Blinds can be inserted manually and can be offset.
- The sort brush now works as a selection.


TheLastManStanding
Jan 14, 2008
Mash Buttons!
New Program: (Download) Had some free time yesterday so I threw together a RuttEtra style program.

- Full 360 rotation along the X and Y axis.
- X and Y resolution control. (Warning: Using very low x/y spacing on large images can pretty much stall your computer. When working with large images, slowly lower the spacing. I might limit this later.)
- Line thicknesses.
- Displacement mapping using any combination of RGB and/or HSB.
- Perspective or Orthographic projections.
- Display results as a single plane, horizontal lines, floating pixels, or a mesh.
- It also lets you load a custom displacement map for added fun.
- As always, the 's' key saves the frame.


Example of the different modes:


Example of line thickness at high line spacing:


I've found that looking behind the images often gives the best results:

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Nope. Is your java up to date? I'm assuming that was an attempt at running the applet and not the source code? The applet only works for 64-bit Windows, so if your on a mac or something else you'll have to install processing and run the source (make sure to rename the source folder to match the program name).

TheLastManStanding
Jan 14, 2008
Mash Buttons!

AphexMandelbrot posted:

Take picture.
Run through Processing. Base vectors established; export map. (1)
Second run through Processing. Shadow vectors established; export map. (2)
Call Twitter API via Python. Pull latest tweets.
Check input variable; currently word/mood/etc (the guts used to run my Raspberry Pi Twitter mood lamp).
Compute mood for color (C); compute instances for generative variable (G); compute hashtag use for intensity (I).
(G) and (I) make out some.
Export (G)(I)'s lovechild (A); send with (C) to Processing.
Call image.
Apply (1) vector map to image; fill based on (A) -- (AA)
/// Revise to include a ChillTheFuckOut because it takes around 1.5m on an i7 with 10Gb RAM.
Apply (2) shadow vector map to (AA) -- (AAA).
ASDF Low: 15% full threshold.
ASDF High: 15% full threshold.
/// Done.
Stare. Start digging through friends' profile pictures looking for portraits.
-
Result:


I have no idea what any of that means, but it looks awesome.

quote:

I also really like that the timg of this one looks like a normal photo taken through a window on a rainy day.

President Kucinich posted:

Makin diamond flowers.

I started writing a program to handle delaunay triangulation, but got bored; these kind of make me want to finish it.

TheLastManStanding
Jan 14, 2008
Mash Buttons!
It's a Delaunay Filter, most likely this one. If you do use it you'll want to add the lines
code:
H = buffer.height;
W = buffer.width;
right after the line
code:
PImage buffer = loadImage("r.jpg");
which should also be updated with whatever image you are trying to process. The size() parameter should also be updated to be larger than your image. If you want to change the number of points then change the number 300 in the line which is just after the image load. (That number is a threshold value, so a lower number produces more points)
code:
EdgeDetector.extractPoints(vertices, buffer, EdgeDetector.SOBEL, 300, 4);
If you want to toy around with manually added points, then take a look at DMesh.

TheLastManStanding
Jan 14, 2008
Mash Buttons!

President Kucinich posted:

I like this one. It runs like poo poo, and constantly stalls out, took forever to get running right, but it's got some neat options in it.
https://github.com/dplockheart/Triangulate-DF
I can't get this one to display an output (I just get the control window), but I immediately recognized the code as a copy/paste from the one I linked above, but with cp5 controls added. It's apparent that he doesn't know how to code since he has a bunch of if statements that look like this:
code:
if(ready == true) { }
and the fact that he's triangulating the mesh every draw cycle. I appreciate what he tried to do, but :ughh: He also renamed all the images to sauce.

TheLastManStanding fucked around with this message at 05:41 on Feb 12, 2015

TheLastManStanding
Jan 14, 2008
Mash Buttons!
I might get around to finishing it. Most of the code is there, the thing was I figured if I was going to finish it then I wanted it to have at least one major thing that DMesh doesn't have, of which the only things I that came to mind were point-dragging and manual color application. The latter is easy, but the former is tricky. Moving the point is super easy (It's probably two lines of code), but doing it efficiently is tough since in most code it requires triangulating the whole mesh every frame (while dragged), which is exceptionally slow with only a few hundred triangles. My thought was to only re-triangulate the faces connected to the moving point (and the faces connected to those), but proper re-triangulation would require the total area of them to be convex, which becomes more unlikely as you add points. My current thought is to do something similar, remap a small section around the dragged portion, then delete the exterior faces. I'm thinking that it will be good enough in almost every case, and even when it does mess up it won't be an issue as the whole mesh will be recalculated when the mouse is released. I'll have to think about it some more though.

In the mean time....

New Program: (Download) Takes an image and lets you slice up the polygons. It has various blend modes, deletable faces, random slopes, undo up to your last 100 actions, full stroke control, and auto points using two point edge detection (because of geometry, the results will be more abstract than you might anticipate).

As usual, the app is for win-64 with Java 7, source included for everyone else.




TheLastManStanding
Jan 14, 2008
Mash Buttons!
Also some junk I did in Re (which I've been meaning to update).





TheLastManStanding
Jan 14, 2008
Mash Buttons!
Update: Re Version 2 (Download)
- Updated the menu to the new style
- Added blocks and vertical line modes
- Changed how RGB displacement is calculated (looks much better now).
- Offloaded the displacement to some custom shaders

That last bit means that the shape only has to be remade when switching modes or resolution, so changing line thickness or displacement are instantaneous. The side effect of this is I had to change how the mask worked: Displacement is now based off of both the RGB/Brightness of the main image and the mask brightness, with the upside that they are all individually scalable. It also caused a minor change in how lines are rendered, but it shouldn't be an issue.

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Odd. If you're running the app you shouldn't have to do anything. I downloaded it and it's working for me, so the link is fine. Could be an OpenGL/video drivers issue. Were you able to get the other program running (slicer)? If you copy the data folder into the source folder and rename the source folder to Re you could try running it in Processing, which should give an error code if there's a problem.

As a side note, Processing runs on Java 7. The current Java is version 8 and if you update to it it will suggest that you uninstall old versions, which means Processing apps won't run, so you should make sure the version you have is the newest version of 7. (You can have both versions installed as they are independent. Java is silly like that).

TheLastManStanding fucked around with this message at 08:43 on Feb 18, 2015

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Try replacing the data folder with this one

TheLastManStanding
Jan 14, 2008
Mash Buttons!
Sooo... Two weeks ago I finally got around to starting on my Deluanay program. I started by poking around other peoples code to see how they were doing it. Nearly everyone was using some slightly modified form of the triangulate library, which seemed convenient: However, in my tests it sometimes gave improper triangulations (for 5000 points there was around a 1/10 change of a mistake, typically a small and almost unnoticeable, but still a mistake). After a week of poking around the code I wasn't able to completely fix it, got frustrated, and threw everything out. I took a few days off from the project and when I came back I decided to look for a different route. I found one person who wasn't using the standard code. I tried it out and while it had some errors and was significantly slower (4000ms vs 600ms for 5000 points), the code was much simpler. I started with fixing the circumcircle equation and switched the inTriangle function from the dot product method to ray casting; neither gave improved speed, but it fixed the errors. Sorting the points gave a good boost bringing the time down to 1000ms. Still slow, but I figured it was decent. I then tweaked everything line by line, completely rewrote the face flipping and adjacent finding algorithms, and switched to a TreeSet to remove coincident points. That brought the time down to 50ms :psyduck: Somehow I had written a Deluanay triangulation program was 10 times faster than the one everyone else is using.

Anyways, have fun with it. I'll probably clean up the triangulation code a bit more and release it as a library. I also have some more features I might try out.

New Program: (Download)
It makes Deluanay triangulations. Add points, delete points, move points, points that make holes, random points, points that use edge detection, plus all the overlay, blending, and stroke options from my other programs, plus a few more.
You can use the a/d/c/h keys to quickly change modes. Right click a point to delete it. Play around with everything else.


Adbot
ADBOT LOVES YOU

TheLastManStanding
Jan 14, 2008
Mash Buttons!
You should be using Java 7u75 and make sure your graphics driver is up to date. If you're running it through processing and it throws an error I might be able to tell you what it means.

  • Locked thread