##final###
in this project we looked at making a system that took input from colors and gave a representation of what the color is in a grey space.
my thinking for this project was to make something that has function over form, rather than having states that a unqiue to each color sample, so i decided to go with something that i found would work in a grid layout and or as a stand alone.
the idea behind using ocotogons is that they arragne well and that i can have a duplicate of the shape within the shape so that it can be representative of other attribute of the glyph data
i went with a multi-layer design so that i can have objects effect each other as the values get changed, so i can have for example the attributes for saturations effect hue in some ways to show new information.
(refer to previous post in order to see how each attribute is represented)
-
-
Save oxbowmantella/c6fd9519beb954695d0cd1c115fb188e to your computer and use it in GitHub Desktop.
17.1.MDDN242 PS2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// note: this file is poorly named - it can generally be ignored. | |
// helper functions below for supporting blocks/purview | |
function saveBlocksImages(doZoom) { | |
if(doZoom == null) { | |
doZoom = false; | |
} | |
// generate 960x500 preview.jpg of entire canvas | |
// TODO: should this be recycled? | |
var offscreenCanvas = document.createElement('canvas'); | |
offscreenCanvas.width = 960; | |
offscreenCanvas.height = 500; | |
var context = offscreenCanvas.getContext('2d'); | |
// background is flat white | |
context.fillStyle="#FFFFFF"; | |
context.fillRect(0, 0, 960, 500); | |
context.drawImage(this.canvas, 0, 0, 960, 500); | |
// save to browser | |
var downloadMime = 'image/octet-stream'; | |
var imageData = offscreenCanvas.toDataURL('image/jpeg'); | |
imageData = imageData.replace('image/jpeg', downloadMime); | |
p5.prototype.downloadFile(imageData, 'preview.jpg', 'jpg'); | |
// generate 230x120 thumbnail.png centered on mouse | |
offscreenCanvas.width = 230; | |
offscreenCanvas.height = 120; | |
// background is flat white | |
context = offscreenCanvas.getContext('2d'); | |
context.fillStyle="#FFFFFF"; | |
context.fillRect(0, 0, 230, 120); | |
if(doZoom) { | |
// pixelDensity does the right thing on retina displays | |
var pd = this._pixelDensity; | |
var sx = pd * mouseX - pd * 230/2; | |
var sy = pd * mouseY - pd * 120/2; | |
var sw = pd * 230; | |
var sh = pd * 120; | |
// bounds checking - just displace if necessary | |
if (sx < 0) { | |
sx = 0; | |
} | |
if (sx > this.canvas.width - sw) { | |
sx = this.canvas.width - sw; | |
} | |
if (sy < 0) { | |
sy = 0; | |
} | |
if (sy > this.canvas.height - sh) { | |
sy = this.canvas.height - sh; | |
} | |
// save to browser | |
context.drawImage(this.canvas, sx, sy, sw, sh, 0, 0, 230, 120); | |
} | |
else { | |
// now scaledown | |
var full_width = this.canvas.width; | |
var full_height = this.canvas.height; | |
context.drawImage(this.canvas, 0, 0, full_width, full_height, 0, 0, 230, 120); | |
} | |
imageData = offscreenCanvas.toDataURL('image/png'); | |
imageData = imageData.replace('image/png', downloadMime); | |
p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png'); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* val4 is an array of 3 numbers that range from [0,100] | |
* size is the number of pixels for width and height | |
* use p5.js to draw a round grawscale glpyh within the bounding box | |
*/ | |
function gray_glyph(values, size) { | |
// replace this with your own version | |
// map brightness to large circle shade | |
var color1 = map(values[2], 0, 100, 10, 70) //brightness | |
stroke(color1); | |
fill(color1) | |
var s2 = size/2; | |
polygon(s2, s2, s2,8); //gives indicator for brightness | |
// inner size is set to 30% | |
var inner_size = 0.2 + 0.4 * 0.3; | |
var s3 = size * inner_size; | |
// inner color based on saturation | |
var color2 = map(values[1], 0, 100, color1+20, 240) //saturation | |
fill(color2); | |
stroke(color2); | |
// hue controls left/right shift | |
var shift_frac = (values[0] - 180.0) / 180.0; | |
var s4 = map(size, 0,100,10,60); | |
var max_shift = 0.5 * (size - s4); | |
var x_shift = shift_frac * max_shift; | |
polygon(s2 + x_shift, s2, s2/2, 8); //inner indicators for hue and saturation, | |
polygon(s2 - x_shift, s2, s2/2, 8); //futher aparts means dark hue, dark to light means saturation | |
var color3 = map(values[2], 0, 100, 0,300); //remap of colour for brightness | |
fill(color3); //new colour fill | |
polygon(s2, s2, s2/2, 8); //hue display on top of the brightness polygon | |
} | |
function polygon(x, y, radius, npoints) { | |
var angle = TWO_PI / npoints; | |
beginShape(); | |
for (var a = 0; a < TWO_PI; a += angle) { | |
var sx = x + cos(a) * radius; | |
var sy = y + sin(a) * radius; | |
vertex(sx, sy); | |
} | |
endShape(CLOSE); | |
} | |
//backup | |
// function gray_glyph(values, size) { | |
// // replace this with your own version | |
// // map brightness to large circle shade | |
// var color1 = map(values[2], 0, 100, 10, 70) | |
// stroke(color1); | |
// fill(color1) | |
// var s2 = size/2; | |
// ellipse(s2, s2, size); | |
// // inner size is set to 30% | |
// var inner_size = 0.2 + 0.4 * 0.3; | |
// var s3 = size * inner_size; | |
// // inner color based on saturation | |
// var color2 = map(values[1], 0, 100, color1+20, 240) | |
// fill(color2); | |
// stroke(color2); | |
// // hue controls left/right shift | |
// var shift_frac = (values[0] - 180.0) / 180.0; | |
// var max_shift = 0.5 * (size - s3); | |
// var x_shift = shift_frac * max_shift; | |
// ellipse(s2 + x_shift, s2, s3); | |
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function GrayGlyph() { | |
/* | |
* values is an array of 3 numbers: [hue, saturation, brightness] | |
* + hue ranges from 0..360 | |
* + saturation ranges from 0..100 | |
* + brightness ranges from 0..100 | |
* this matches the default range for p5.js colorMode(HSB) as describe at: | |
* https://p5js.org/reference/#/p5/colorMode | |
* | |
* size is the number of pixels for width and height | |
* | |
* use p5.js to draw a round grayscale glpyh | |
* the glyph should stay within the bounding box [0, 0, width, height] | |
* this is a grayscale glyph, so only brighness can be adjusted. | |
* the range for brighness is 0..100 | |
* | |
* the color mode will be HSB, so you can either: | |
* + use a one argument grayscale call; this is easiest. examples: | |
* - fill(50); // ranges from 0-100 | |
* - stroke(100); // white | |
* + use a three arguement HSB call with values but set both H and S to 0. examples: | |
* - fill(0, 0, 51); // equivalent to above | |
* - stroke(0, 0, 100); // | |
*/ | |
this.draw = function(values, size) { | |
// map brightness to large circle shade | |
var color1 = map(values[2], 0, 100, 10, 70) //brightness | |
stroke(color1); | |
fill(color1) | |
var s2 = size/2; | |
polygon(s2, s2, s2,8); //gives indicator for brightness | |
// inner size is set to 30% | |
var inner_size = 0.2 + 0.4 * 0.3; | |
var s3 = size * inner_size; | |
// inner color based on saturation | |
var color2 = map(values[1], 0, 100, color1/2, 100) //saturation | |
fill(color2); //saturation | |
stroke(color2); | |
// hue controls left/right shift | |
var shift_frac = (values[0] - 180.0) / 180.0; | |
var s4 = map(size, 0,100,10,60); | |
var max_shift = 0.5 * (size - s4); | |
var x_shift = shift_frac * max_shift; | |
polygon(s2 + x_shift, s2, s2/2, 8); //inner indicators for hue and saturation, | |
polygon(s2 - x_shift, s2, s2/2, 8); //futher aparts means dark hue, dark to light means saturation | |
var color3 = map(values[2], 0, 100, 0,300); //remap of colour for brightness | |
fill(color3); //new colour fill | |
polygon(s2, s2, s2/2, 8); //hue display on top of the brightness polygon | |
} | |
function polygon(x, y, radius, npoints) { | |
var angle = TWO_PI / npoints; | |
beginShape(); | |
for (var a = 0; a < TWO_PI; a += angle) { | |
var sx = x + cos(a) * radius; | |
var sy = y + sin(a) * radius; | |
vertex(sx, sy); | |
} | |
endShape(CLOSE); | |
} | |
// // replace this with your own version | |
// // map brightness to large circle shade | |
// var color1 = map(values[2], 0, 100, 10, 70) | |
// stroke(color1); | |
// fill(color1) | |
// var s2 = size/2; | |
// ellipse(s2, s2, size); | |
// // inner size is set to 30% | |
// var inner_size = 0.2 + 0.4 * 0.3; | |
// var s3 = size * inner_size; | |
// // inner color based on saturation | |
// var color2 = map(values[1], 0, 100, color1+20, 240) | |
// fill(color2); | |
// stroke(color2); | |
// // hue controls left/right shift | |
// var shift_frac = (values[0] - 180.0) / 180.0; | |
// var max_shift = 0.5 * (size - s3); | |
// var x_shift = shift_frac * max_shift; | |
// ellipse(s2 + x_shift, s2, s3); | |
//} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<head> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/p5.js"></script> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/addons/p5.dom.js"></script> | |
<script language="javascript" type="text/javascript" src=".purview_helper.js"></script> | |
<script language="javascript" type="text/javascript" src="grayglyph.js"></script> | |
<script language="javascript" type="text/javascript" src="spotglyph.js"></script> | |
<script language="javascript" type="text/javascript" src="sketch.js"></script> | |
<style> | |
body { padding: 0; margin: 0; } | |
.inner { position: absolute; } | |
#controls { | |
font: 300 12px "Helvetica Neue"; | |
padding: 5; | |
margin: 5; | |
background: #f0f0f0; | |
opacity: 0.0; | |
-webkit-transition: opacity 0.2s ease; | |
-moz-transition: opacity 0.2s ease; | |
-o-transition: opacity 0.2s ease; | |
-ms-transition: opacity 0.2s ease; | |
} | |
#controls:hover { opacity: 0.9; } | |
</style> | |
</head> | |
<body style="background-color:white"> | |
<div class="outer"> | |
<div class="inner"> | |
<div id="canvasContainer"></div> | |
</div> | |
<div class="inner" id="controls" height="500px"> | |
<table> | |
<tr> | |
<td>hue</td> | |
<td id="slider1Container"></td> | |
</tr> | |
<tr> | |
<td>saturation</td> | |
<td id="slider2Container"></td> | |
</tr> | |
<tr> | |
<td>brightness</td> | |
<td id="slider3Container"></td> | |
</tr> | |
<tr> | |
<td> | |
<hr> | |
</td> | |
</tr> | |
<tr> | |
<td>Mode</td> | |
<td id="selector1Container"></td> | |
</tr> | |
<tr> | |
<td>Glyph</td> | |
<td id="selector2Container"></td> | |
</tr> | |
<tr> | |
<td>Size</td> | |
<td id="selector3Container"></td> | |
</tr> | |
<tr> | |
<td>Show Guide</td> | |
<td id="checkContainer"></td> | |
</tr> | |
<tr> | |
<td></td> | |
<td id="buttonContainer"></td> | |
</tr> | |
</div> | |
</div> | |
</table> | |
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"commits": [ | |
{ | |
"sha": "cf452505d35312e5f9ddfe8fbad8287a316fb99c", | |
"name": "Glyph final" | |
}, | |
{ | |
"sha": "61964ddde7b687fe51a5a986a70f62132f16a674", | |
"name": "Color Glyph - SPOT_COLOR" | |
}, | |
{ | |
"sha": "614f76e12e79e6812920c07e9076164f29af5b95", | |
"name": "Gif_Glyphs - OBJECTS" | |
}, | |
{ | |
"sha": "884d5fa6058b11a37186c9d74cf46faf733746e0", | |
"name": "Glyph_System" | |
}, | |
{ | |
"sha": "f5d83a75fc96ac9198c6cf588efe22b51258dd5a", | |
"name": "Interpolation" | |
}, | |
{ | |
"sha": "aeedcc49ed754daeb69b7855aa03ca08397a6ca5", | |
"name": "Colors_and_Glyphs - SKETCH" | |
} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<head> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/p5.js"></script> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/addons/p5.dom.js"></script> | |
<script language="javascript" type="text/javascript" src=".purview_helper.js"></script> | |
<script language="javascript" type="text/javascript" src="sketch2.js"></script> | |
</head> | |
<body style="background-color:white"> | |
<div class="outer"> | |
<div class="inner"> | |
<div id="canvasContainer"></div> | |
</div> | |
</div> | |
</table> | |
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var canvasWidth = 960; | |
var canvasHeight = 500; | |
var glyphSelector; | |
var modeSelector; | |
var sizeSelector; | |
var show_oddball = false; | |
var oddball_row = 0; | |
var oddball_col = 0; | |
var val_sliders = []; | |
var max_vals = [360, 100, 100]; | |
var curEmoji = 76; | |
var NUM_EMOJI = 872; | |
var EMOJI_WIDTH = 38; | |
var lastKeyPressedTime; | |
var secondsUntilSwapMode = 10; | |
var secondsPerEmoji = 5; | |
var isSwappingEmoji = false; | |
var emojiSwapLerp = 0; | |
var prevEmoji = 0; | |
var lastEmojiSwappedTime; | |
var emojiImg; | |
var curEmojiImg; | |
var curEmojiPixels; | |
var curEmojiColors, nextEmojiColors, prevEmojiColors; | |
function preload() { | |
emojiImg = loadImage("twemoji36b_montage.png"); | |
} | |
function setup() { | |
// create the drawing canvas, save the canvas element | |
var main_canvas = createCanvas(canvasWidth, canvasHeight); | |
main_canvas.parent('canvasContainer'); | |
var now = millis(); | |
lastKeyPressedTime = now; | |
lastEmojiSwappedTime = now; | |
// create two sliders | |
for (i=0; i<3; i++) { | |
var slider = createSlider(0, 10*max_vals[i], 10*max_vals[i]/2); | |
slider.parent("slider" + (i+1) + "Container") | |
slider.changed(sliderUpdated); | |
slider.mouseMoved(sliderUpdated); | |
slider.touchMoved(sliderUpdated); | |
val_sliders.push(slider); | |
} | |
modeSelector = createSelect(); | |
modeSelector.option('drive'); | |
modeSelector.option('gradient'); | |
modeSelector.option('random_grid'); | |
modeSelector.option('oddball'); | |
modeSelector.option('image'); | |
modeSelector.changed(modeChangedEvent); | |
modeSelector.value('image'); | |
modeSelector.parent('selector1Container'); | |
glyphSelector = createSelect(); | |
glyphSelector.option('show_color'); | |
glyphSelector.option('gray'); | |
glyphSelector.option('spot'); | |
glyphSelector.changed(modeChangedEvent); | |
glyphSelector.value('spot'); | |
glyphSelector.parent('selector2Container'); | |
sizeSelector = createSelect(); | |
sizeSelector.option('32'); | |
sizeSelector.option('64'); | |
sizeSelector.option('128'); | |
sizeSelector.option('256'); | |
sizeSelector.parent('selector3Container'); | |
sizeSelector.value('32'); | |
sizeSelector.changed(sizeChangedEvent); | |
guideCheckbox = createCheckbox('', false); | |
guideCheckbox.parent('checkContainer'); | |
guideCheckbox.changed(guideChangedEvent); | |
button = createButton('redo'); | |
button.mousePressed(buttonPressedEvent); | |
button.parent('buttonContainer'); | |
curEmojiImg = createImage(36, 36); | |
// create an array for HSB values: [18][18][3] | |
curEmojiPixels = Array(18); | |
curEmojiColors = Array(18); | |
for(var i=0; i<18; i++) { | |
curEmojiPixels[i] = Array(18); | |
curEmojiColors[i] = Array(18); | |
for(var j=0; j<18; j++) { | |
curEmojiPixels[i][j] = Array(3); | |
} | |
} | |
gray_glyph = new GrayGlyph(); | |
spot_glyph = new SpotGlyph(); | |
colorMode(HSB); | |
refreshGridData(); | |
modeChangedEvent(); | |
} | |
function sliderUpdated() { | |
redraw(); | |
} | |
function mouseClicked() { | |
if (mouseX > width/4) { | |
refreshGridData(); | |
} | |
redraw(); | |
} | |
function dataInterpolate(data1, data2, val) { | |
var d = new Array(8); | |
for(var i=0; i<8; i++) { | |
d[i] = lerp(data1[i], data2[i], val); | |
} | |
return d; | |
} | |
var numGridRows; | |
var numGridCols; | |
var gridValues; // row, col order | |
var gridOffsetX, gridOffsetY; | |
var gridSpacingX, gridSpacingY; | |
// Generate data for putting glyphs in a grid | |
function clamp(num, min, max) { | |
return Math.min(Math.max(num, min), max); | |
} | |
function refreshGridData() { | |
var mode = modeSelector.value(); | |
var glyphSize = parseInt(sizeSelector.value(), 10); | |
if (mode == "image") { | |
if(glyphSize == 32) { | |
numGridCols = 18; | |
numGridRows = 17; | |
gridOffsetX = 320; | |
gridSpacingX = 31; | |
gridOffsetY = 2; | |
gridSpacingY = 29; | |
} | |
else if(glyphSize == 64) { | |
numGridCols = 10; | |
numGridRows = 9; | |
gridOffsetX = 280; | |
gridSpacingX = 66; | |
gridOffsetY = -18; | |
gridSpacingY = 59; | |
} | |
else if(glyphSize == 128) { | |
numGridCols = 6; | |
numGridRows = 5; | |
gridOffsetX = 164; | |
gridSpacingX = 132; | |
gridOffsetY = -50; | |
gridSpacingY = 118; | |
} | |
else if(glyphSize == 256) { | |
numGridCols = 3; | |
numGridRows = 3; | |
gridOffsetX = 172; | |
gridSpacingX = 262; | |
gridOffsetY = -100; | |
gridSpacingY = 234; | |
} | |
} | |
else if(glyphSize == 128) { | |
numGridCols = 7; | |
numGridRows = 3; | |
gridOffsetX = 10; | |
gridSpacingX = 136; | |
gridOffsetY = 20; | |
gridSpacingY = 166; | |
} | |
else if(glyphSize == 256) { | |
numGridCols = 3; | |
numGridRows = 1; | |
gridOffsetX = 20; | |
gridSpacingX = 320; | |
gridOffsetY = 100; | |
gridSpacingY = 500; | |
} | |
else if(glyphSize == 64) { | |
numGridCols = 14; | |
numGridRows = 7; | |
gridOffsetX = 3; | |
gridSpacingX = 68; | |
gridOffsetY = 6; | |
gridSpacingY = 71; | |
} | |
else if(glyphSize == 32) { | |
numGridCols = 24; | |
numGridRows = 13; | |
gridOffsetX = 4; | |
gridSpacingX = 40; | |
gridOffsetY = 4; | |
gridSpacingY = 38; | |
} | |
gridValues = new Array(numGridRows); | |
for (var i=0; i<numGridRows; i++) { | |
gridValues[i] = new Array(numGridCols); | |
for (var j=0; j<numGridCols; j++) { | |
gridValues[i][j] = new Array(8); | |
} | |
} | |
if (mode == "gradient" || mode == 'oddball') { | |
var top_left = Array(3); | |
var top_right = Array(3); | |
var bottom_left = Array(3); | |
var bottom_right = Array(3); | |
for (var k=0; k<3; k++) { | |
top_left[k] = random(max_vals[k]); | |
top_right[k] = random(max_vals[k]); | |
bottom_left[k] = random(max_vals[k]); | |
bottom_right[k] = random(max_vals[k]); | |
} | |
for (var i=0; i<numGridRows; i++) { | |
if(numGridRows == 1) { | |
var frac_down = 0; | |
} | |
else { | |
var frac_down = i / (numGridRows - 1.0); | |
} | |
d_left = dataInterpolate(top_left, bottom_left, frac_down); | |
d_right = dataInterpolate(top_right, bottom_right, frac_down); | |
for (var j=0; j<numGridCols; j++) { | |
if(numGridCols == 0) { | |
var frac_over = 0; | |
} | |
else { | |
var frac_over = j / (numGridCols - 1.0); | |
} | |
gridValues[i][j] = dataInterpolate(d_left, d_right, frac_over); | |
} | |
} | |
if (mode == 'oddball') { | |
// replace an entry at random | |
oddball_row = Math.floor(random(numGridRows)) | |
oddball_col = Math.floor(random(numGridCols)) | |
for (var k=0; k<3; k++) { | |
gridValues[oddball_row][oddball_col][k] = random(max_vals[k]); | |
} | |
} | |
} | |
else if(mode == "image") { | |
for (var i=0; i<numGridRows; i++) { | |
for (var j=0; j<numGridCols; j++) { | |
for (var k=0; k<3; k++) { | |
gridValues[i][j][k] = curEmojiPixels[i][j][k]; | |
} | |
} | |
} | |
} | |
else { | |
for (var i=0; i<numGridRows; i++) { | |
for (var j=0; j<numGridCols; j++) { | |
for (var k=0; k<3; k++) { | |
gridValues[i][j][k] = random(max_vals[k]); | |
} | |
} | |
} | |
} | |
} | |
function sizeChangedEvent() { | |
var mode = modeSelector.value(); | |
if (mode != "drive") { | |
refreshGridData(); | |
} | |
redraw(); | |
} | |
function guideChangedEvent() { | |
show_oddball = guideCheckbox.checked(); | |
redraw(); | |
} | |
function modeChangedEvent() { | |
var mode = modeSelector.value(); | |
// enable/disable sliders | |
if (mode === "drive") { | |
// disable the button | |
// button.attribute('disabled',''); | |
// enable the size selector | |
sizeSelector.removeAttribute('disabled'); | |
// enable the first four sliders | |
for(var i=0; i<3; i++) { | |
val_sliders[i].removeAttribute('disabled'); | |
} | |
} | |
else { | |
// enable the button | |
// button.removeAttribute('disabled'); | |
// disable the sliders | |
for(var i=0; i<3; i++) { | |
val_sliders[i].attribute('disabled',''); | |
} | |
// enable the size selector | |
// sizeSelector.removeAttribute('disabled'); | |
// refresh data | |
refreshGridData(); | |
} | |
if (mode === "image") { | |
// get current emoji image | |
var offsetX = 36 * (curEmoji % 38); | |
var offsetY = 36 * Math.floor(curEmoji / 38); | |
var squareOffsets = [ [0,0], [0,1], [1,1], [1, 0] ]; | |
curEmojiImg.copy(emojiImg, offsetX, offsetY, 36, 36, 0, 0, 36, 36); | |
curEmojiImg.loadPixels(); | |
colorMode(RGB); | |
for(var i=0; i<17; i++) { | |
// i is y | |
var maxX = 18; | |
var offsetX = 0; | |
if (i%2 == 1) { | |
maxX = 17; | |
offsetX = 1; | |
} | |
for(var j=0; j<maxX; j++) { | |
// j is x | |
var sumColor = [0, 0, 0]; | |
for(var k=0; k<4; k++) { | |
// k is summing over 4 adacent pixels | |
var curColor = curEmojiImg.get(j*2 + squareOffsets[k][0] + offsetX, 1 + i*2 + squareOffsets[k][1]); | |
for(var l=0; l<3; l++) { | |
sumColor[l] += curColor[l] / 4.0; | |
} | |
} | |
var curColor = color(sumColor); | |
curEmojiColors[i][j] = curColor; | |
curEmojiPixels[i][j][0] = curColor._getHue(); | |
curEmojiPixels[i][j][1] = curColor._getSaturation(); | |
curEmojiPixels[i][j][2] = curColor._getBrightness(); | |
} | |
} | |
colorMode(HSB); | |
// refresh data | |
refreshGridData(); | |
} | |
redraw(); | |
} | |
function buttonPressedEvent() { | |
refreshGridData(); | |
redraw(); | |
} | |
var colorBack = "rgb(50, 50, 50)" | |
var colorFront = "rgb(192, 192, 255)" | |
function ColorGlyph() { | |
this.draw = function(values, size) { | |
fill(values[0], values[1], values[2]); | |
stroke(0); | |
var s2 = size/2; | |
ellipse(s2, s2, size); | |
} | |
} | |
var color_glyph = new ColorGlyph(); | |
function highlightGlyph(glyphSize) { | |
halfSize = glyphSize / 2.0; | |
stroke(0, 0, 255, 128); | |
noFill(); | |
strokeWeight(4); | |
ellipse(halfSize, halfSize, glyphSize+4); | |
fill(0); | |
strokeWeight(1); | |
} | |
function getGyphObject() { | |
var glyphMode = glyphSelector.value(); | |
var glyph_obj = color_glyph; | |
if(glyphMode == "gray") | |
glyph_obj = gray_glyph; | |
else if(glyphMode == "spot") | |
glyph_obj = spot_glyph; | |
return(glyph_obj); | |
} | |
function drawDriveMode() { | |
var glyph_obj = getGyphObject(); | |
var glyphSize = parseInt(sizeSelector.value(), 10); | |
var halfSize = glyphSize / 2; | |
background(colorBack); | |
var halfSize = glyphSize / 2; | |
var middle_x = canvasWidth / 2; | |
var middle_y = canvasHeight / 2; | |
var val = [0,0,0]; | |
for(i=0; i<3; i++) { | |
val[i] = val_sliders[i].value() / 10.0; | |
} | |
resetMatrix(); | |
translate(middle_x - halfSize, middle_y - halfSize); | |
glyph_obj.draw(val, glyphSize); | |
if (show_oddball) { | |
resetMatrix(); | |
translate(middle_x - halfSize, middle_y - halfSize); | |
highlightGlyph(glyphSize) | |
} | |
resetMatrix(); | |
translate(middle_x + halfSize + 32, middle_y - halfSize); | |
color_glyph.draw(val, glyphSize); | |
} | |
function drawGridMode() { | |
var mode = modeSelector.value(); | |
var glyph_obj = getGyphObject(); | |
var glyphSize = parseInt(sizeSelector.value(), 10); | |
background(colorBack); | |
if (show_oddball && mode == 'oddball') { | |
resetMatrix(); | |
translate(gridOffsetX + oddball_col * gridSpacingX, gridOffsetY + oddball_row * gridSpacingY); | |
highlightGlyph(glyphSize) | |
} | |
var hexOffset = (mode == "image"); | |
for (var i=0; i<numGridRows; i++) { | |
var tweakedNumGridCols = numGridCols; | |
var offsetX = 0; | |
if (hexOffset && i%2 == 1) { | |
offsetX = gridSpacingX / 2; | |
tweakedNumGridCols = numGridCols - 1; | |
} | |
for (var j=0; j<tweakedNumGridCols; j++) { | |
resetMatrix(); | |
translate(gridOffsetX + j * gridSpacingX + offsetX, gridOffsetY + i * gridSpacingY); | |
glyph_obj.draw(gridValues[i][j], glyphSize); | |
resetMatrix(); | |
} | |
} | |
} | |
function colorCopyArray(c) { | |
d = Array(18); | |
for(var i=0; i<18; i++) { | |
d[i] = Array(18); | |
for(var j=0; j<18; j++) { | |
d[i][j] = c[i][j]; | |
} | |
} | |
return d; | |
} | |
function checkImageUpdate() { | |
var mode = modeSelector.value(); | |
isSwappingEmoji = false; | |
if (mode == "image") { | |
now = millis(); | |
if(lastKeyPressedTime + 1000 * secondsUntilSwapMode < now) { | |
// key not pressed recently | |
if(lastEmojiSwappedTime + 1000 * secondsPerEmoji < now) { | |
prevEmoji = curEmoji; | |
prevEmojiColors = colorCopyArray(curEmojiColors); | |
// no swaps recently | |
updateEmoji(1); | |
nextEmojiColors = colorCopyArray(curEmojiColors); | |
lastEmojiSwappedTime = now; | |
} | |
if(now - lastEmojiSwappedTime < 1000) { | |
isSwappingEmoji = true; | |
emojiSwapLerp = (now - lastEmojiSwappedTime) / 1000.0; | |
// print("LERP: " + emojiSwapLerp); | |
for (var i=0; i<numGridRows; i++) { | |
for (var j=0; j<numGridCols; j++) { | |
// var curColor = lerpColor(prevEmojiColors[i][j], nextEmojiColors[i][j], emojiSwapLerp); | |
var curColor = prevEmojiColors[i][j]; | |
if (curColor) { | |
curColor = lerpColor(prevEmojiColors[i][j], nextEmojiColors[i][j], emojiSwapLerp); | |
curEmojiPixels[i][j][0] = curColor._getHue(); | |
curEmojiPixels[i][j][1] = curColor._getSaturation(); | |
curEmojiPixels[i][j][2] = curColor._getBrightness(); | |
} | |
} | |
} | |
refreshGridData(); | |
} | |
else { | |
for (var i=0; i<numGridRows; i++) { | |
for (var j=0; j<numGridCols; j++) { | |
var curColor = nextEmojiColors[i][j]; | |
if (curColor) { | |
curEmojiPixels[i][j][0] = curColor._getHue(); | |
curEmojiPixels[i][j][1] = curColor._getSaturation(); | |
curEmojiPixels[i][j][2] = curColor._getBrightness(); | |
} | |
} | |
} | |
refreshGridData(); | |
} | |
} | |
} | |
} | |
var is_drawing = false; | |
function draw () { | |
if (is_drawing) { | |
return; | |
} | |
is_drawing = true; | |
colorMode(HSB); | |
var mode = modeSelector.value(); | |
checkImageUpdate(); | |
if (mode == "drive") { | |
drawDriveMode(); | |
} | |
else { | |
drawGridMode(); | |
} | |
resetMatrix(); | |
if (mode == "image") { | |
image(curEmojiImg, 32, height-32-36); | |
} | |
is_drawing = false; | |
} | |
function keyTyped() { | |
if (key == '!') { | |
saveBlocksImages(); | |
} | |
else if (key == '@') { | |
saveBlocksImages(true); | |
} | |
else if (key == ' ') { | |
refreshGridData(); | |
redraw(); | |
} | |
else if (key == 'f') { | |
var curGlyph = glyphSelector.value() | |
if(curGlyph == "show_color") { | |
glyphSelector.value('gray'); | |
} | |
else if(curGlyph == "gray") { | |
glyphSelector.value('spot'); | |
} | |
else if(curGlyph == "spot") { | |
glyphSelector.value('show_color'); | |
} | |
redraw(); | |
} | |
else if (key == 's') { | |
var old_value = guideCheckbox.checked(); | |
guideCheckbox.checked(!old_value); | |
guideChangedEvent(); | |
} | |
else if (key == '1') { | |
sizeSelector.value('32'); | |
sizeChangedEvent() | |
} | |
else if (key == '2') { | |
sizeSelector.value('64'); | |
sizeChangedEvent() | |
} | |
else if (key == '3') { | |
sizeSelector.value('128'); | |
sizeChangedEvent() | |
} | |
else if (key == '4') { | |
sizeSelector.value('256'); | |
sizeChangedEvent() | |
} | |
else if (key == 'd') { | |
modeSelector.value('drive'); | |
modeChangedEvent() | |
} | |
else if (key == 'g') { | |
modeSelector.value('gradient'); | |
modeChangedEvent() | |
} | |
else if (key == 'r') { | |
modeSelector.value('random'); | |
modeChangedEvent() | |
} | |
else if (key == 'o') { | |
modeSelector.value('oddball'); | |
modeChangedEvent() | |
} | |
else if (key == 'i') { | |
modeSelector.value('image'); | |
modeChangedEvent() | |
} | |
} | |
function updateEmoji(offset) { | |
curEmoji = (curEmoji + NUM_EMOJI + offset) % NUM_EMOJI; | |
modeChangedEvent() | |
} | |
function keyPressed() { | |
lastKeyPressedTime = millis(); | |
if (keyCode == LEFT_ARROW) { | |
updateEmoji(-1); | |
} | |
else if (keyCode == RIGHT_ARROW) { | |
updateEmoji(1); | |
} | |
else if (keyCode == UP_ARROW) { | |
updateEmoji(-38); | |
} | |
else if (keyCode == DOWN_ARROW) { | |
updateEmoji(38); | |
} | |
} | |
function mouseMoved() { | |
lastKeyPressedTime = millis(); | |
} | |
function mouseDragged() { | |
lastKeyPressedTime = millis(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var canvasWidth = 960; | |
var canvasHeight = 500; | |
function setup () { | |
// create the drawing canvas, save the canvas element | |
var main_canvas = createCanvas(canvasWidth, canvasHeight); | |
main_canvas.parent('canvasContainer'); | |
colorMode(HSL, 100); // Use HSB with scale of 0-100 | |
// this means draw will only be called once | |
noLoop(); | |
} | |
function draw_shape(column, row, size, cur_color) { | |
// replace this with your own logic | |
var half_size = size/2; | |
var spacer = 15; | |
// defaults | |
fill(60); | |
strokeWeight(2); | |
var rect_width = 60; | |
if (row === 0) { | |
// hue | |
var stroke_w = map(column, 0, 4, 1, 3); | |
strokeWeight(stroke_w); | |
triangle(90 , 75, 58, 20, 86, 75); | |
strokeWeight(0.5) | |
triangle(35 , 75, 58, 20, 30, 75); | |
strokeWeight(0.5); | |
rect((rect_width/2), 75, half_size+2,half_size/3); | |
} | |
else if (row === 1) { | |
// saturation | |
var rect_width = map(column, 0, 4, 10, 80); | |
strokeWeight(0.5); | |
triangle(90 , 75, 58, 20, 86, 75); | |
strokeWeight(stroke_w); | |
triangle(35 , 75, 58, 20, 30, 75); | |
strokeWeight(0.5); | |
rect((rect_width/2), 75, half_size+2,half_size/3); | |
} | |
else { | |
// lightness | |
var fill_col = map(column, 0, 4, 30, 90); | |
fill(fill_col); | |
strokeWeight(0.5); | |
triangle(90 , 75, 58, 20, 86, 75); | |
strokeWeight(0.5); | |
triangle(35 , 75, 58, 20, 30, 75); | |
strokeWeight(stroke_w); | |
rect((rect_width/2), 75, half_size+2,half_size/3); | |
} | |
} | |
// some examples of how to specify a base color | |
// var my_color = "#d24632" | |
var my_color = "rgb(164, 13, 255)" | |
// var my_color = "rgb(20%, 47%, 67%)" | |
var shapes_should_draw = true; | |
// draw five colors and then five glyphs | |
function draw () { | |
var size=120; | |
var xsteps = 5; | |
var xdiff = (width - xsteps * size) / xsteps; | |
var xstep = size + xdiff; | |
var ysteps = 3; | |
var ydiff = (height - ysteps * size) / ysteps; | |
var ystep = size + ydiff; | |
var bg_color = color("#ffffdc"); | |
var base_color = color(my_color); | |
var base_hue = hue(base_color); | |
var base_sat = saturation(base_color); | |
var base_lgt = lightness(base_color); | |
background(bg_color); | |
noStroke(); | |
for (var x=0; x<xsteps; x++) { | |
for (var y=0; y<ysteps; y++) { | |
var cur_color = base_color; | |
if (y == 0) { | |
// hue | |
var cur_hue = (85 + base_hue + 100 * 0.3 * x / xsteps) % 100; | |
cur_color = color(cur_hue, base_sat, base_lgt); | |
} | |
else if (y == 1) { | |
// saturation | |
var cur_sat = (5 + 90 * x / xsteps); | |
cur_color = color(base_hue, cur_sat, base_lgt); | |
} | |
else if (y == 2) { | |
// lightness | |
var cur_lgt = (5 + 90 * x / xsteps); | |
cur_color = color(base_hue, base_sat, cur_lgt); | |
} | |
fill(cur_color); | |
noStroke(); | |
rect(xdiff/2 + xstep * x - 10, ydiff/2 + ystep * y - 10, size, size); | |
strokeWeight(2); | |
stroke(0); | |
fill(bg_color); | |
var curx = xdiff/2 + xstep * x + 10; | |
var cury = ydiff/2 + ystep * y + 10; | |
rect(curx, cury, size, size); | |
if (shapes_should_draw) { | |
push(); | |
translate(curx, cury); | |
draw_shape(x, y, size, cur_color); | |
//rect(x,y,size/4,cur_color); | |
pop(); | |
} | |
} | |
} | |
} | |
function keyTyped() { | |
if (key == '!') { | |
saveBlocksImages(); | |
} | |
else if (key == '@') { | |
saveBlocksImages(true); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function SpotGlyph() { | |
this.spot_hue = 281; //pick a hue colour: purple | |
var SH; | |
//colorMode(HSB, this.spot_hue); | |
/* | |
* values is an array of 3 numbers: [hue, saturation, brightness] | |
* + hue ranges from 0..360 | |
* + saturation ranges from 0..100 | |
* + brightness ranges from 0..100 | |
* this matches the default range for p5.js colorMode(HSB) as describe at: | |
* https://p5js.org/reference/#/p5/colorMode | |
* | |
* size is the number of pixels for width and height | |
* | |
* use p5.js to draw a round grayscale glpyh | |
* the glyph should stay within the bounding box [0, 0, width, height] | |
* | |
* this glyph can utilize changes in brightness and saturation, but only | |
* using the spot_hue set above. So: | |
* | |
* + hue will always be set to spot_hue (a value from 0-360) | |
* + saturation can vary from 0-100 | |
* + brighness can vary from 0-100 | |
* | |
* examples: | |
* - fill(this.spot_hue, 25, 50); // desaturated. middle brightness. | |
* - stroke(this.spot_hue, 100, 100); // fully saturated and maximum brightness | |
*/ | |
this.draw = function(values, size) { | |
// map brightness to large circle shade | |
var color1 = map(values[2], 0, 100, 0, 100); //brightnes | |
var stroke1; | |
//looks at the values of the hue and then sets the stroke color | |
//if under halfway, stroke is blk, else if its bigger stroke is wht | |
if(values[0] <= 180){ | |
stroke1 = 0; | |
} | |
else if(values[0] >= 180){ | |
stroke1 = 255; | |
} | |
//brightness color octogon | |
stroke(stroke1); | |
fill(color1); | |
var s2 = size/2; | |
polygon(s2, s2, s2,8); //gives indicator for brightness | |
stroke(color1); | |
var inner_size = 0.2 + 0.4 * 0.3; // inner size is set to 30% | |
var s3 = size * inner_size; | |
//saturation color octogons | |
var color2 = map(values[1], 0, 100, color1/2, 100) //saturation | |
fill(color2); //saturation | |
stroke(color2/2); | |
var shift_frac = (values[0] - 180.0) / 180.0; | |
var s4 = map(size, 0,100,10,60); | |
var max_shift = 0.5 * (size - s4); | |
var x_shift = shift_frac * max_shift; | |
polygon(s2 + x_shift, s2, s2/2, 8); //inner indicators for hue and saturation, | |
polygon(s2 - x_shift, s2, s2/2, 8); //futher aparts means dark hue, dark to light means saturation | |
//hue color octogons | |
var color3 = map(values[2], 0, 100, 0,300); //remap of colour for brightness | |
fill(this.spot_hue, color1/2, color1); //hue | |
polygon(s2, s2 + x_shift, s2/2, 8); //inner indicators for hue and saturation, | |
polygon(s2, s2 - x_shift, s2/2, 8); //futher aparts means dark hue, dark to light means saturation | |
fill(this.spot_hue, color1, color1); | |
//fill(color3); //hue fill | |
polygon(s2, s2, s2/3, 8); //hue display on top of the brightness polygon | |
} | |
function polygon(x, y, radius, npoints) { | |
var angle = TWO_PI / npoints; | |
beginShape(); | |
for (var a = 0; a < TWO_PI; a += angle) { | |
var sx = x + cos(a) * radius; | |
var sy = y + sin(a) * radius; | |
vertex(sx, sy); | |
} | |
endShape(CLOSE); | |
} | |
} | |
//backup | |
// this.draw = function(values, size) { | |
// var hue = values[0]; | |
// var sat = values[1]; | |
// var brt = values[2]; | |
// var halfSize = size/2; | |
// var sqSize = size * Math.sqrt(2) / 2; | |
// noStroke(); | |
// if(hue > this.spot_hue && hue < this.spot_hue + 90) { | |
// fill(this.spot_hue, sat, brt); | |
// } | |
// else { | |
// fill(this.spot_hue, 0, brt); | |
// } | |
// translate(halfSize, halfSize); | |
// rect(-sqSize/2, -sqSize/2, sqSize, sqSize); | |
// } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment