Reordering Pixels
I played with reordering pixels in an image based on their brightness or color. It’s not particularly novel, but I thought it would be fun.
I started with black/white/grey images since ordering on a greyscale is straightforward while ordering color is not.
The first attempt reordered horizontally, as shown below and in the code here.
and
However, I thought a circle would be more appealing. Implementing this was non-trivial, as I had to figure out how to assign the ordered colors into a spiral in the final image.
It was tempting to try to figure out how to map the ith color in the ordered color list to some particular x/y coordinate in the final image. Instead, I ended up ordering the x/y coordinate pairs in the final image based on “spiral order.” Then I used a for loop to go through the color list and assign each color to the matching element in the sorted vector of x-y pairs. This way I never needed to figure out a mapping to a particular pixel, but rather just match up each color and pixel in order.
This code shows how I created and walked through the color list.
<em>vector <int> colors;
for (int i = 0; i < width * height; i++){
colors.push_back(pixOrig[i]);
}
ofSort(colors);
// create a vector of all pixels, and sort them by spiral order from center
vector <ofVec2f> coords;
for (int i = 0; i < width; i++){
for (int j = 0; j < height; j++){
// redefine coordinates from center for sorting, note the offset needed for the center
coords.push_back(ofVec2f(float(i) - width / 2,float(j) - height / 2));
}
}
// sort the ordered pairs of pixels into a spiral, using function declared above
ofSort(coords, orderPixels);
// walk through the vector of ordered pixels and assign colors in order
for (int i = 0; i < colors.size(); i++){
ofVec2f k = coords[i];
pixFinal[int((k.y + height/2) * width + (k.x + width/2))] = colors[i];
}</em>
And, this is the sorting function “orderPixels” which was used to sort the vector of ordered pairs of coordinates.
bool ofApp::orderPixels(ofVec2f a, ofVec2f b){
// goal: return true if a > b
// check if radius a is larger than radius b, using pythagorian theorem
if(sqrt(a.x * a.x + a.y * a.y) > sqrt(b.x * b.x + b.y * b.y) + 1){
return true;
//check if radius b is larger than radius a
} else if (sqrt(a.x * a.x + a.y * a.y) + 1 < sqrt(b.x * b.x + b.y * b.y)){
return false;
// if the radius is within 1, check the angles
} else {
// both points below midpoint?
if(a.y < 0 and b.y < 0){
// and further left?
if(a.x < b.x){
return true;
} else {
return false;
}
// both points above midpoint?
} else if(a.y > 0 and b.y > 0){
// and further right?
if(a.x > b.x){
return true;
} else {
return false;
}
// one point above midpoint, and the other below?
} else if(a.y > b.y){
return true;
} else {
return false;
}
} }
The rest of the code is here.
The result is this:
and
and
and
I also played with reversing the order:
and
Next up will be defining functions to order color. This harkens back in a way to the color interpolation tests I did in D3/JS last year.