August 27, 2014
Exhibition Alert:
August 28th - Sept 4th @ Fridman Gallery
LANDSCAPE WITH DEVICES
Noa Dolberg Esther Ruiz Phillip Stearns
Opening Reception:Thursday, August 28, 6-8pm

Closing Reception:Thursday, September 4, 6-8pm

Exhibition Alert:

August 28th - Sept 4th @ Fridman Gallery

LANDSCAPE WITH DEVICES

Noa Dolberg
Esther Ruiz
Phillip Stearns

Opening Reception:Thursday, August 28, 6-8pm

Closing Reception:Thursday, September 4, 6-8pm

August 26, 2014
Sun is Always Setting/Rising Somewhere

Sun is Always Setting/Rising Somewhere

July 3, 2014
Shifting

Shifting

June 11, 2014

PureDatrocessarduinoMOS - A workshop

June 14th + 15th in NYC @Harvestworks for the Dark Circuits Festival

Sign up here: http://tammen.org/workshop-pure-datrocessorduinomos/

(Source: vimeo.com)

May 16, 2014
[Jun 14/15] Workshop Pure DatrocessorduinoMOS

A crash course in building connections between Pure Data or Processing and DIY CMOS circuits using Arduino. This is a really fun way of learning how to integrate software based interfaces, custom code, and physical hardware through music! Don’t worry if you’re not a seasoned expert in any of these areas. Beginners are welcome! Examples will be provided and explained along with brief introductions to the systems/environments and how to explore them further on your own. This workshop is part of the Dark Circuits Festival 2014. http://www.darkcircuitsfestival.com

April 23, 2014

adamgrabowski said: You sir, are a pioneer. I was wondering if you would be so kind as to make the source code for your chris christie pixel sorting piece available? that would be amazing and helpful. (I am struggling to learn processing, and any help would be greatly appreciated) Thank you!

/*
RGB Sorting

Made in Processing 2.1.2
By Phillip Stearns

A less glitchy approach to pixel sorting.

Part of the glitchiness, or glitch-like look and feel of Kim Asendorf's
brilliant ASDFPixelSort lies in the fact that when you apply the sort()
method to an array of pixels, you're actually sorting according to the
numeric value of that pixel. Processing treats the color of a pixel
as a single 32 bit number, ordered ARGB in 24 bit colorspace w/ alpha.

A 100% opaque red pixel would have the binary representation of
11111111111111110000000000000000
Alpha  |  Red  | Green  | Blue   
^                              ^
|                              |
MSB                           LSB

MSB = most significant bit, like the 9 in 900 for those used to base ten counting
LSB = least significant bit, like the 1 in 5 million and 21.

This also means that red pixel is a bigger number than a green pixel, which
is greater than a blue pixel.

It's not so much based on a perceptual color evaluation; pixel sorting
looks the way it does because the sorting criteria is based on numbers alone,
which don't quite line up with perception. Why things look interesting when you sort pixels this way is
a result of how we use numbers to describe the color of a pixel.

THIS little program sorts the channels separately, which has a slightly
different, smoother effect overall. Rather than sort the pixels according to their ARGB value, RGBsort first breaks up the image into R G B channels, sorts them individually, then recombines them.  Have a look!
*/


PImage sourceImg;
int sortDirection;

void setup(){
  sourceImg = loadImage("random.jpg");
  size(sourceImg.width, sourceImg.height);
  noLoop(); //stops the draw from looping
  sortDirection = 0; //0 sorts all the rows, 1 sorts all the columns
}

void draw(){
  
  //switch lets us do different things for different cases 
  switch(sortDirection) {
    
    //ror sorting
    case 0: 
      for(int row = 0 ; row < sourceImg.height ; row++){
        RGBsortRow(sourceImg, row);
      }
      break;
    
    //column sorting
    case 1: 
      for(int col = 0 ; col < sourceImg.width ; col++){
        RGBsortColumn(sourceImg, col);
      }
      break;
  }
  
  //display the sorted image
  image(sourceImg, 0, 0);  
}


void RGBsortRow(PImage image, int row){
  
  int[] bufferR = new int[image.width];
  int[] bufferG = new int[image.width];
  int[] bufferB = new int[image.width];
  
  //make sure that the row number exists
  if (row < 0 || row >= height){
    //if it doesn't, please let me know
    println("Row value is out of range.");
  } else{
    //otherwise, please sort
    
    for(int i = 0; i < image.width ; i++){
      //basically we're walking through the row specified in the function arguments and separating the RGB values into their respective buffers
      //to do this, we use the bitwise >> or shift right operator and mask the extraneous bits with the & (AND) 0xFF or 11111111
      bufferR[i] = image.pixels[row*image.width+i] >> 16 & 0xFF;
      bufferG[i] = image.pixels[row*image.width+i] >> 8 & 0xFF;
      bufferB[i] = image.pixels[row*image.width+i] & 0xFF;
    }
    
    //sort the pixels in the buffers
    bufferR = sort(bufferR);
    bufferG = sort(bufferG);
    bufferB = sort(bufferB);
    
    //recombine the RGB values using the << shift left and | (OR) operator
    for(int j = 0; j < image.width ; j++){
      image.pixels[row*image.width+j] = (255 << 24) | (bufferR[j] << 16) | (bufferG[j] << 8) | (bufferB[j]);
    } 
  }
}


//the column sorting works in the same manner
void RGBsortColumn(PImage image, int column){
  int[] bufferR = new int[image.height];
  int[] bufferG = new int[image.height];
  int[] bufferB = new int[image.height];
  if (column < 0 || column >= width){
    println("Column value is out of range.");
  } else{
    for(int i = 0; i < image.height ; i++){
      bufferR[i] = image.pixels[i*image.width+column] >> 16 & 0xFF;
      bufferG[i] = image.pixels[i*image.width+column] >> 8 & 0xFF;
      bufferB[i] = image.pixels[i*image.width+column] & 0xFF;
    }
    bufferR = sort(bufferR);
    bufferG = sort(bufferG);
    bufferB = sort(bufferB);
    for(int j = 0; j < image.height ; j++){
      image.pixels[j*image.width+column] = (255 << 24) | (bufferR[j] << 16) | (bufferG[j] << 8) | (bufferB[j]);
    }
  }
}

April 21, 2014

April 21, 2014

January 30, 2014

RGB Channel Shifting

Top Image Source

Bottom Image Source

January 30, 2014

Sorting Governor Chris Christie

on left: sorting by 32bit ARGB color values

on right: sorting RGB channel values separately

Source Image

January 30, 2014

January 30, 2014
More pixel shifting experiments&#8230;
Source Image:
Processing Code:
//PixelShifting by Phillip Stearns 2014
PImage sourceImg;
int iteration;

void setup(){
  iteration=0;
  sourceImg = loadImage("shift.jpg");
  size(sourceImg.width, sourceImg.height);
}

void draw(){
  int yoffset = int(random(height));
  int xoffset= int(random(width));
  int randomRows= int(random(height)) - yoffset;
  int randomColumns=int(random(width)) - xoffset;
  
  for(int i = 0 ; i &lt; randomRows ; i++){
  shiftRow(sourceImg, i+yoffset, 15);
  }
  for(int j = 0 ; j &lt; randomColumns ; j++){
  shiftColumn(sourceImg, j+xoffset, 15);
  }
  image(sourceImg, 0, 0);
  sourceImg.save("shifted_" +nf(iteration, 3)+ ".png");
  iteration++;
}

void shiftRow(PImage image, int row, int shift){
  int[] buffer = new int[image.width];
  if (row &lt; 0 || row &gt;= height){
    println("Row value is out of range.");
  } else{
    for(int i = 0 ; i &lt; image.width ; i++){
      buffer[(i+shift) % (image.width)] = image.pixels[row*image.width+i];
    }
    for(int j = 0 ; j &lt; image.width ; j++){  

      sourceImg.pixels[row*image.width+j] = buffer[j];
    }
  }
  sourceImg.updatePixels();
}

void shiftColumn(PImage image, int column, int shift){
  int[] buffer = new int[image.height];
  if(column &lt; 0 || column &gt;= width){
    println("Column value is out of range.");
  }else{ 
    for(int i = 0 ; i &lt; image.height ; i++){
      buffer[(i+shift) % (image.height)] = image.pixels[i*image.width+column];
    }
    for(int j = 0 ; j &lt; image.height ; j++){  
      sourceImg.pixels[j*image.width+column] = buffer[j];
    }
  }
  sourceImg.updatePixels();
}

More pixel shifting experiments…

Source Image:

Processing Code:

//PixelShifting by Phillip Stearns 2014
PImage sourceImg;
int iteration;

void setup(){
  iteration=0;
  sourceImg = loadImage("shift.jpg");
  size(sourceImg.width, sourceImg.height);
}

void draw(){
  int yoffset = int(random(height));
  int xoffset= int(random(width));
  int randomRows= int(random(height)) - yoffset;
  int randomColumns=int(random(width)) - xoffset;
  
  for(int i = 0 ; i < randomRows ; i++){
  shiftRow(sourceImg, i+yoffset, 15);
  }
  for(int j = 0 ; j < randomColumns ; j++){
  shiftColumn(sourceImg, j+xoffset, 15);
  }
  image(sourceImg, 0, 0);
  sourceImg.save("shifted_" +nf(iteration, 3)+ ".png");
  iteration++;
}

void shiftRow(PImage image, int row, int shift){
  int[] buffer = new int[image.width];
  if (row < 0 || row >= height){
    println("Row value is out of range.");
  } else{
    for(int i = 0 ; i < image.width ; i++){
      buffer[(i+shift) % (image.width)] = image.pixels[row*image.width+i];
    }
    for(int j = 0 ; j < image.width ; j++){  

      sourceImg.pixels[row*image.width+j] = buffer[j];
    }
  }
  sourceImg.updatePixels();
}

void shiftColumn(PImage image, int column, int shift){
  int[] buffer = new int[image.height];
  if(column < 0 || column >= width){
    println("Column value is out of range.");
  }else{ 
    for(int i = 0 ; i < image.height ; i++){
      buffer[(i+shift) % (image.height)] = image.pixels[i*image.width+column];
    }
    for(int j = 0 ; j < image.height ; j++){  
      sourceImg.pixels[j*image.width+column] = buffer[j];
    }
  }
  sourceImg.updatePixels();
}

January 29, 2014
Playing with wrap around, pixel shift registers. Each row of pixels has been shifted a random amount.
Source Image

Playing with wrap around, pixel shift registers. Each row of pixels has been shifted a random amount.

Source Image

January 29, 2014
Image Source

Image Source

January 29, 2014

Toying around with averaging and sorting on RGB channels…

Source Image