Created
March 27, 2013 16:48
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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