Skip to content

Instantly share code, notes, and snippets.

@atduskgreg
Created March 27, 2013 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atduskgreg/5255922 to your computer and use it in GitHub Desktop.
Save atduskgreg/5255922 to your computer and use it in GitHub Desktop.
Cache results of Seam Carving in order to make resizing of images work interactively.
import dynamicprogramming.*;
class SeamPoint {
PVector position;
color c;
SeamPoint(PVector position, color c) {
this.position = position;
this.c = c;
}
}
class Seam {
ArrayList<SeamPoint> points;
Seam(ArrayList<PVector> seamPoints, PImage img) {
points = new ArrayList<SeamPoint>();
for (PVector p : seamPoints) {
points.add(new SeamPoint(p, img.pixels[int(p.x) + int(p.y)*img.width]));
}
}
void addPoint(PVector p, color c) {
points.add(new SeamPoint(p, c));
}
String toString(){
String[] result = new String[points.size()*3];
for(int i = 0; i < result.length; i+=3){
result[i] = "" + points.get(i).position.x;
result[i+1] = "" + points.get(i).position.y;
}
return (join(result, ","));
}
}
class SeamCache {
ArrayList<Seam> seams;
PImage img, originalImg;
SeamCarving carver;
int currentSeam = 0;
int numSeams;
SeamCache(PApplet parent, PImage img) {
this.img = img;
originalImg = createImage(img.width, img.height, RGB);
originalImg.copy(img, 0, 0, img.width, img.height, 0,0, img.width,img.height);
this.carver = new SeamCarving(parent, originalImg);
seams = new ArrayList<Seam>();
}
void process(int n) {
this.numSeams = n;
for (int i = 0; i < numSeams; i++) {
println(i);
seams.add(new Seam(carver.findMinSeam(), originalImg));
originalImg.loadPixels();
originalImg = carver.removeColumn();
originalImg.updatePixels();
carver.setImage(originalImg);
}
}
int getCurrentSeam(){
return currentSeam;
}
void removeSeam() {
//println("currentSeam: " + currentSeam + "/" + seams.size());
if (currentSeam == numSeams-1) {
println("out of seams");
return;
}
Seam seam = seams.get(currentSeam);
PImage result = createImage(img.width-1, img.height, RGB);
img.loadPixels();
//println("seam.points.size:" + seam.points.size());
for (SeamPoint p : seam.points) {
int origRowBeginning = (int)p.position.y * img.width;
int destRowBeginning = (int)p.position.y * result.width;
//println("img.pix: " + img.pixels.length + " origRowb: " + origRowBeginning + " result.pix " + result.pixels.length + " " + destRowBeginning + " - " + (int)p.position.x);
if (p.position.x > 0) {
System.arraycopy(img.pixels, origRowBeginning, result.pixels, destRowBeginning, (int)p.position.x);
}
// if there are pixels to copy to the right of the seam
// copy them in as well
if (p.position.x < img.width - 1) {
System.arraycopy(img.pixels, origRowBeginning + (int)p.position.x+1, result.pixels, destRowBeginning + (int)p.position.x, result.width - (int)p.position.x);
}
}
img = result;
img.updatePixels();
currentSeam++;
}
// void saveSeams(){
// for()
// }
void addSeam() {
if (currentSeam == 0) {
println("at original size");
return;
}
Seam seam = seams.get(currentSeam);
PImage result = createImage(img.width+1, img.height, RGB);
img.loadPixels();
// println("seam.points.size:" + seam.points.size());
for (SeamPoint p : seam.points) {
int origRowBeginning = (int)p.position.y * img.width;
int destRowBeginning = (int)p.position.y * result.width;
if (p.position.x > 0) {
System.arraycopy(img.pixels, origRowBeginning, result.pixels, destRowBeginning, (int)p.position.x);
}
result.pixels[destRowBeginning + (int)p.position.x] = p.c;
// if there are pixels to copy to the right of the seam
// copy them in as well
// println( "img.pix: " + img.pixels.length + " origRowb+p.x: " + (origRowBeginning + (int)p.position.x) + " result.pix " + result.pixels.length + " destrowb + p.x " + (destRowBeginning + (int)p.position.x));
if (p.position.x < img.width) {
System.arraycopy(img.pixels, origRowBeginning + (int)(p.position.x), result.pixels, destRowBeginning + (int)p.position.x+1, result.width - (int)p.position.x-1);
}
}
img = result;
img.updatePixels();
currentSeam--;
}
PImage getImage() {
return img;
}
}
import dynamicprogramming.*;
SeamCache cache;
PImage img;
void setup() {
img = loadImage("snow.png");
size(img.height, img.width);
cache = new SeamCache(this, img);
cache.process(img.width-1);
}
void draw() {
fill(255);
text(cache.getCurrentSeam(), 25, 25);
translate(width/2, width/2);
rotate(radians(90));
translate(-width/2, -width/2);
background(0);
image(img, 0, 0);
if (pmouseX > mouseX) {
for (int i = 0; i < abs(pmouseX - mouseX); i++) {
cache.removeSeam();
img = cache.getImage();
}
}
if (pmouseX < mouseX) {
for (int i = 0; i < abs(pmouseX - mouseX); i++) {
cache.addSeam();
img = cache.getImage();
}
}
}
void keyPressed() {
if (key == '-') {
println(img.width);
cache.removeSeam();
img = cache.getImage();
println(img.width);
}
if (key == '=') {
println(img.width);
cache.addSeam();
img = cache.getImage();
println(img.width);
}
// img.loadPixels();
// img = carver.removeColumn();
// img.updatePixels();
//
// carver.setImage(img);
// seam = carver.findMinSeam();
// newSeam = true;
//
// println("calculating score image");
// scoreImage = carver.getScoreImage();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment