Difference between revisions of "User:Tom"

From DigitalCraft_Wiki
Jump to navigation Jump to search
m
 
(41 intermediate revisions by the same user not shown)
Line 1: Line 1:
= Project (WORK IN PROGRESS) =
+
= Pixel Sorting=
  
I ran into a couple of gifs that visualised how certain sorting algorithms worked. Normally I don’t understand algorithms, but these visualisations made it so easy and insightful to understand what is going on. Besides that I think it’s cool to see an algorithm at work like this, I also think it has some artistic value. You could call it glitch art (glitch art:——————)
+
I ran into a couple of gifs that visualised how certain sorting algorithms worked. Normally I don’t understand algorithms, but these visualisations made it so easy and insightful to understand what is going on. Besides that I think it’s cool to see an algorithm at work like this, I also think it has some artistic value. You could call it [https://en.wikipedia.org/wiki/Glitch_art Glitch Art].
 +
 
 +
These are some examples of different codes working on a color palette:
 +
 
 +
[[File: PixelSortingExample.gif]]
  
 
It is a code creating a new kind of image by rearranging the original. This results in an image made anonymous. Or maybe more like a vague memory, where everything is still there but over time you start to forget what it looks like. This creates a new memory, a distorted version of the original.
 
It is a code creating a new kind of image by rearranging the original. This results in an image made anonymous. Or maybe more like a vague memory, where everything is still there but over time you start to forget what it looks like. This creates a new memory, a distorted version of the original.
  
What is Pixel Sorting?
+
{|style="margin: 0 auto;"
 +
|[[File:Examplesort1.jpg|480x240px]]
 +
|[[File:Examplesort2.jpg|480x240px]]
 +
|}
 +
{|style="margin: 0 auto;"
 +
|[[File:Examplesort3.jpg|480x240px]]
 +
|[[File:Examplesort4.jpg|480x240px]]
 +
|}
 +
 
 +
== What is Pixel Sorting? ==
  
 
Pixel Sorting is done with a program called Processing. It takes the pixels in a digital image and places them into a semblance of order.
 
Pixel Sorting is done with a program called Processing. It takes the pixels in a digital image and places them into a semblance of order.
Pixel sorting was made popular by an artist of the name Kim Asendorf. He began sorting by developing a code in Processing.
+
Pixel sorting was made popular by an artist of the name [https://www.kimasendorf.com Kim Asendorf]. He began sorting by developing a code in Processing.
  
Examples from artists/reddit
 
  
Experiment
+
= Experiment =
  
CODE!
+
==  Processing ==
  
This is a modified version of the code written bij Kim Asendorf. It is written in Processing language, and requires a folder called ‘data’ in the same location as the .pde processing file.  
+
This is a modified version of the code written bij Kim Asendorf. It is written in Processing language, and requires a folder called ‘data’ in the same location as the .pde processing file. I used it to experiment with different images to discover what would happen. 
  
 
  <nowiki>
 
  <nowiki>
Line 73: Line 85:
 
The code results in a pixel sorting visualisation:  
 
The code results in a pixel sorting visualisation:  
  
GIF MAKEN
+
[[File:Airplanesort.gif]]
 +
 
 +
The result was alright, only I had less control than I wanted to. I did research for some more codes and finally found one called 'Butter'. This code gave me a lot more control. I now had the option to sort the 'black', 'white' and 'bright' of the image.
 +
 
 +
== Butter ==
 +
 
 +
\begin{lstlisting}
 +
 
 +
(function () {
 +
  var validModes = ['black', 'bright', 'white'];
 +
  var defaultMode = validModes[0];
 +
 
 +
  function Butter(mode, threshold) {
 +
    this.mode = mode || defaultMode;
 +
    if (validModes.indexOf(this.mode) === -1) {
 +
      console.log('Butter has no mode called "' + this.mode + '".');
 +
      this.mode = defaultMode;
 +
    }
 +
 
 +
    // defaults
 +
    this.threshold = {
 +
      black: -10000000,
 +
      white: -6000000,
 +
      bright: 30
 +
    };
 +
 
 +
    if (typeof threshold !== 'undefined' && threshold !== null) {
 +
      this.threshold[this.mode] = threshold;
 +
    }
 +
  }
 +
 
 +
  Butter.prototype.sort = function sort(canvas, iterations) {
 +
    if (!canvas) {
 +
      throw 'Butter needs a <canvas> to sort';
 +
    }
 +
    var context = canvas.getContext('2d'),
 +
        width = canvas.width,
 +
        height = canvas.height,
 +
        // Get the current data
 +
        imageData = context.getImageData(0, 0, width, height),
 +
        // And sort it
 +
        sortedImage = this.sortImageData(imageData, width, height, iterations);
 +
 
 +
    context.putImageData(sortedImage, 0, 0);
 +
  };
 +
 
 +
  Butter.prototype.sortImageData = function sortImageData(imageData, width, height, iterations) {
 +
    this.imageData = imageData;
 +
    this.width = width;
 +
    this.height = height;
 +
    iterations || (iterations = 1);
 +
 
 +
    for (var i = 0; i < iterations; i++) {
 +
 
 +
      for (var column = 0; column < this.width; column++) {
 +
        this.sortColumn(column);
 +
      }
 +
 
 +
      for (var row = 0; row < this.height; row++) {
 +
        this.sortRow(row);
 +
      }
 +
    }
 +
 
 +
    return this.imageData;
 +
  };
 +
 
 +
  Butter.prototype.setThreshold = function setThreshold(value) {
 +
    this.threshold[this.mode] = value;
 +
  };
 +
 
 +
  Butter.prototype.sortColumn = function sortColumn(x) {
 +
    var ranges = this.getRangesForColumn(x),
 +
        range, width, pixelData;
 +
 
 +
    // For each range...
 +
    for (var i = 0; i < ranges.length; i++) {
 +
      range = ranges[i];
 +
      width = range.end - range.start;
 +
 
 +
      pixelData = new Array(width);
 +
 
 +
      // Get all the pixels in that range
 +
      for (var j = 0; j < width; j++) {
 +
        pixelData[j] = this.getPixelValue(x, range.start + j);
 +
      }
 +
 
 +
      // Sort them!
 +
      pixelData.sort();
 +
 
 +
      // And put the new pixels back
 +
      for (var j = 0; j < width; j++) {
 +
        this.setPixelValue(x, (range.start + j), pixelData[j]);
 +
      }
 +
    }
 +
  };
 +
 
 +
  Butter.prototype.sortRow = function sortRow(y) {
 +
    var ranges = this.getRangesForRow(y),
 +
        range, width, pixelData;
 +
 
 +
    // For each range...
 +
    for (var i = 0; i < ranges.length; i++) {
 +
      range = ranges[i];
 +
      width = range.end - range.start;
 +
 
 +
      pixelData = new Array(width);
 +
 
 +
      // Get all the pixels in that range
 +
      for (var j = 0; j < width; j++) {
 +
        pixelData[j] = this.getPixelValue(range.start + j, y);
 +
      }
 +
 
 +
      // Sort them!
 +
      pixelData.sort();
 +
 
 +
      // And put the new pixels back
 +
      for (var j = 0; j < width; j++) {
 +
        this.setPixelValue((range.start + j), y, pixelData[j]);
 +
      }
 +
    }
 +
  };
 +
 
 +
  Butter.prototype.getRangesForColumn = function getRangesForColumn(x) {
 +
    var ranges = [],
 +
        start = 0,
 +
        end = 0,
 +
        findFirst, findNext;
 +
 
 +
    switch(this.mode) {
 +
      case 'black':
 +
        findFirst = this.getFirstNotBlackY;
 +
        findNext = this.getNextBlackY;
 +
        break;
 +
 
 +
      case 'bright':
 +
        findFirst = this.getFirstBrightY;
 +
        findNext = this.getNextDarkY;
 +
        break;
 +
 
 +
      case 'white':
 +
        findFirst = this.getFirstNotWhiteY;
 +
        findNext = this.getNextWhiteY;
 +
        break;
 +
    }
 +
 
 +
    for ( ; end < this.height; start = (end + 1)) {
 +
      start = findFirst.call(this, x, start);
 +
      end = findNext.call(this, x, start);
 +
 
 +
      // No more ranges
 +
      if (start < 0 || start >= this.height) break;
 +
 
 +
      ranges.push({start: start, end: end});
 +
    }
 +
    return ranges;
 +
  };
 +
 
 +
  Butter.prototype.getRangesForRow = function getRangesForRow(y) {
 +
    var ranges = [],
 +
        start = 0,
 +
        end = 0,
 +
        findFirst, findNext;
 +
 
 +
    switch(this.mode) {
 +
      case 'black':
 +
        findFirst = this.getFirstNotBlackX;
 +
        findNext = this.getNextBlackX;
 +
        break;
 +
 
 +
      case 'bright':
 +
        findFirst = this.getFirstBrightX;
 +
        findNext = this.getNextDarkX;
 +
        break;
 +
 
 +
      case 'white':
 +
        findFirst = this.getFirstNotWhiteX;
 +
        findNext = this.getNextWhiteX;
 +
        break;
 +
    }
 +
 
 +
    for ( ; end < this.width; start = (end + 1)) {
 +
      start = findFirst.call(this, start, y);
 +
      end = findNext.call(this, start, y);
 +
 
 +
      // No more ranges
 +
      if (start < 0 || start >= this.width) break;
 +
 
 +
      ranges.push({start: start, end: end});
 +
    }
 +
    return ranges;
 +
  };
 +
 
 +
  /*
 +
    Finders
 +
  */
 +
 
 +
  Butter.prototype.getFirstNotBlackX = function getFirstNotBlackX(x, y) {
 +
    // Loop until we find a match
 +
    for ( ; this.getPixelValue(x, y) < this.threshold.black; x++) {
 +
      // Oh no, we've reached the edge!
 +
      if (x >= this.width) return -1;
 +
    }
 +
    // Return the match
 +
    return x;
 +
  }
 +
 
 +
  Butter.prototype.getNextBlackX = function getNextBlackX(x, y) {
 +
    // We want the _next_ one
 +
    x += 1;
 +
    for ( ; this.getPixelValue(x, y) > this.threshold.black; x++) {
 +
      if (x >= this.width) return this.width - 1;
 +
    }
 +
    return x;
 +
  }
 +
 
 +
 
 +
  Butter.prototype.getFirstBrightX = function getFirstBrightX(x, y) {
 +
    for ( ; this.getPixelBrightness(x, y) < this.threshold.bright; x++) {
 +
      if (x >= this.width) return -1;
 +
    }
 +
    return x;
 +
  }
 +
 
 +
  Butter.prototype.getNextDarkX = function getNextDarkX(x, y) {
 +
    x += 1;
 +
    for ( ; this.getPixelBrightness(x, y) > this.threshold.bright; x++) {
 +
      if (x >= this.width) return this.width - 1;
 +
    }
 +
    return x;
 +
  }
 +
 
 +
 
 +
  Butter.prototype.getFirstNotWhiteX = function getFirstNotWhiteX(x, y) {
 +
    for ( ; this.getPixelValue(x, y) > this.threshold.white; x++) {
 +
      if (x >= this.width) return -1;
 +
    }
 +
    return x;
 +
  }
 +
 
 +
  Butter.prototype.getNextWhiteX = function getNextWhiteX(x, y) {
 +
    x += 1;
 +
    for ( ; this.getPixelValue(x, y) < this.threshold.white; x++) {
 +
      if (x >= this.width) return this.width - 1;
 +
    }
 +
    return x;
 +
  }
 +
 
 +
 
 +
  Butter.prototype.getFirstNotBlackY = function getFirstNotBlackY(x, y) {
 +
    for ( ; this.getPixelValue(x, y) < this.threshold.black; y++) {
 +
      if (y >= this.height) return -1;
 +
    }
 +
    return y;
 +
  }
 +
 
 +
  Butter.prototype.getNextBlackY = function getNextBlackY(x, y) {
 +
    y += 1;
 +
    for ( ; this.getPixelValue(x, y) > this.threshold.black; y++) {
 +
      if (y >= this.height) return this.height - 1;
 +
    }
 +
    return y;
 +
  }
 +
 
 +
 
 +
  Butter.prototype.getFirstBrightY = function getFirstBrightY(x, y) {
 +
    for ( ; this.getPixelBrightness(x, y) < this.threshold.bright; y++) {
 +
      if (y >= this.height) return -1;
 +
    }
 +
    return y;
 +
  }
 +
 
 +
  Butter.prototype.getNextDarkY = function getNextDarkY(x, y) {
 +
    y += 1;
 +
    for ( ; this.getPixelBrightness(x, y) > this.threshold.bright; y++) {
 +
      if (y >= this.height) return this.height - 1;
 +
    }
 +
    return y;
 +
  }
 +
 
 +
 
 +
  Butter.prototype.getFirstNotWhiteY = function getFirstNotWhiteY(x, y) {
 +
    for ( ; this.getPixelValue(x, y) > this.threshold.white; y++) {
 +
      if (y >= this.height) return -1;
 +
    }
 +
    return y;
 +
  }
 +
 
 +
  Butter.prototype.getNextWhiteY = function getNextWhiteY(x, y) {
 +
    y += 1;
 +
    for ( ; this.getPixelValue(x, y) < this.threshold.white; y++) {
 +
      if (y >= this.height) return this.height - 1;
 +
    }
 +
    return y;
 +
  }
 +
 
 +
  /*
 +
    Utilities
 +
  */
 +
 
 +
  Butter.prototype.getPixelOffset = function getPixelOffset(x, y) {
 +
    return (x + y * this.width) * 4;
 +
  };
 +
 
 +
  Butter.prototype.setPixelValue = function setPixelValue(x, y, val) {
 +
    var offset = this.getPixelOffset(x, y),
 +
        r = (val >> 16) & 255,
 +
        g = (val >> 8) & 255,
 +
        b = val & 255,
 +
        data = this.imageData.data;
 +
 
 +
    data[offset] = r;
 +
    data[offset + 1] = g;
 +
    data[offset + 2] = b;
 +
  }
 +
 
 +
  Butter.prototype.getPixelValue = function getPixelValue(x, y) {
 +
    var offset = this.getPixelOffset(x, y),
 +
        data = this.imageData.data,
 +
        r = data[offset],
 +
        g = data[offset + 1],
 +
        b = data[offset + 2];
 +
 
 +
    return ( ((255 << 8) | r) << 8 | g) << 8 | b;
 +
  }
 +
 
 +
  Butter.prototype.getPixelBrightness = function getPixelBrightness(x, y) {
 +
    var offset = this.getPixelOffset(x, y),
 +
        data = this.imageData.data,
 +
        r = data[offset],
 +
        g = data[offset + 1],
 +
        b = data[offset + 2];
 +
 
 +
    return Math.max(r, g, b) / 255 * 100;
 +
  }
 +
 
 +
  // Let it loose
 +
  if ((typeof module !== "undefined") && (module.exports)) {
 +
    module.exports = Butter;
 +
  } else {
 +
    this.Butter = Butter;
 +
  }
 +
 
 +
This code gave me a lot more control. For instance with the old Apple universe background image:
 +
 
 +
[[File:apple.jpg]]
 +
[[File:apple1.png]]
 +
[[File:apple2.png]]
 +
[[File:apple3.png]]
 +
 
 +
= Other Experiments =
 +
 
 +
These are experiments i tried with simpler codes.
 +
 
 +
[[File:Favicon.png | 250px]]
 +
 
 +
Sorted horizontally from dark to light colors.
 +
 
 +
[[File:Favicon Sort.png | 250px]]
 +
 
 +
[[File:1.png | 250px]]
 +
 
 +
[[File:2.png | 250px]]
 +
 
 +
[[File:3ico.png | 250px]]
 +
 
 +
[[File:4ico.png | 250px]]
 +
 
 +
= Former Glory: Logo's & Icons =
 +
 
 +
As I mentioned before, the result of pixel sorting reminds me of some distant memory, distorted over time. I want to recreate this feeling in a series of images.
 +
 
 +
First I needed something that counts as some sort of memory, something recognisable. Second, it had to be recognisable for a larger audience. So I had to find some sort of 'collective memory'. For this I chose to use iconic logo's of worldwide brands like McDonalds or Coca Cola. These brands are known worldwide and have been around for many years. Chances are high people will recognise them, even when the logos appear distorted.
 +
 
 +
[[File:billboardold.jpg | center | 240px ]]
 +
 
 +
== Chanel ==
 +
[[File:ChanelLogo.jpg | 400px | center ]]
 +
 
 +
=== Sorted + Contact Sheet ===
 +
 
 +
Click to enlarge!!!
 +
 
 +
[[File:ChanelLogo6.png | center]]
 +
 
 +
[[File:ChanelSheet.jpg | center| 720px]]
 +
 
 +
== Coca Cola ==
 +
[[File:Coca Cola logo.jpg | 400px | center ]]
 +
 
 +
=== Sorted + Contact Sheet ===
 +
 
 +
Click to enlarge!!!
 +
 
 +
[[File:CocaColaLogo17.png | center]]
 +
 
 +
[[File:CocaColaSheet.jpg | center| 720px]]
 +
 
 +
== Marlboro ==
 +
[[File:MarlboroLogo.jpg | 400px | center ]]
 +
 
 +
=== Sorted + Contact Sheet ===
 +
 
 +
Click to enlarge!!!
 +
 
 +
[[File:MarlboroLogo2.png | 400px | center]]
 +
 
 +
[[File:MarlboroSheet.jpg | center| 720px]]
 +
 
 +
== Mcdonalds ==
 +
[[File:McdonaldsLogo.png | center ]]
 +
 
 +
=== Sorted + Contact Sheet ===
 +
 
 +
Click to enlarge!!!
 +
 
 +
[[File:McDonaldsLogo21.png | 400px | center ]]
 +
 
 +
[[File:McDonaldsSheet.jpg | center| 720px]]
 +
 
 +
== Pepsi ==
 +
[[File:PepsiLogo.jpg | 400px | center ]]
 +
 
 +
=== Sorted + Contact Sheet ===
 +
 
 +
Click to enlarge!!!
 +
 
 +
[[File:PepsiLogo3.png | 400 px | center]]
 +
 
 +
[[File:PepsiSheet.jpg | center| 720px]]
 +
 
 +
== Starbucks ==
 +
[[File:StarbucksLogo.png | 400px | center ]]
 +
 
 +
=== Sorted + Contact Sheet ===
 +
 
 +
Click to enlarge!!!
 +
 
 +
[[File:Starbuckslogo14.png | 400px | center]]
 +
 
 +
[[File:StarbucksSheet.jpg | center| 720px]]
 +
 
 +
== Volkswagen ==
 +
[[File:VolkswagenLogo.png | 300px | center ]]
 +
 
 +
=== Sorted + Contact Sheet ===
 +
 
 +
Click to enlarge!!!
 +
 
 +
[[File:VolkswagenLogo20.png | center]]
 +
 
 +
[[File:VolkswagenSheet.jpg | center| 720px]]

Latest revision as of 20:42, 4 February 2018

Pixel Sorting

I ran into a couple of gifs that visualised how certain sorting algorithms worked. Normally I don’t understand algorithms, but these visualisations made it so easy and insightful to understand what is going on. Besides that I think it’s cool to see an algorithm at work like this, I also think it has some artistic value. You could call it Glitch Art.

These are some examples of different codes working on a color palette:

PixelSortingExample.gif

It is a code creating a new kind of image by rearranging the original. This results in an image made anonymous. Or maybe more like a vague memory, where everything is still there but over time you start to forget what it looks like. This creates a new memory, a distorted version of the original.

Examplesort1.jpg Examplesort2.jpg
Examplesort3.jpg Examplesort4.jpg

What is Pixel Sorting?

Pixel Sorting is done with a program called Processing. It takes the pixels in a digital image and places them into a semblance of order. Pixel sorting was made popular by an artist of the name Kim Asendorf. He began sorting by developing a code in Processing.


Experiment

Processing

This is a modified version of the code written bij Kim Asendorf. It is written in Processing language, and requires a folder called ‘data’ in the same location as the .pde processing file. I used it to experiment with different images to discover what would happen.

PImage img;
PImage sorted;
int index = 0;

void setup() {
  size(800, 400);

  img = loadImage("afbeelding.jpg");
  sorted = createImage(img.width, img.height, RGB);
  sorted = img.get();
}

void draw() {
  println(frameRate);

  sorted.loadPixels();

  // Selection sort!
  for (int y = 0; y < sorted.height; y++) {

    float record = -1;
    int selectedPixel = index;

    for (int x = index; x < sorted.width; x++) {
      int loc = y * sorted.width + x;
      color pix = sorted.pixels[loc];
      float b = brightness(pix);
      if (b > record) {
        selectedPixel = loc;
        record = b;
      }
    }
    // Swap selectedPixel with i
    color temp = sorted.pixels[y * sorted.width + index];
    sorted.pixels[y * sorted.width + index] = sorted.pixels[selectedPixel];
    sorted.pixels[selectedPixel] = temp;
  }
  if (index < sorted.width -1) {
    index++;
  } else {
    save("sorted.jpg");
    frameRate(0);
  }

  sorted.updatePixels();

  background(0);
  image(img, 0, 0);
  image(sorted, 400, 0);
}

The code results in a pixel sorting visualisation:

Airplanesort.gif

The result was alright, only I had less control than I wanted to. I did research for some more codes and finally found one called 'Butter'. This code gave me a lot more control. I now had the option to sort the 'black', 'white' and 'bright' of the image.

Butter

\begin{lstlisting}

(function () {

 var validModes = ['black', 'bright', 'white'];
 var defaultMode = validModes[0];
 function Butter(mode, threshold) {
   this.mode = mode || defaultMode;
   if (validModes.indexOf(this.mode) === -1) {
     console.log('Butter has no mode called "' + this.mode + '".');
     this.mode = defaultMode;
   }
   // defaults
   this.threshold = {
     black: -10000000,
     white: -6000000,
     bright: 30
   };
   if (typeof threshold !== 'undefined' && threshold !== null) {
     this.threshold[this.mode] = threshold;
   }
 }
 Butter.prototype.sort = function sort(canvas, iterations) {
   if (!canvas) {
     throw 'Butter needs a <canvas> to sort';
   }
   var context = canvas.getContext('2d'),
       width = canvas.width,
       height = canvas.height,
       // Get the current data
       imageData = context.getImageData(0, 0, width, height),
       // And sort it
       sortedImage = this.sortImageData(imageData, width, height, iterations);
   context.putImageData(sortedImage, 0, 0);
 };
 Butter.prototype.sortImageData = function sortImageData(imageData, width, height, iterations) {
   this.imageData = imageData;
   this.width = width;
   this.height = height;
   iterations || (iterations = 1);
   for (var i = 0; i < iterations; i++) {
     for (var column = 0; column < this.width; column++) {
       this.sortColumn(column);
     }
     for (var row = 0; row < this.height; row++) {
       this.sortRow(row);
     }
   }
   return this.imageData;
 };
 Butter.prototype.setThreshold = function setThreshold(value) {
   this.threshold[this.mode] = value;
 };
 Butter.prototype.sortColumn = function sortColumn(x) {
   var ranges = this.getRangesForColumn(x),
       range, width, pixelData;
   // For each range...
   for (var i = 0; i < ranges.length; i++) {
     range = ranges[i];
     width = range.end - range.start;
     pixelData = new Array(width);
     // Get all the pixels in that range
     for (var j = 0; j < width; j++) {
       pixelData[j] = this.getPixelValue(x, range.start + j);
     }
     // Sort them!
     pixelData.sort();
     // And put the new pixels back
     for (var j = 0; j < width; j++) {
       this.setPixelValue(x, (range.start + j), pixelData[j]);
     }
   }
 };
 Butter.prototype.sortRow = function sortRow(y) {
   var ranges = this.getRangesForRow(y),
       range, width, pixelData;
   // For each range...
   for (var i = 0; i < ranges.length; i++) {
     range = ranges[i];
     width = range.end - range.start;
     pixelData = new Array(width);
     // Get all the pixels in that range
     for (var j = 0; j < width; j++) {
       pixelData[j] = this.getPixelValue(range.start + j, y);
     }
     // Sort them!
     pixelData.sort();
     // And put the new pixels back
     for (var j = 0; j < width; j++) {
       this.setPixelValue((range.start + j), y, pixelData[j]);
     }
   }
 };
 Butter.prototype.getRangesForColumn = function getRangesForColumn(x) {
   var ranges = [],
       start = 0,
       end = 0,
       findFirst, findNext;
   switch(this.mode) {
     case 'black':
       findFirst = this.getFirstNotBlackY;
       findNext = this.getNextBlackY;
       break;
     case 'bright':
       findFirst = this.getFirstBrightY;
       findNext = this.getNextDarkY;
       break;
     case 'white':
       findFirst = this.getFirstNotWhiteY;
       findNext = this.getNextWhiteY;
       break;
   }
   for ( ; end < this.height; start = (end + 1)) {
     start = findFirst.call(this, x, start);
     end = findNext.call(this, x, start);
     // No more ranges
     if (start < 0 || start >= this.height) break;
     ranges.push({start: start, end: end});
   }
   return ranges;
 };
 Butter.prototype.getRangesForRow = function getRangesForRow(y) {
   var ranges = [],
       start = 0,
       end = 0,
       findFirst, findNext;
   switch(this.mode) {
     case 'black':
       findFirst = this.getFirstNotBlackX;
       findNext = this.getNextBlackX;
       break;
     case 'bright':
       findFirst = this.getFirstBrightX;
       findNext = this.getNextDarkX;
       break;
     case 'white':
       findFirst = this.getFirstNotWhiteX;
       findNext = this.getNextWhiteX;
       break;
   }
   for ( ; end < this.width; start = (end + 1)) {
     start = findFirst.call(this, start, y);
     end = findNext.call(this, start, y);
     // No more ranges
     if (start < 0 || start >= this.width) break;
     ranges.push({start: start, end: end});
   }
   return ranges;
 };
 /*
   Finders
 */
 Butter.prototype.getFirstNotBlackX = function getFirstNotBlackX(x, y) {
   // Loop until we find a match
   for ( ; this.getPixelValue(x, y) < this.threshold.black; x++) {
     // Oh no, we've reached the edge!
     if (x >= this.width) return -1;
   }
   // Return the match
   return x;
 }
 Butter.prototype.getNextBlackX = function getNextBlackX(x, y) {
   // We want the _next_ one
   x += 1;
   for ( ; this.getPixelValue(x, y) > this.threshold.black; x++) {
     if (x >= this.width) return this.width - 1;
   }
   return x;
 }


 Butter.prototype.getFirstBrightX = function getFirstBrightX(x, y) {
   for ( ; this.getPixelBrightness(x, y) < this.threshold.bright; x++) {
     if (x >= this.width) return -1;
   }
   return x;
 }
 Butter.prototype.getNextDarkX = function getNextDarkX(x, y) {
   x += 1;
   for ( ; this.getPixelBrightness(x, y) > this.threshold.bright; x++) {
     if (x >= this.width) return this.width - 1;
   }
   return x;
 }


 Butter.prototype.getFirstNotWhiteX = function getFirstNotWhiteX(x, y) {
   for ( ; this.getPixelValue(x, y) > this.threshold.white; x++) {
     if (x >= this.width) return -1;
   }
   return x;
 }
 Butter.prototype.getNextWhiteX = function getNextWhiteX(x, y) {
   x += 1;
   for ( ; this.getPixelValue(x, y) < this.threshold.white; x++) {
     if (x >= this.width) return this.width - 1;
   }
   return x;
 }


 Butter.prototype.getFirstNotBlackY = function getFirstNotBlackY(x, y) {
   for ( ; this.getPixelValue(x, y) < this.threshold.black; y++) {
     if (y >= this.height) return -1;
   }
   return y;
 }
 Butter.prototype.getNextBlackY = function getNextBlackY(x, y) {
   y += 1;
   for ( ; this.getPixelValue(x, y) > this.threshold.black; y++) {
     if (y >= this.height) return this.height - 1;
   }
   return y;
 }


 Butter.prototype.getFirstBrightY = function getFirstBrightY(x, y) {
   for ( ; this.getPixelBrightness(x, y) < this.threshold.bright; y++) {
     if (y >= this.height) return -1;
   }
   return y;
 }
 Butter.prototype.getNextDarkY = function getNextDarkY(x, y) {
   y += 1;
   for ( ; this.getPixelBrightness(x, y) > this.threshold.bright; y++) {
     if (y >= this.height) return this.height - 1;
   }
   return y;
 }


 Butter.prototype.getFirstNotWhiteY = function getFirstNotWhiteY(x, y) {
   for ( ; this.getPixelValue(x, y) > this.threshold.white; y++) {
     if (y >= this.height) return -1;
   }
   return y;
 }
 Butter.prototype.getNextWhiteY = function getNextWhiteY(x, y) {
   y += 1;
   for ( ; this.getPixelValue(x, y) < this.threshold.white; y++) {
     if (y >= this.height) return this.height - 1;
   }
   return y;
 }
 /*
   Utilities
 */
 Butter.prototype.getPixelOffset = function getPixelOffset(x, y) {
   return (x + y * this.width) * 4;
 };
 Butter.prototype.setPixelValue = function setPixelValue(x, y, val) {
   var offset = this.getPixelOffset(x, y),
       r = (val >> 16) & 255,
       g = (val >> 8) & 255,
       b = val & 255,
       data = this.imageData.data;
   data[offset] = r;
   data[offset + 1] = g;
   data[offset + 2] = b;
 }
 Butter.prototype.getPixelValue = function getPixelValue(x, y) {
   var offset = this.getPixelOffset(x, y),
       data = this.imageData.data,
       r = data[offset],
       g = data[offset + 1],
       b = data[offset + 2];
   return ( ((255 << 8) | r) << 8 | g) << 8 | b;
 }
 Butter.prototype.getPixelBrightness = function getPixelBrightness(x, y) {
   var offset = this.getPixelOffset(x, y),
       data = this.imageData.data,
       r = data[offset],
       g = data[offset + 1],
       b = data[offset + 2];
   return Math.max(r, g, b) / 255 * 100;
 }
 // Let it loose
 if ((typeof module !== "undefined") && (module.exports)) {
   module.exports = Butter;
 } else {
   this.Butter = Butter;
 }

This code gave me a lot more control. For instance with the old Apple universe background image:

Apple.jpg Apple1.png Apple2.png Apple3.png

Other Experiments

These are experiments i tried with simpler codes.

Favicon.png

Sorted horizontally from dark to light colors.

Favicon Sort.png

1.png

2.png

3ico.png

4ico.png

Former Glory: Logo's & Icons

As I mentioned before, the result of pixel sorting reminds me of some distant memory, distorted over time. I want to recreate this feeling in a series of images.

First I needed something that counts as some sort of memory, something recognisable. Second, it had to be recognisable for a larger audience. So I had to find some sort of 'collective memory'. For this I chose to use iconic logo's of worldwide brands like McDonalds or Coca Cola. These brands are known worldwide and have been around for many years. Chances are high people will recognise them, even when the logos appear distorted.

Chanel

ChanelLogo.jpg

Sorted + Contact Sheet

Click to enlarge!!!

ChanelLogo6.png
ChanelSheet.jpg

Coca Cola

Coca Cola logo.jpg

Sorted + Contact Sheet

Click to enlarge!!!

CocaColaLogo17.png
CocaColaSheet.jpg

Marlboro

MarlboroLogo.jpg

Sorted + Contact Sheet

Click to enlarge!!!

MarlboroLogo2.png
MarlboroSheet.jpg

Mcdonalds

McdonaldsLogo.png

Sorted + Contact Sheet

Click to enlarge!!!

McDonaldsLogo21.png
McDonaldsSheet.jpg

Pepsi

PepsiLogo.jpg

Sorted + Contact Sheet

Click to enlarge!!!

PepsiLogo3.png
PepsiSheet.jpg

Starbucks

StarbucksLogo.png

Sorted + Contact Sheet

Click to enlarge!!!

Starbuckslogo14.png
StarbucksSheet.jpg

Volkswagen

VolkswagenLogo.png

Sorted + Contact Sheet

Click to enlarge!!!

VolkswagenLogo20.png
VolkswagenSheet.jpg