The last time Hackerfall tried to access this page, it returned a not found error. A cached version of the page is below, or clickhereto continue anyway

reimertz.co - Get the coolest Designer News profile

A typical morning in my life. Wake up, make coffee and scroll through last days posts on the www. But this specific day, I opened my designer news profile and realized something funny: you can't upload your own profile photo, you have to draw it yourself, pixel by pixel.

Thats a lot of pixels, the portrait is 20 rows and 20 columns, so not that bad, but the header image consists of 29 rows and 62 columns, that equals to 1,798 possible pixels to click on. I don't wanna do that. Let's implement a hack instead that does this for us!

We need to figure out the following things to make this work.

Let's start from the top.

###How do we get the pixel data from an image?

HTML5 introduced some neat features, on of them was canvases. Let's use that!

var canvas = document.getElementById("header-canvas"),
    img = new Image(),
    imgPixels;

img.src = 'headerimage.jpg';
img.height = 29;
img.width = 62;
canvas.height = img.height;
canvas.width = img.width;

var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);

//Pixels!
imgPixels = ctx.getImageData(0, 0, canvas.width, canvas.height);

###How do we decide if a pixel is black or white?

We first need to convert all the pixels into grayscale and then use a threshold to decide if a pixel should be black or white.

// The data ``imgPixels`` has the following structure.
imgPixels.data[0] // pixel 1 red color
imgPixels.data[1] // pixel 1 green color
imgPixels.data[2] // pixel 1 blue color
imgPixels.data[3] // pixel 1 alpha channel
imgPixels.data[4] // pixel 2 red color
imgPixels.data[5] // pixel 2 green c..

var grayScalePixels [];

for(var i = 0; i<imgPixels.length-1; i+=4){

  var r = imgPixels.data[i],
      g = imgPixels.data[i+1],
      b = imgPixels.data[i+2];
      //ignore alpha channel

  //take (r+g+b)/3 to get grayscale color
  var avg = (r+g+b)/3;

  grayScalePixels.push(avg);
}

var blackAndWhitePixels = [],
    //color value is between 0 - 255, so lets set
    //the threshold in the middle
    threshold = 127;

for(pixel in grayScalePixels){
  var color = (pixel >= threshold) ? 'white' : 'black';
  blackAndWhitePixels.push(color);
}

###How do we store this information and what kind of algorithm should we use?

We know that blackAndWhitePixels only contains 'black'||'white', so we can assume that there will be only two states when iterating over the pixels.

blackAndWhitePixels[i] !== blackAndWhitePixels[i+1] //(color swaps)
blackAndWhitePixels[i] === blackAndWhitePixels[i+1] //(color stay the same)

So all we have to do is to store all the indices when we see this color swap. The following code is pretty self explanatory:

var actions = {
  firstPixelIsBlack: false,
  swapAt: [1,25,35,110]
};


function addNewPixels(){
var colorIsBlack = actions.firstPixelIsBlack,
    cells = document.querySelectorAll('#ProfilePicture .Cell');

  for(var i = 0; i < cells.length-1;i++){
    //trigger a click on the appropriate pixel to make it black
    if(colorIsBlack) swapPixel(cells[i]);

    //if we have reached an index where we should swap
    if(i === actions.swapAt[0]){
      actions.swapAt.shift();
      colorIsBlack = !colorIsBlack;
    }
  }
}

###How do we apply these pixels to designer news?

Since this is already a bit hacky, my idea is to generate some code that we just copy-paste into the js console while editing our designer news profile.

All that is left is to be able to trigger appropriate click-events on each pixel. It's important that we set bubbles: true so that all events bubbles up to the appropriate event-listeners.

var options = {
      'view': window,
      'bubbles': true,
      'cancelable': true
    },
    enter = new MouseEvent('mouseenter', options),
    down = new MouseEvent('mousedown', options),
    up = new MouseEvent('mouseup', options);

function swapPixel(cell) {
  cell.dispatchEvent(enter);
  cell.dispatchEvent(down);
  cell.dispatchEvent(up);
}

##That's all folk, let's try it!

  1. Drop an image in one of the pixel areas below
  2. Calibrate by using the slider
  3. Copy the code
  4. Open your dn profile and click edit
  5. paste code in the console and press enter
  6. Just wow

Header

Portrait

##Thats it, we did it!

I hope you liked it, and if you really, really, ridiculously liked it, don't forget to share it with you friends so I get all that social love I'm craving for.

XOXO

Continue reading on www.reimertz.co