Thrown together by David Tames using Processing and Processing.js
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;
}
}