Organizing Order (Pixel Sort Part 1)

While working on the series, I consulted Ina to see if I could work on a larger scale. I wanted to have the works be detailed and intricate and thought that the larger size will be able to do justice to the compositions. I decided that working on A3 for my final works would be an ideal size. With this decided, I was able to create works that were larger and more complex.

The first design that I created was the Pixel Sorting one. The biggest challenge with making this work was identifying a process that would help me produce the results I wanted in an efficient manner. After looking around, I realized that I would have to create a program that would help me analyze a digital image and carry out the pixel sorting according to the instructions I gave it.

I decided to work with Processing to create the program. This software uses Java as a programming language to create visual ‘sketches’. I referenced some code from Kim Asendorf’s pixel sorting method to create the following:

int mode = 0;

//MODE:
//0 -> black
//1 -> bright
//2 -> white

PImage img;
String imgFileName = "image";
String fileType = "jpg";

int loops = 1;

int blackValue = -10000000;
int brigthnessValue = 60;
int whiteValue = -6000000;

int row = 0;
int column = 0;

boolean saved = false;

void setup() {
 img = loadImage(imgFileName+"."+fileType);
 size(img.width, img.height);
 image(img, 0, 0);
}


void draw() {
 while(column < width-1) {
 img.loadPixels(); 
 sortColumn();
 column++;
 img.updatePixels();
 }
 
 while(row < height-1) {
 img.loadPixels(); 
 sortRow();
 row++;
 img.updatePixels();
 }
 
 image(img,0,0);
 if(!saved && frameCount >= loops) {
 saveFrame(imgFileName+"_"+mode+".png");
 saved = true;
 println("DONE"+frameCount);
 System.exit(0);
 }
}


void sortRow() {
 int x = 0;
 int y = row;
 int xend = 0;
 
 while(xend < width-1) {
 switch(mode) {
 case 0:
 x = getFirstNotBlackX(x, y);
 xend = getNextBlackX(x, y);
 break;
 case 1:
 x = getFirstBrightX(x, y);
 xend = getNextDarkX(x, y);
 break;
 case 2:
 x = getFirstNotWhiteX(x, y);
 xend = getNextWhiteX(x, y);
 break;
 default:
 break;
 }
 
 if(x < 0) break;
 
 int sortLength = xend-x;
 
 color[] unsorted = new color[sortLength];
 color[] sorted = new color[sortLength];
 
 for(int i=0; i<sortLength; i++) {
 unsorted[i] = img.pixels[x + i + y * img.width];
 }
 
 sorted = sort(unsorted);
 
 for(int i=0; i<sortLength; i++) {
 img.pixels[x + i + y * img.width] = sorted[i]; 
 }
 
 x = xend+1;
 }
}


void sortColumn() {
 int x = column;
 int y = 0;
 int yend = 0;
 
 while(yend < height-1) {
 switch(mode) {
 case 0:
 y = getFirstNotBlackY(x, y);
 yend = getNextBlackY(x, y);
 break;
 case 1:
 y = getFirstBrightY(x, y);
 yend = getNextDarkY(x, y);
 break;
 case 2:
 y = getFirstNotWhiteY(x, y);
 yend = getNextWhiteY(x, y);
 break;
 default:
 break;
 }
 
 if(y < 0) break;
 
 int sortLength = yend-y;
 
 color[] unsorted = new color[sortLength];
 color[] sorted = new color[sortLength];
 
 for(int i=0; i<sortLength; i++) {
 unsorted[i] = img.pixels[x + (y+i) * img.width];
 }
 
 sorted = sort(unsorted);
 
 for(int i=0; i<sortLength; i++) {
 img.pixels[x + (y+i) * img.width] = sorted[i];
 }
 
 y = yend+1;
 }
}


//BLACK
int getFirstNotBlackX(int _x, int _y) {
 int x = _x;
 int y = _y;
 color c;
 while((c = img.pixels[x + y * img.width]) < blackValue) {
 x++;
 if(x >= width) return -1;
 }
 return x;
}

int getNextBlackX(int _x, int _y) {
 int x = _x+1;
 int y = _y;
 color c;
 while((c = img.pixels[x + y * img.width]) > blackValue) {
 x++;
 if(x >= width) return width-1;
 }
 return x-1;
}

//BRIGHTNESS
int getFirstBrightX(int _x, int _y) {
 int x = _x;
 int y = _y;
 color c;
 while(brightness(c = img.pixels[x + y * img.width]) < brigthnessValue) {
 x++;
 if(x >= width) return -1;
 }
 return x;
}

int getNextDarkX(int _x, int _y) {
 int x = _x+1;
 int y = _y;
 color c;
 while(brightness(c = img.pixels[x + y * img.width]) > brigthnessValue) {
 x++;
 if(x >= width) return width-1;
 }
 return x-1;
}

//WHITE
int getFirstNotWhiteX(int _x, int _y) {
 int x = _x;
 int y = _y;
 color c;
 while((c = img.pixels[x + y * img.width]) > whiteValue) {
 x++;
 if(x >= width) return -1;
 }
 return x;
}

int getNextWhiteX(int _x, int _y) {
 int x = _x+1;
 int y = _y;
 color c;
 while((c = img.pixels[x + y * img.width]) < whiteValue) {
 x++;
 if(x >= width) return width-1;
 }
 return x-1;
}

The code above first analyzes the entire image and documents the luminosity of each individual pixel. It then proceeds to assign a value to each of these pixels. There are 3 modes that I can sort the pixels by. I can choose to leave the darkest pixels alone and have everything else arrange by brightness, have all brightest pixels stay and arrange everything else by brightness, or rearrange the entire image based on the brightness values of these pixels. I carried out some experimentation to see how these different methods affected the final outcome. I inputed this royalty free stock image of a wave:

Awesome-wave

and these were the various results in order:

Final_0 Final_1 Final_2

Each method had different resulting effects that carried their own appeal. The algorithm was being sensitive to different parts of the image that created carrying results. At this point, I realized that the best thing to do would be to apply all three techniques to the images that I wanted to sort and have them composited onto each other in Photoshop. This would provide me with the most amount of flexibility in deciding how the final images would turn out.

At this juncture, I also needed to decide on what image I would be using in the sorting process. For this, I referred to my concept statement once again.

“Order from the point of view of a computer algorithm is pixel sorting.

I wanted this image to show order and structure but yet, be somewhat organic. From my research, I realized that the best images to use for sorting were those that had clearly discernible features that were high contrast. This would create the signature ‘edges’ seen in Pixel Sorted images. I also thought that using natural features such as mountains and clouds would result in the organic look that I was after. I also liked how the waves turned out in the tests. As such, I decided to use pictures of nature to create the Sorted results.

Since the process was significantly altering the image, I decided to start with the image of the waves that I used in the test. It proved to be rather challenging to take astounding pictures of nature in Singapore and I felt that using Stock Images would be wiser. I found two royalty free stock images of waves that I used in this work:

Awesome-wave waves_foam_sea_wave_ocean_5000x3181

These images were high contrast and had obvious edges that would create good Pixel Sorts.

I also used some images of leaves that I shot in school. I also made sure that the images were high contrast and defined the leaves well by shooting sometime during noon. The sunlight and shadows enhanced the the individual leaves and the overall appearance of the flora.

IMG_4496 IMG_4503

The rest of the process is documented in the follow-up post here.

Author: Kapi

Kapilan Naidu is a multimedia artist, designer, data-junkie, sometimes DJ and bedroom producer.

Leave a Reply