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.

Written on November 23, 2014