Thrown together by David Tames using Processing and Processing.js

back to DMI project index

Source Code

/**
 * interaction of color 1
 * 
 * Experiment with color perception and how it is determined by context, 
 * the color of the small block looks different depending on the color of the
 * field surrounding it, inspired by "Interaction of Color" by Josef Albers,
 * see http://yalepress.yale.edu/yupbooks/book.asp?isbn=9780300115956
 * 
 * Developed and tested using Processing 1.1, requires ColorRect and
 * ColorScrollbar classes (included below).
 * 
 * This code is released to the public domain, however, attribution is
 * appreciated. Cover likeness of "Interaction of Color" copyright 1963 by
 * Yale University Press and used in the current context for educational
 * purposes under fair use guidelines, other uses may be restricted.
 * 
 * David Tames
 * http://kino-eye.com
 *
 * Version 1.0 July 1, 2010
 * Version 1.1 March 6, 2011, revised for Processing.js, fonts not working right
 * BUGS: rounding errors cause block colors to change on multiple selection clicks.
 * we might fix this in a future version, or if you do, let me know.
 */

// Scrollbar stuff
ColorScrollbar barHue;
ColorScrollbar barSaturation;
ColorScrollbar barValue;
int barPosHue;
int barPosSaturation;
int barPosValue;
int SLIDER_HUE = 1;
int SLIDER_SATURATION = 2;
int SLIDER_VALUE = 3;

// UI screen position constants (we don't use these consistently yet,
// too many hard coded values throughout the code at the moment, the
// code that puts UI elements on the screen should  be driven by the
// set of constants here.
final int fieldWidth = 350;
final int fieldHeight = 440;
final int blockWidth = 100;
final int blockHeight = 100;
final int margin = 20;
final int UIsp = 28; // spacing between sliders
final int UIsep = 210; // spacing between control groups
final int UIx = 490, UIy = 130; // starting position of controllers
final int UIswh = 50; // height of the swatch
final int UIcw = 220, UIch = 16; // height and width of sliders

// type 
PFont textRegular;
PFont textSmall;
PFont textUI;
String userMessage = "Color of block:                   ";

// color values
int blockHue = 0, blockSat = 0, blockValue = 0;
int blockCount = 7;
ColorRect[] rectangle = new ColorRect[blockCount];
int targetBlock; 
int lastBlock;
int radioID;
int fieldHue = 0, fieldSaturation = 0, fieldValue = 0;
int startColor = 0;
int bgColor = color (60, 60, 60);

// --------------------------------------------------------------
// setup
// --------------------------------------------------------------
//
void setup() {
  size(800,600);
  frameRate(25);
  smooth();
  colorMode(HSB, 360, 100, 100); // hue in degress, saturation 0-100%, Value 0-100%
  // intitialize colors and UI
  textRegular = loadFont("Helvetica-20.vlw");
  textSmall = loadFont("Helvetica-12.vlw");
  textUI = loadFont("OCRAStd-14.vlw");
  // Create Rectangles
  rectangle[0] = new ColorRect (0, 0, 438, 630, 0); 
  rectangle[1] = new ColorRect (38, 74, 368, 146, 1);
  rectangle[2] = new ColorRect (38,220,368,100, 2); 
  rectangle[3] = new ColorRect (38,318,368,100, 3);
  rectangle[4] = new ColorRect (38,418,368,146, 4); 
  rectangle[5] = new ColorRect (188,156,64,64, 5);
  rectangle[6] = new ColorRect ( 188,418,64,64, 6);
  initColors(); 
  // Hue Slider
  barHue = new ColorScrollbar(510, 160, 216, 14, 0.0, 360.0, SLIDER_HUE);
  barHue.setPos(hue(rectangle[targetBlock].getColor()));
  barHue.update(0, 0);
  barHue.display();
  // Saturation Slider
  barSaturation = new ColorScrollbar(510, 200, 216, 14, 0.0, 100.0, SLIDER_SATURATION);
  barSaturation.setPos(saturation(rectangle[targetBlock].getColor()));
  barSaturation.update(0, 0);
  barSaturation.display();
  // Value Slider
  barValue = new ColorScrollbar(510, 240, 216, 14, 0.0, 100.0, SLIDER_VALUE);
  barValue.setPos(brightness(rectangle[targetBlock].getColor()));
  barValue.update(0, 0);
  barValue.display();
}

// --------------------------------------------------------------
// draw
// --------------------------------------------------------------
//
void draw() {
  noStroke();
  background(bgColor);
  rect(margin, margin, fieldWidth, fieldHeight);
  // in the future, it would be nice to get this data from a config file to allow
  // various block arrangements, and even allow interactive configuration, but we'll
  // hard code for now... old template: rect(UIx, UIy-UIswh-UIsp/2, UIcw, UIswh);
  for (int i=0; i x) && (mx < x + sw) && (my > y) && (my < y + sh)) {
      return true;
    } 
    else {
      return false;
    }
  }

  // Draws the scrollbar to the screen

  void display() {
    strokeWeight(lineWeight);
    stroke(scrollerColor);
    fill(backgroundColor);
    rect(x, y, sw, sh);
    if ((rollover == true) || (locked == true)) {
      fill(dotColor);
    } 
    else {
      fill(otherColor);
    }
    rect(pos, y, sh, sh);
  }

  //  Sets the current value of the thumb pos is in the callers units
  void setPos(float pv) {
    pos = map (pv, minVal, maxVal, posMin, posMax);
  }

  // Returns the current value of the thumb pos is in the callers units
  float getPos() {
    float scalar = sw / (sw - sh);
    float ratio = (pos - x) * scalar;
    float offset = minVal + (ratio / sw * (maxVal - minVal));
    return offset;
  }
}

/**
 * ColorRect class
 * 
 */

class ColorRect {

  int myID;
  color myColor;
  int myX;
  int myY;
  int myWidth;
  int myHeight;

  // CONSTRUCTORS

  ColorRect(int xp, int yp, int wp, int hp, color cp, int ip) {
    myID = ip;
    myColor = cp;
    myX = xp;
    myY = yp;
    myWidth  = wp;
    myHeight =  hp;
  }

  ColorRect(int xp, int yp, int wp, int hp, int ip) {
    myID = ip;
    myColor = color (0,0,0);
    myX = xp;
    myY = yp;
    myWidth  = wp;
    myHeight =  hp;
  }

  boolean press(int mx, int my) {
    if (overMe(mx, my) == true) {
       // println ("rect id=" + myID + " was clicked");
      return true;
    } else {
      return false;
    }

  }

  boolean overMe(int px, int py) {
    if ((px > myX) && (px < myX + myWidth) && (py > myY) && (py < myY + myHeight)) {
      return true;
    }  else {
      return false;
    }
  }

  void display() {
    noStroke();
    fill(myColor);
    rect(myX, myY, myWidth, myHeight);
  }

  void setPos(int px, int py) {
    myX = px;
    myX = py;
  }

  int getXPos() {
    return myX;
  }

  int getYPos() {
    return myY;
  }

  void setColor(color pc) {
    myColor = pc;
  }

  color getColor() {
    return myColor;
  }
}