378 lines
7.3 KiB
Plaintext
378 lines
7.3 KiB
Plaintext
|
|
/********
|
|
|
|
ASDF Pixel Sort
|
|
Kim Asendorf | 2010 | kimasendorf.com
|
|
|
|
Sorting modes
|
|
0 = white
|
|
1 = black
|
|
2 = bright
|
|
3 = dark
|
|
|
|
*/
|
|
|
|
int mode = 0;
|
|
|
|
// image path is relative to sketch directory
|
|
PImage img;
|
|
String imgFileName = "mountains";
|
|
String fileType = "jpg";
|
|
|
|
int loops = 1;
|
|
|
|
// threshold values to determine sorting start and end pixels
|
|
// using the absolute rgb value
|
|
// r*g*b = 255*255*255 = 16581375
|
|
// 0 = white
|
|
// -16581375 = black
|
|
// sort all pixels whiter than the threshold
|
|
int whiteValue = -12345678;
|
|
// sort all pixels blacker than the threshold
|
|
int blackValue = -3456789;
|
|
// using the brightness value
|
|
// sort all pixels brighter than the threshold
|
|
int brightValue = 127;
|
|
// sort all pixels darker than the threshold
|
|
int darkValue = 223;
|
|
|
|
|
|
int row = 0;
|
|
int column = 0;
|
|
|
|
boolean saved = false;
|
|
|
|
void setup() {
|
|
img = loadImage(imgFileName + "." + fileType);
|
|
|
|
// use only numbers (not variables) for the size() command, Processing 3
|
|
size(1, 1);
|
|
|
|
// allow resize and update surface to image dimensions
|
|
surface.setResizable(true);
|
|
surface.setSize(img.width, img.height);
|
|
|
|
// load image onto surface - scale to the available width,height for display
|
|
image(img, 0, 0, width, height);
|
|
}
|
|
|
|
|
|
void draw() {
|
|
|
|
if (frameCount <= loops) {
|
|
|
|
// loop through columns
|
|
println("Sorting Columns");
|
|
while (column < img.width-1) {
|
|
img.loadPixels();
|
|
sortColumn();
|
|
column++;
|
|
img.updatePixels();
|
|
}
|
|
|
|
// loop through rows
|
|
println("Sorting Rows");
|
|
while (row < img.height-1) {
|
|
img.loadPixels();
|
|
sortRow();
|
|
row++;
|
|
img.updatePixels();
|
|
}
|
|
}
|
|
|
|
// load updated image onto surface and scale to fit the display width and height
|
|
image(img, 0, 0, width, height);
|
|
|
|
if (!saved && frameCount >= loops) {
|
|
// save img
|
|
img.save(imgFileName + "_" + mode + ".png");
|
|
|
|
saved = true;
|
|
println("Saved frame " + frameCount);
|
|
|
|
// exiting here can interrupt file save, wait for user to trigger exit
|
|
println("Click or press any key to exit...");
|
|
}
|
|
}
|
|
|
|
void keyPressed() {
|
|
if (saved) {
|
|
System.exit(0);
|
|
}
|
|
}
|
|
|
|
void mouseClicked() {
|
|
if (saved) {
|
|
System.exit(0);
|
|
}
|
|
}
|
|
|
|
void sortRow() {
|
|
// current row
|
|
int y = row;
|
|
|
|
// where to start sorting
|
|
int x = 0;
|
|
|
|
// where to stop sorting
|
|
int xEnd = 0;
|
|
|
|
while (xEnd < img.width-1) {
|
|
switch (mode) {
|
|
case 0:
|
|
x = getFirstNoneWhiteX(x, y);
|
|
xEnd = getNextWhiteX(x, y);
|
|
break;
|
|
case 1:
|
|
x = getFirstNoneBlackX(x, y);
|
|
xEnd = getNextBlackX(x, y);
|
|
break;
|
|
case 2:
|
|
x = getFirstNoneBrightX(x, y);
|
|
xEnd = getNextBrightX(x, y);
|
|
break;
|
|
case 3:
|
|
x = getFirstNoneDarkX(x, y);
|
|
xEnd = getNextDarkX(x, y);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (x < 0) break;
|
|
|
|
int sortingLength = xEnd-x;
|
|
|
|
color[] unsorted = new color[sortingLength];
|
|
color[] sorted = new color[sortingLength];
|
|
|
|
for (int i = 0; i < sortingLength; i++) {
|
|
unsorted[i] = img.pixels[x + i + y * img.width];
|
|
}
|
|
|
|
sorted = sort(unsorted);
|
|
|
|
for (int i = 0; i < sortingLength; i++) {
|
|
img.pixels[x + i + y * img.width] = sorted[i];
|
|
}
|
|
|
|
x = xEnd+1;
|
|
}
|
|
}
|
|
|
|
|
|
void sortColumn() {
|
|
// current column
|
|
int x = column;
|
|
|
|
// where to start sorting
|
|
int y = 0;
|
|
|
|
// where to stop sorting
|
|
int yEnd = 0;
|
|
|
|
while (yEnd < img.height-1) {
|
|
switch (mode) {
|
|
case 0:
|
|
y = getFirstNoneWhiteY(x, y);
|
|
yEnd = getNextWhiteY(x, y);
|
|
break;
|
|
case 1:
|
|
y = getFirstNoneBlackY(x, y);
|
|
yEnd = getNextBlackY(x, y);
|
|
break;
|
|
case 2:
|
|
y = getFirstNoneBrightY(x, y);
|
|
yEnd = getNextBrightY(x, y);
|
|
break;
|
|
case 3:
|
|
y = getFirstNoneDarkY(x, y);
|
|
yEnd = getNextDarkY(x, y);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (y < 0) break;
|
|
|
|
int sortingLength = yEnd-y;
|
|
|
|
color[] unsorted = new color[sortingLength];
|
|
color[] sorted = new color[sortingLength];
|
|
|
|
for (int i = 0; i < sortingLength; i++) {
|
|
unsorted[i] = img.pixels[x + (y+i) * img.width];
|
|
}
|
|
|
|
sorted = sort(unsorted);
|
|
|
|
for (int i = 0; i < sortingLength; i++) {
|
|
img.pixels[x + (y+i) * img.width] = sorted[i];
|
|
}
|
|
|
|
y = yEnd+1;
|
|
}
|
|
}
|
|
|
|
|
|
// white x
|
|
int getFirstNoneWhiteX(int x, int y) {
|
|
while (img.pixels[x + y * img.width] < whiteValue) {
|
|
x++;
|
|
if (x >= img.width) return -1;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
int getNextWhiteX(int x, int y) {
|
|
x++;
|
|
while (img.pixels[x + y * img.width] > whiteValue) {
|
|
x++;
|
|
if (x >= img.width) return img.width-1;
|
|
}
|
|
return x-1;
|
|
}
|
|
|
|
// black x
|
|
int getFirstNoneBlackX(int x, int y) {
|
|
while (img.pixels[x + y * img.width] > blackValue) {
|
|
x++;
|
|
if (x >= img.width) return -1;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
int getNextBlackX(int x, int y) {
|
|
x++;
|
|
while (img.pixels[x + y * img.width] < blackValue) {
|
|
x++;
|
|
if (x >= img.width) return img.width-1;
|
|
}
|
|
return x-1;
|
|
}
|
|
|
|
// bright x
|
|
int getFirstNoneBrightX(int x, int y) {
|
|
while (brightness(img.pixels[x + y * img.width]) < brightValue) {
|
|
x++;
|
|
if (x >= img.width) return -1;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
int getNextBrightX(int x, int y) {
|
|
x++;
|
|
while (brightness(img.pixels[x + y * img.width]) > brightValue) {
|
|
x++;
|
|
if (x >= img.width) return img.width-1;
|
|
}
|
|
return x-1;
|
|
}
|
|
|
|
// dark x
|
|
int getFirstNoneDarkX(int x, int y) {
|
|
while (brightness(img.pixels[x + y * img.width]) > darkValue) {
|
|
x++;
|
|
if (x >= img.width) return -1;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
int getNextDarkX(int x, int y) {
|
|
x++;
|
|
while (brightness(img.pixels[x + y * img.width]) < darkValue) {
|
|
x++;
|
|
if (x >= img.width) return img.width-1;
|
|
}
|
|
return x-1;
|
|
}
|
|
|
|
// white y
|
|
int getFirstNoneWhiteY(int x, int y) {
|
|
if (y < img.height) {
|
|
while (img.pixels[x + y * img.width] < whiteValue) {
|
|
y++;
|
|
if (y >= img.height) return -1;
|
|
}
|
|
}
|
|
return y;
|
|
}
|
|
|
|
int getNextWhiteY(int x, int y) {
|
|
y++;
|
|
if (y < img.height) {
|
|
while (img.pixels[x + y * img.width] > whiteValue) {
|
|
y++;
|
|
if (y >= img.height) return img.height-1;
|
|
}
|
|
}
|
|
return y-1;
|
|
}
|
|
|
|
|
|
// black y
|
|
int getFirstNoneBlackY(int x, int y) {
|
|
if (y < img.height) {
|
|
while (img.pixels[x + y * img.width] > blackValue) {
|
|
y++;
|
|
if (y >= img.height) return -1;
|
|
}
|
|
}
|
|
return y;
|
|
}
|
|
|
|
int getNextBlackY(int x, int y) {
|
|
y++;
|
|
if (y < img.height) {
|
|
while (img.pixels[x + y * img.width] < blackValue) {
|
|
y++;
|
|
if (y >= img.height) return img.height-1;
|
|
}
|
|
}
|
|
return y-1;
|
|
}
|
|
|
|
// bright y
|
|
int getFirstNoneBrightY(int x, int y) {
|
|
if (y < img.height) {
|
|
while (brightness(img.pixels[x + y * img.width]) < brightValue) {
|
|
y++;
|
|
if (y >= img.height) return -1;
|
|
}
|
|
}
|
|
return y;
|
|
}
|
|
|
|
int getNextBrightY(int x, int y) {
|
|
y++;
|
|
if (y < img.height) {
|
|
while (brightness(img.pixels[x + y * img.width]) > brightValue) {
|
|
y++;
|
|
if (y >= img.height) return img.height-1;
|
|
}
|
|
}
|
|
return y-1;
|
|
}
|
|
|
|
// dark y
|
|
int getFirstNoneDarkY(int x, int y) {
|
|
if (y < img.height) {
|
|
while (brightness(img.pixels[x + y * img.width]) > darkValue) {
|
|
y++;
|
|
if (y >= img.height) return -1;
|
|
}
|
|
}
|
|
return y;
|
|
}
|
|
|
|
int getNextDarkY(int x, int y) {
|
|
y++;
|
|
if (y < img.height) {
|
|
while (brightness(img.pixels[x + y * img.width]) < darkValue) {
|
|
y++;
|
|
if (y >= img.height) return img.height-1;
|
|
}
|
|
}
|
|
return y-1;
|
|
}
|