@@ -0,0 +1,293 @@ | |||
class ASDFPIXELSORT extends Shader { | |||
ASDFPIXELSORT() { | |||
name = "fxASDFPixelSort"; | |||
params.add(new Param("black", 0, 200, new int[]{SIN, LINE, RAMPUPDOWN, TAN, COS})); | |||
params.add(new Param("white", -20000000, -6000000, new int[]{SIN, LINE, RAMPUPDOWN, TAN, COS})); | |||
params.add(new Param("brightness", -15000000, 2000000, new int[]{SIN, LINE, RAMPUPDOWN, TAN, COS})); | |||
params.add(new Param("mode", 3, new int[]{RANDOM})); | |||
} | |||
/* | |||
float playSpeed = 4; | |||
float inc1, inc2, inc3; | |||
void animate() { | |||
inc1+=playSpeed/400; | |||
inc2+=playSpeed/300; | |||
inc3+=playSpeed/350; | |||
if ((frameCount % int(map(playSpeed, 0, 4, 15, 120))) == 0) { | |||
for (int i = 0; i < params.size(); i++) | |||
params.get(i).randomize(); | |||
} | |||
params.get(0).setValue((sin(inc1)+1)/2); | |||
params.get(2).setValue((sin(inc2)+1)/2); | |||
params.get(1).setValue((sin(inc3)+1)/2); | |||
} | |||
*/ | |||
void apply() { | |||
row = 0; | |||
column = 0; | |||
renderer.beginDraw(); | |||
renderer.colorMode(RGB); | |||
colorMode(RGB); | |||
while (column < renderer.width-1) { | |||
renderer.loadPixels(); | |||
sortColumn(); | |||
column++; | |||
renderer.updatePixels(); | |||
} | |||
while (row < renderer.height-1) { | |||
renderer.loadPixels(); | |||
sortRow(); | |||
row++; | |||
renderer.updatePixels(); | |||
} | |||
renderer.endDraw(); | |||
} | |||
int row = 0; | |||
int column = 0; | |||
void sortRow() { | |||
int x = 0; | |||
int y = row; | |||
int xend = 0; | |||
while (xend < renderer.width-1) { | |||
switch((int)params.get(3).value) { | |||
case 0: | |||
x = getFirstNotBlackX(x, y); | |||
xend = getNextBlackX(x, y); | |||
break; | |||
case 1: | |||
x = getFirstBrightX(x, y); | |||
xend = getNextDarkX(x, y); | |||
break; | |||
case 2: | |||
x = getFirstNotWhiteX(x, y); | |||
xend = getNextWhiteX(x, y); | |||
break; | |||
default: | |||
break; | |||
} | |||
if (x < 0) break; | |||
int sortLength = xend-x; | |||
color[] unsorted = new color[sortLength]; | |||
color[] sorted = new color[sortLength]; | |||
for (int i=0; i<sortLength; i++) { | |||
unsorted[i] = renderer.pixels[x + i + y * renderer.width]; | |||
} | |||
sorted = sort(unsorted); | |||
for (int i=0; i<sortLength; i++) { | |||
renderer.pixels[x + i + y * renderer.width] = sorted[i]; | |||
} | |||
x = xend+1; | |||
} | |||
} | |||
void sortColumn() { | |||
int x = column; | |||
int y = 0; | |||
int yend = 0; | |||
while (yend < renderer.height-1) { | |||
switch((int)params.get(3).value) { | |||
case 0: | |||
y = getFirstNotBlackY(x, y); | |||
yend = getNextBlackY(x, y); | |||
break; | |||
case 1: | |||
y = getFirstBrightY(x, y); | |||
yend = getNextDarkY(x, y); | |||
break; | |||
case 2: | |||
y = getFirstNotWhiteY(x, y); | |||
yend = getNextWhiteY(x, y); | |||
break; | |||
default: | |||
break; | |||
} | |||
if (y < 0) break; | |||
int sortLength = yend-y; | |||
color[] unsorted = new color[sortLength]; | |||
color[] sorted = new color[sortLength]; | |||
for (int i=0; i<sortLength; i++) { | |||
unsorted[i] = renderer.pixels[x + (y+i) * renderer.width]; | |||
} | |||
sorted = sort(unsorted); | |||
for (int i=0; i<sortLength; i++) { | |||
renderer.pixels[x + (y+i) * renderer.width] = sorted[i]; | |||
} | |||
y = yend+1; | |||
} | |||
} | |||
//BLACK | |||
int getFirstNotBlackX(int _x, int _y) { | |||
int x = _x; | |||
int y = _y; | |||
color c; | |||
while ( (c = renderer.pixels[x + y * renderer.width]) < params.get(0).value) { | |||
x++; | |||
if (x >= renderer.width) return -1; | |||
} | |||
return x; | |||
} | |||
int getNextBlackX(int _x, int _y) { | |||
int x = _x+1; | |||
int y = _y; | |||
color c; | |||
while ( (c = renderer.pixels[x + y * renderer.width]) > params.get(0).value) { | |||
x++; | |||
if (x >= renderer.width) return renderer.width-1; | |||
} | |||
return x-1; | |||
} | |||
//BRIGHTNESS | |||
int getFirstBrightX(int _x, int _y) { | |||
int x = _x; | |||
int y = _y; | |||
color c; | |||
while (brightness (c = renderer.pixels[x + y * renderer.width]) < params.get(2).value) { | |||
x++; | |||
if (x >= renderer.width) return -1; | |||
} | |||
return x; | |||
} | |||
int getNextDarkX(int _x, int _y) { | |||
int x = _x+1; | |||
int y = _y; | |||
color c; | |||
while (brightness (c = renderer.pixels[x + y * renderer.width]) > params.get(2).value) { | |||
x++; | |||
if (x >= renderer.width) return renderer.width-1; | |||
} | |||
return x-1; | |||
} | |||
//WHITE | |||
int getFirstNotWhiteX(int _x, int _y) { | |||
int x = _x; | |||
int y = _y; | |||
color c; | |||
while ( (c = renderer.pixels[x + y * renderer.width]) > params.get(1).value) { | |||
x++; | |||
if (x >= renderer.width) return -1; | |||
} | |||
return x; | |||
} | |||
int getNextWhiteX(int _x, int _y) { | |||
int x = _x+1; | |||
int y = _y; | |||
color c; | |||
while ( (c = renderer.pixels[x + y * renderer.width]) < params.get(1).value) { | |||
x++; | |||
if (x >= renderer.width) return renderer.width-1; | |||
} | |||
return x-1; | |||
} | |||
//BLACK | |||
int getFirstNotBlackY(int _x, int _y) { | |||
int x = _x; | |||
int y = _y; | |||
color c; | |||
if (y < renderer.height) { | |||
while ( (c = renderer.pixels[x + y * renderer.width]) < params.get(0).value) { | |||
y++; | |||
if (y >= renderer.height) return -1; | |||
} | |||
} | |||
return y; | |||
} | |||
int getNextBlackY(int _x, int _y) { | |||
int x = _x; | |||
int y = _y+1; | |||
color c; | |||
if (y < renderer.height) { | |||
while ( (c = renderer.pixels[x + y * renderer.width]) > params.get(0).value) { | |||
y++; | |||
if (y >= renderer.height) return renderer.height-1; | |||
} | |||
} | |||
return y-1; | |||
} | |||
//BRIGHTNESS | |||
int getFirstBrightY(int _x, int _y) { | |||
int x = _x; | |||
int y = _y; | |||
color c; | |||
if (y < renderer.height) { | |||
while (brightness (c = renderer.pixels[x + y * renderer.width]) < params.get(2).value) { | |||
y++; | |||
if (y >= renderer.height) return -1; | |||
} | |||
} | |||
return y; | |||
} | |||
int getNextDarkY(int _x, int _y) { | |||
int x = _x; | |||
int y = _y+1; | |||
color c; | |||
if (y < renderer.height) { | |||
while (brightness (c = renderer.pixels[x + y * renderer.width]) > params.get(2).value) { | |||
y++; | |||
if (y >= renderer.height) return renderer.height-1; | |||
} | |||
} | |||
return y-1; | |||
} | |||
//WHITE | |||
int getFirstNotWhiteY(int _x, int _y) { | |||
int x = _x; | |||
int y = _y; | |||
color c; | |||
if (y < renderer.height) { | |||
while ( (c = renderer.pixels[x + y * renderer.width]) > params.get(2).value) { | |||
y++; | |||
if (y >= renderer.height) return -1; | |||
} | |||
} | |||
return y; | |||
} | |||
int getNextWhiteY(int _x, int _y) { | |||
int x = _x; | |||
int y = _y+1; | |||
color c; | |||
if (y < renderer.height) { | |||
while ( (c = renderer.pixels[x + y * renderer.width]) < params.get(1).value) { | |||
y++; | |||
if (y >= renderer.height) return renderer.height-1; | |||
} | |||
} | |||
return y-1; | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
class AUECHO extends Shader { | |||
AUECHO() { | |||
name = "fxAUecho"; | |||
params.add(new Param("mode", 2, new int[]{RANDOM})); | |||
params.add(new Param("echo", 0, 255, new int[]{SIN, LINE, RAMPUPDOWN, TAN, COS})); | |||
params.add(new Param("decay", 0, 255, new int[]{SIN, LINE, RAMPUPDOWN, TAN, COS})); | |||
} | |||
/* | |||
float inc1, inc2; | |||
void animate() { | |||
inc1+=.00003; | |||
inc2+=.04; | |||
params.get(1).setValue((sin(inc1)+1)/4); | |||
params.get(2).setValue((sin(inc2)+1)/2); | |||
if (random(1) > .99) { | |||
for (int i = 0; i < params.size(); i++) | |||
params.get(i).randomize(); | |||
} | |||
} | |||
*/ | |||
void apply() { | |||
renderer.beginDraw(); | |||
if (params.get(0).value == 0) { | |||
renderer.colorMode(HSB); | |||
colorMode(HSB); | |||
} else { | |||
renderer.colorMode(RGB); | |||
colorMode(RGB); | |||
} | |||
renderer.loadPixels(); | |||
float _delay = map(params.get(1).getValue(params.get(1).value, true), 0, 1, 0.001, 1.0); | |||
float decay = map(params.get(2).getValue(params.get(2).value, true), 0, 1, 0.0, 1.0); | |||
int delay = (int)(renderer.pixels.length * _delay); | |||
color[] history = new color[renderer.pixels.length]; | |||
int blendMode = BLEND; | |||
for ( int i = 0, l = renderer.pixels.length; i<l; i++) { | |||
history[i] = renderer.pixels[i]; | |||
} | |||
for ( int i = 0, l = renderer.pixels.length; i<l; i++) { | |||
int fromPos = i-delay < 0 ? l-abs(i-delay) : i-delay; | |||
color fromColor = history[fromPos]; | |||
float r = red(fromColor) * decay; | |||
float g = green(fromColor) * decay; | |||
float b = blue(fromColor) * decay; | |||
color origColor = history[i]; | |||
color toColor = color( | |||
r = r + red(origColor) > 255 ? r + red(origColor) - 255 : r + red(origColor), // simulate overflow ;) | |||
g = g + green(origColor) > 255 ? g + green(origColor) - 255 : g + green(origColor), | |||
b = b + blue(origColor) > 255 ? b + blue(origColor) - 255 : b + blue(origColor) ); | |||
renderer.pixels[i] = history[i] = toColor; //blendColor(origColor, toColor, blendMode); | |||
} | |||
renderer.updatePixels(); | |||
if (params.get(0).value == 0) { | |||
renderer.colorMode(RGB); | |||
colorMode(RGB); | |||
} | |||
renderer.endDraw(); | |||
} | |||
} |
@@ -0,0 +1,83 @@ | |||
class BRIGHTER extends Shader { | |||
BRIGHTER() { | |||
name = "fxBRIGHTER"; | |||
params.add(new Param("mode", 2, new int[]{RANDOM})); | |||
params.add(new Param("thresh", 60, 180, new int[]{SIN, LINE, RAMPUPDOWN, TAN, COS})); | |||
params.add(new Param("thresh2", 120, 200, new int[]{SIN, LINE, RAMPUPDOWN, TAN, COS})); | |||
params.add(new Param("brighten", 140, 220, new int[]{SIN, LINE, RAMPUPDOWN, TAN, COS})); | |||
/* | |||
params.add(new Param("mode", 2)); | |||
params.add(new Param("thresh", 60, 180)); | |||
params.add(new Param("thresh2", 120, 200)); | |||
params.add(new Param("brighten", 140, 220));*/ | |||
} | |||
/* | |||
float inc1, inc2, inc3; | |||
float speed; | |||
void animate() { | |||
inc1+=(speed + .006); | |||
inc2+=(speed + .0045); | |||
inc3+=(speed + .002); | |||
//gui.brickP5.getController("knobOne-"+str(brick)).setValue(int(map(sin(inc1), 2, -1, 0, 255))); | |||
//gui.brickP5.getController("knobTwo-"+str(brick)).setValue(int(map(cos(inc2), -1, 1, 0, 255))); | |||
//if (mode == 0) { | |||
// gui.brickP5.getController("knobThree-"+str(brick)).setValue(int(map(cos(inc2), -1, 1, 0, int(map(cos(inc2), -1, 1, 0, 255))))); | |||
//} else if (mode == 1) { | |||
// gui.brickP5.getController("knobThree-"+str(brick)).setValue(int(map(cos(inc2), -1, 1, int(map(cos(inc2), -1, 1, 0, 255)), 255 ))); | |||
//} | |||
if (random(1) > .99) { | |||
for (int i = 0; i < params.size(); i++) | |||
params.get(i).randomize(); | |||
} | |||
} | |||
*/ | |||
void apply() { | |||
int mode = (int)params.get(0).value; | |||
float brighten = params.get(1).value; | |||
float thresh = params.get(2).value; | |||
float thresh2 = params.get(3).value; | |||
renderer.beginDraw(); | |||
renderer.colorMode(HSB); | |||
colorMode(HSB); | |||
renderer.loadPixels(); | |||
if (mode == 0) { | |||
for (int i = 0; i < renderer.width*renderer.height; i++) { | |||
float hue = hue(renderer.pixels[i]); | |||
float sat = saturation(renderer.pixels[i]); | |||
float bright = brightness(renderer.pixels[i]); | |||
if (bright < thresh && bright > thresh2) { | |||
bright += brighten; | |||
constrain(bright, 0, 255); | |||
} | |||
color c = color(hue, sat, bright); | |||
renderer.pixels[i] = c; | |||
} | |||
} else if (mode == 1) { | |||
for (int i = 0; i < renderer.width*renderer.height; i++) { | |||
float hue = hue(renderer.pixels[i]); | |||
float sat = saturation(renderer.pixels[i]); | |||
float bright = brightness(renderer.pixels[i]); | |||
if (bright > thresh && bright < thresh2) { | |||
bright += brighten; | |||
constrain(bright, 0, 255); | |||
} | |||
color c = color(hue, sat, bright); | |||
renderer.pixels[i] = c; | |||
} | |||
} | |||
renderer.updatePixels(); | |||
renderer.colorMode(RGB); | |||
colorMode(RGB); | |||
renderer.endDraw(); | |||
} | |||
} |
@@ -0,0 +1,74 @@ | |||
class DARKER extends Shader { | |||
DARKER() { | |||
name = "fxDARKER"; | |||
/* | |||
params.add(new Param ("layers", 5)); | |||
params.add(new Param ("thresh", 0, 255)); | |||
params.add(new Param ("value", 0, 255)); | |||
params.add(new Param ("mode", 2));*/ | |||
} | |||
float inc1, inc2; | |||
float playSpeed = 4; | |||
void animate() { | |||
inc1+=playSpeed/400; | |||
inc2+=playSpeed/300; | |||
if ((frameCount % int(map(playSpeed, 0, 4, 15, 120))) == 0) { | |||
for (int i = 0; i < params.size(); i++) | |||
params.get(i).randomize(); | |||
} | |||
params.get(1).setValue((sin(inc1)+1)/2); | |||
params.get(2).setValue((sin(inc2)+1)/2); | |||
} | |||
void apply() { | |||
float h, s, b; | |||
renderer.beginDraw(); | |||
renderer.colorMode(HSB); | |||
renderer.loadPixels(); | |||
colorMode(HSB); | |||
if (params.get(3).value == 0) { | |||
for (int j = 1; j < params.get(0).value+1; j++) { | |||
for (int i = 0; i < renderer.width*renderer.height; i++) { | |||
h = hue(renderer.pixels[i]); | |||
s = saturation(renderer.pixels[i]); | |||
b = brightness(renderer.pixels[i]); | |||
if (b > params.get(1).value/j); | |||
{ | |||
if (!(h == 85.0 && s == 255.0 && b == 255.0)) { | |||
b -= params.get(2).value/j; | |||
constrain(b, 0, 255); | |||
color c = color(h, s, b); | |||
renderer.pixels[i] = c; | |||
} | |||
} | |||
} | |||
} | |||
} else if (params.get(3).value == 1) { | |||
for (int j = 1; j < params.get(0).value+1; j++) { | |||
for (int i = 0; i < renderer.width*renderer.height; i++) { | |||
h = hue(renderer.pixels[i]); | |||
s = saturation(renderer.pixels[i]); | |||
b = brightness(renderer.pixels[i]); | |||
if (b < params.get(1).value/j) { | |||
if (!(h == 85.0 && s == 255.0 && b == 255.0)); | |||
{ | |||
b -= params.get(2).value/j; | |||
constrain(b, 0, 255); | |||
} | |||
} | |||
color c = color(h, s, b); | |||
renderer.pixels[i] = c; | |||
} | |||
} | |||
} | |||
renderer.updatePixels(); | |||
renderer.colorMode(RGB); | |||
renderer.endDraw(); | |||
colorMode(RGB); | |||
} | |||
} |
@@ -0,0 +1,142 @@ | |||
class DISTORTER extends Shader { | |||
PImage buffer; | |||
int[][] distort = new int[2][512]; | |||
final static float tick = 1.0/512.0; | |||
final int[] blends = { | |||
ADD, SUBTRACT, DARKEST, LIGHTEST, DIFFERENCE, EXCLUSION, MULTIPLY, SCREEN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN | |||
}; | |||
// ALL Channels, Nxxx stand for negative (255-value) | |||
// channels to work with | |||
final static int RED = 0; | |||
final static int GREEN = 1; | |||
final static int BLUE = 2; | |||
final static int HUE = 3; | |||
final static int SATURATION = 4; | |||
final static int BRIGHTNESS = 5; | |||
final static int NRED = 6; | |||
final static int NGREEN = 7; | |||
final static int NBLUE = 8; | |||
final static int NHUE = 9; | |||
final static int NSATURATION = 10; | |||
final static int NBRIGHTNESS = 11; | |||
DISTORTER() { | |||
name = "fxDistorter"; | |||
/* | |||
//params.add(new Param ("shifthue", 1)); //boolean shift_hue | |||
params.add(new Param("hueshift", 0, 1)); //float shift_amt | |||
params.add(new Param("scalex", 0.01, 1)); //float scalex | |||
params.add(new Param("scaley", 0.01, 1)); //float scaley | |||
//params.add(new Param ("blend", 1)); //boolean do_blend | |||
params.add(new Param ("blendmode", blends.length)); //int blend_mode | |||
params.add(new Param("channel", 12));*/ | |||
buffer = createImage(renderer.width, renderer.height, ARGB); | |||
// prepare distortion pattern | |||
for (int i=0; i<512; i++) { | |||
distort[0][i] = (int)random(-128, 128); | |||
distort[1][i] = (int)random(-128, 128); | |||
} | |||
} | |||
float inc1, inc2; | |||
void animate() { | |||
inc1+=.03; | |||
inc2+=.04; | |||
params.get(1).setValue((sin(inc1)+1)/2); | |||
params.get(2).setValue((sin(inc2)+1)/2); | |||
if (random(1) > .99) { | |||
for (int i = 0; i < params.size(); i++) | |||
params.get(i).randomize(); | |||
} | |||
} | |||
void apply() { | |||
buffer = renderer.get(); | |||
buffer.resize(renderer.width, renderer.height); | |||
float neww = map(params.get(1).value, 0, 1, 1, buffer.width/4); | |||
float newh = map(params.get(2).value, 0, 1, 1, buffer.height/4); | |||
float totalnum = neww+newh; | |||
float times = (totalnum/floor(totalnum/neww)); | |||
float offx = (totalnum%neww)/times; | |||
float ratiox = neww/buffer.width; | |||
renderer.beginDraw(); | |||
renderer.noStroke(); | |||
for (int y=0; y<buffer.height; y++) { | |||
float yy = y/(float)buffer.height; | |||
for (int x=0; x<buffer.width; x++) { | |||
float xx = x/(float)buffer.width; | |||
float offy = floor(newh*yy); | |||
float fx = xx*ratiox+offx*offy; | |||
float shift = fx%1.0; | |||
float st = shift/tick; | |||
int no1 = floor(st)%512; | |||
int no2 = ceil(st)%512; | |||
float l = st-(float)no1; | |||
float cx = lerp(distort[0][no1], distort[0][no2], l); | |||
float cy = lerp(distort[1][no1], distort[1][no2], l); | |||
float rx =getChannel(buffer.get(x, y), (int)params.get(4).value); | |||
int sx = (int)((buffer.width+x+cx*rx*params.get(1).value*0.1)%buffer.width); | |||
int sy = (int)((buffer.height+y+cy*params.get(0).value)%buffer.height); | |||
color c=buffer.get(sx, sy); | |||
//if (boolean((int)(params.get(0).value))) { | |||
colorMode(HSB, 255); | |||
c = color((hue(c)+params.get(0).value*255*noise(newh+y))%255.0, constrain(saturation(c)*1.2, 0, 255), constrain(brightness(c), 0, 255)); | |||
colorMode(RGB, 255); | |||
//} | |||
//renderer.fill(lerpColor(c,buffer.get(x,y),0.2)); | |||
renderer.fill(c); | |||
renderer.rect(x, y, 1, 1); | |||
} | |||
} | |||
//if (boolean((int)(params.get(4).value))) | |||
renderer.blend(buffer, 0, 0, buffer.width, buffer.height, 0, 0, renderer.width, renderer.height, (int)params.get(3).value); | |||
colorMode(RGB); | |||
renderer.endDraw(); | |||
} | |||
float getChannel(color c, int channel) { | |||
int ch = channel>5?channel-6:channel; | |||
float cc; | |||
switch(ch) { | |||
case RED: | |||
cc = red(c); | |||
break; | |||
case GREEN: | |||
cc = green(c); | |||
break; | |||
case BLUE: | |||
cc = blue(c); | |||
break; | |||
case HUE: | |||
cc = hue(c); | |||
break; | |||
case SATURATION: | |||
cc = saturation(c); | |||
break; | |||
default: | |||
cc= brightness(c); | |||
break; | |||
} | |||
return channel>5?255-cc:cc; | |||
} | |||
} |
@@ -0,0 +1,119 @@ | |||
class DRAWGENERATIVE extends Shader { | |||
// choose channel | |||
int channel = HUE; | |||
// run, after 30 iterations result will be saved automatically | |||
// or press SPACE | |||
// channels to work with | |||
final static int RED = 0; | |||
final static int GREEN = 1; | |||
final static int BLUE = 2; | |||
final static int HUE = 3; | |||
final static int SATURATION = 4; | |||
final static int BRIGHTNESS = 5; | |||
final static int NRED = 6; | |||
final static int NGREEN = 7; | |||
final static int NBLUE = 8; | |||
final static int NHUE = 9; | |||
final static int NSATURATION = 10; | |||
final static int NBRIGHTNESS = 11; | |||
int n=2000; | |||
float [] cx=new float[n]; | |||
float [] cy=new float[n]; | |||
int len; | |||
// working buffer | |||
PGraphics buffer; | |||
int tick = 0; | |||
DRAWGENERATIVE() { | |||
name = "fxDrawGenerative"; | |||
buffer = createGraphics(renderer.width, renderer.height); | |||
buffer.noFill(); | |||
buffer.beginDraw(); | |||
buffer.strokeWeight(0.3); | |||
//buffer.background(0); //ENABLE THIS TO DRAW FROM BLANK | |||
buffer.endDraw(); | |||
rw = renderer.width; | |||
len = (renderer.width<renderer.height?renderer.width:renderer.height)/6; | |||
for (int i=0; i<n; i++) { | |||
cx[i]=random(renderer.width); | |||
cy[i]=random(renderer.height); | |||
} | |||
} | |||
int rw; | |||
void apply() { | |||
if (rw != renderer.width) { | |||
rw = renderer.width; | |||
PGraphics save = createGraphics(renderer.width, renderer.height); | |||
save.beginDraw(); | |||
save.image(buffer, 0, 0, save.width, save.height); | |||
save.endDraw(); | |||
buffer.setSize(renderer.width, renderer.height); | |||
buffer.beginDraw(); | |||
buffer.image(save,0,0,buffer.width,buffer.height); | |||
buffer.endDraw(); | |||
} | |||
buffer.beginDraw(); | |||
for (int i=1; i<n; i++) { | |||
color c = renderer.get((int)cx[i], (int)cy[i]); | |||
buffer.stroke(c); | |||
buffer.point(cx[i], cy[i]); | |||
// you can choose channels: red(c), blue(c), green(c), hue(c), saturation(c) or brightness(c) | |||
cy[i]+=sin(map(getChannel(c), 0, 255, 0, TWO_PI)); | |||
cx[i]+=cos(map(getChannel(c), 0, 255, 0, TWO_PI)); | |||
} | |||
if (frameCount>len) { | |||
frameCount=0; | |||
println("iteration: " + tick++); | |||
for (int i=0; i<n; i++) { | |||
cx[i]=random(renderer.width); | |||
cy[i]=random(renderer.height); | |||
} | |||
} | |||
buffer.endDraw(); | |||
renderer.beginDraw(); | |||
renderer.image(buffer, 0, 0, renderer.width, renderer.height); | |||
renderer.endDraw(); | |||
} | |||
float getChannel(color c) { | |||
int ch = channel>5?channel-6:channel; | |||
float cc; | |||
switch(ch) { | |||
case RED: | |||
cc = red(c); | |||
break; | |||
case GREEN: | |||
cc = green(c); | |||
break; | |||
case BLUE: | |||
cc = blue(c); | |||
break; | |||
case HUE: | |||
cc = hue(c); | |||
break; | |||
case SATURATION: | |||
cc = saturation(c); | |||
break; | |||
default: | |||
cc= brightness(c); | |||
break; | |||
} | |||
return channel>5?255-cc:cc; | |||
} | |||
} |
@@ -0,0 +1,209 @@ | |||
class DRAWSTROKES extends Shader { | |||
int stat_type = ABSDIST2; // type of diff calculation: fast: ABSDIST, DIST, slow: HUE, SATURATION, BRIGHTNESS | |||
int stroke_len = 3; // length of the stroke, values: 1 and above | |||
int angles_no = 30; // number of directions stroke can be drew, 2 and above | |||
int segments = 500; // number of segments of single thread | |||
float stroke_width = 1; // width of the stroke, 0.5 - 3 | |||
int stroke_alpha = 100; // alpha channel of the stroke: 30 - 200 | |||
color background_color = color(255, 255, 255); // RGB | |||
boolean interactive = false; | |||
int max_display_size = 800; // viewing window size (regardless image size) | |||
int len; | |||
// working buffer | |||
PGraphics buffer; | |||
int currx, curry; | |||
int[] sintab, costab; | |||
int sqwidth; | |||
int calcDiff(PImage img1, PImage img2) { | |||
int err = 0; | |||
for (int i=0; i<img1.pixels.length; i++) | |||
err += getStat(img1.pixels[i], img2.pixels[i]); | |||
return err; | |||
} | |||
DRAWSTROKES() { | |||
name = "fxDrawStrokes"; | |||
/* | |||
params.add(new Param ("stat_type", 6)); //0 bis 5, 4 und 5 sind mit abstand am schnellsten | |||
params.add(new Param ("stroke_len", 1, 15)); | |||
params.add(new Param ("angles_no", 2, 50)); | |||
params.add(new Param ("segments", 50, 1500)); | |||
params.add(new Param ("stroke_width", 0.5, 3)); | |||
params.add(new Param ("stroke_alpha", 50, 200)); | |||
*/ | |||
params.get(0).randomize(); | |||
params.get(1).randomize(); | |||
params.get(2).randomize(); | |||
params.get(3).randomize(); | |||
params.get(4).randomize(); | |||
params.get(5).randomize(); | |||
len = (renderer.width<renderer.height?renderer.width:renderer.height)/3; | |||
buffer = createGraphics(renderer.width, renderer.height); | |||
//buffer.smooth(8); | |||
buffer.beginDraw(); | |||
buffer.background(255); | |||
buffer.noFill(); | |||
buffer.endDraw(); | |||
rw = renderer.width; | |||
reinit(); | |||
} | |||
void reinit() { | |||
buffer.beginDraw(); | |||
buffer.strokeWeight(stroke_width); | |||
//buffer.background(background_color); //ENABLE THIS TO DRAW FROM BLANK | |||
buffer.endDraw(); | |||
currx = (int)random(renderer.width); | |||
curry = (int)random(renderer.height); | |||
sintab = new int[angles_no]; | |||
costab = new int[angles_no]; | |||
for (int i=0; i<angles_no; i++) { | |||
sintab[i] = (int)(stroke_len * sin(TWO_PI*i/(float)angles_no)); | |||
costab[i] = (int)(stroke_len * cos(TWO_PI*i/(float)angles_no)); | |||
} | |||
sqwidth = stroke_len * 2 + 4; | |||
} | |||
void animate() { | |||
if (random(1) > .99) { | |||
for (int i = 0; i < params.size(); i++) | |||
params.get(i).randomize(); | |||
stat_type = (int)params.get(0).value; | |||
stroke_len = (int)params.get(1).value; | |||
angles_no = (int)params.get(2).value; | |||
segments = (int)params.get(3).value; | |||
stroke_width = params.get(4).value; | |||
stroke_alpha = (int)params.get(5).value; | |||
reinit(); | |||
} | |||
} | |||
int rw; | |||
void apply() { | |||
if (rw != renderer.width) { | |||
rw = renderer.width; | |||
PGraphics save = createGraphics(renderer.width, renderer.height); | |||
save.beginDraw(); | |||
save.image(buffer, 0, 0, save.width, save.height); | |||
save.endDraw(); | |||
buffer.setSize(renderer.width, renderer.height); | |||
buffer.beginDraw(); | |||
buffer.image(save, 0, 0, buffer.width, buffer.height); | |||
buffer.endDraw(); | |||
} | |||
currx = (int)random(renderer.width); | |||
curry = (int)random(renderer.height); | |||
buffer.beginDraw(); | |||
//draw whole segment using current color | |||
buffer.stroke(renderer.get(currx, curry), stroke_alpha); | |||
for (int iter=0; iter<segments; iter++) { | |||
// corners of square containing new strokes | |||
int corx = currx-stroke_len-2; | |||
int cory = curry-stroke_len-2; | |||
// take square from image and current screen | |||
PImage imgpart = renderer.get(corx, cory, sqwidth, sqwidth); | |||
PImage mypart = buffer.get(corx, cory, sqwidth, sqwidth); | |||
imgpart.loadPixels(); | |||
mypart.loadPixels(); | |||
// calc current diff | |||
float localerr = calcDiff(imgpart, mypart); | |||
// chosen stroke will be here | |||
PImage destpart = null; | |||
int _nx=currx, _ny=curry; | |||
// start with random angle | |||
int i = (int)random(angles_no); | |||
int iterangles = angles_no; | |||
while (iterangles-- > 0) { | |||
// take end points | |||
int nx = currx + costab[i]; | |||
int ny = curry + sintab[i]; | |||
// if not out of the screen | |||
if (nx>=0 && nx<renderer.width-1 && ny>=0 && ny<renderer.height-1) { | |||
// clean region and draw line | |||
buffer.image(mypart, corx, cory); | |||
buffer.line(currx, curry, nx, ny); | |||
// take region with line and calc diff | |||
PImage curr = buffer.get(corx, cory, sqwidth, sqwidth); | |||
curr.loadPixels(); | |||
int currerr = calcDiff(imgpart, curr); | |||
// if better, remember this region and line endpoint | |||
if (currerr < localerr) { | |||
destpart = curr; | |||
_nx = nx; | |||
_ny = ny; | |||
localerr = currerr; | |||
} | |||
} | |||
// next angle | |||
i = (i+1)%angles_no; | |||
} | |||
// if we have new stroke, draw it | |||
if (destpart != null) { | |||
buffer.image(destpart, corx, cory); | |||
currx = _nx; | |||
curry = _ny; | |||
} else { | |||
break; // skip | |||
} | |||
} | |||
buffer.endDraw(); | |||
renderer.beginDraw(); | |||
renderer.image(buffer, 0, 0, renderer.width, renderer.height); | |||
renderer.endDraw(); | |||
} | |||
final static int DIST = 0; | |||
final static int HUE = 1; | |||
final static int BRIGHTNESS = 2; | |||
final static int SATURATION = 3; | |||
final static int ABSDIST = 4; | |||
final static int ABSDIST2 = 5; | |||
final float getStat(color c1, color c2) { | |||
switch(stat_type) { | |||
case HUE: | |||
abs(hue(c1)-hue(c2)); | |||
case BRIGHTNESS: | |||
abs(brightness(c1)-brightness(c2)); | |||
case SATURATION: | |||
abs(saturation(c1)-saturation(c2)); | |||
case ABSDIST: | |||
return abs(red(c1)-red(c2))+abs(green(c1)-green(c2))+abs(blue(c1)-blue(c2)); | |||
case ABSDIST2: | |||
return abs( (red(c1)+blue(c1)+green(c1)) - (red(c2)+blue(c2)+green(c2)) ); | |||
default: | |||
return sq(red(c1)-red(c2)) + sq(green(c1)-green(c2)) + sq(blue(c1)-blue(c2)); | |||
} | |||
} | |||
} |
@@ -0,0 +1,249 @@ | |||
// FM - frequency modulator | |||
// 2016 Tomasz Sulej, generateme.blog@gmail.com, http://generateme.tumblr.com | |||
// Licence: http://unlicense.org/ | |||
// Frequency modulation and demodulation of the image | |||
// process goes in following way: | |||
// - convert RGB into desired colorspace (GS - grayscale) | |||
// For every channel | |||
// - modulate signal | |||
// - quantize and dequantize signal (if quantval > 0) | |||
// - demodulate signal using derivative method | |||
// - apply 3 lowpass filters in a chain to remove carrier (if possible) | |||
// Combine channels and convert back to RGB | |||
// Usage: | |||
// * move mouse X axis - change the carrier wave frequency | |||
// * move mouse Y axis - change bandwidth | |||
// * click mouse to fix setup (click again to release) | |||
// * press N to negate image | |||
// * press SPACE to save | |||
class FM extends Shader { | |||
// configuration | |||
int colorspace = RGB; | |||
final static boolean first_channel_only = false; // for L.. or Y.. colorspaces set true to modulate only luma; | |||
final static int quantval = 30; // 0 - off, less - more glitch, more - more precision | |||
final static boolean lowpass1_on = true; // on/off of first low pass filter | |||
final static boolean lowpass2_on = true; // on/off of second low pass filter | |||
final static boolean lowpass3_on = true; // on/off of third low pass filter | |||
// better don't touch it, lowpass filters are run in cascade | |||
float lowpass1_cutoff = 0.25; // percentage of rate | |||
float lowpass2_cutoff = 0.1; | |||
float lowpass3_cutoff = 0.05; | |||
boolean do_blend = true; // blend image after process | |||
int blend_mode = OVERLAY; // blend type | |||
// working buffer | |||
PGraphics buffer; | |||
// image | |||
//PImage img; | |||
// local variables | |||
float min_omega, max_omega; | |||
float min_phase_mult=0.05; | |||
float max_phase_mult=50.0; | |||
LowpassFilter lpf1, lpf2, lpf3; | |||
int[][] pxls; | |||
boolean negate = false; | |||
FM() { | |||
name = "fxFM"; | |||
//img = loadImage(foldername+filename+fileext); | |||
params.add(new Param ("blend_mode", 11, new int[]{RANDOM})); | |||
params.add(new Param ("omega", 0, 1, new int[]{SIN, LINE})); | |||
params.add(new Param ("phase", 0, 1, new int[]{LINE, SIN, TAN, RAMPUPDOWN, RAMP})); | |||
params.get(0).randomize(); | |||
params.get(1).randomize(); | |||
params.get(2).randomize(); | |||
buffer = createGraphics(renderer.width, renderer.height); | |||
buffer.beginDraw(); | |||
buffer.noStroke(); | |||
//buffer.smooth(8); | |||
//buffer.background(0); | |||
// buffer.image(renderer, 0, 0); | |||
buffer.endDraw(); | |||
//img.loadPixels(); | |||
min_omega = TWO_PI/(0.05*renderer.width); | |||
max_omega = TWO_PI/(300.0*renderer.width); | |||
float rate = 100000.0; | |||
lpf1 = new LowpassFilter(rate, lowpass1_cutoff*rate); | |||
lpf2 = new LowpassFilter(rate, lowpass2_cutoff*rate); | |||
lpf3 = new LowpassFilter(rate, lowpass3_cutoff*rate); | |||
rw = renderer.width; | |||
prepareData(); | |||
} | |||
//float inc1, inc2; | |||
//float playSpeed = 4; | |||
/* | |||
void animate() { | |||
blend_mode = (int)params.get(0).value + 2; | |||
inc1+=playSpeed/400; | |||
inc2+=playSpeed/300; | |||
if ((frameCount % int(map(playSpeed, 0, 4, 15, 120))) == 0) { | |||
for (int i = 0; i < params.size(); i++) | |||
params.get(i).randomize(); | |||
} | |||
params.get(1).setValue((sin(inc1)+1)/2); | |||
params.get(2).setValue((sin(inc2)+1)/2); | |||
} | |||
*/ | |||
void prepareData() { | |||
pxls = new int[3][renderer.pixels.length]; | |||
for (int i=0; i<renderer.pixels.length; i++) { | |||
int cl = toColorspace(renderer.pixels[i], colorspace); | |||
pxls[0][i] = (cl >> 16) & 0xff; | |||
pxls[1][i] = (cl >> 8) & 0xff; | |||
pxls[2][i] = (cl) & 0xff; | |||
} | |||
} | |||
float omega, min_phase, max_phase; | |||
int rw, rh; | |||
void apply() { | |||
if (rw != renderer.width || rh != renderer.height) { | |||
rw = renderer.width; | |||
rh = renderer.height; | |||
min_omega = TWO_PI/(0.05*renderer.width); | |||
max_omega = TWO_PI/(300.0*renderer.width); | |||
prepareData(); | |||
} | |||
buffer.setSize(renderer.width, renderer.height); | |||
omega = map(sqrt(params.get(1).value), 0, 1, min_omega, max_omega); | |||
float phase = map(sq(params.get(2).value), 0, 1, min_phase_mult, max_phase_mult); | |||
max_phase = phase * omega; | |||
min_phase = -max_phase; | |||
processImage(); | |||
} | |||
void processImage() { | |||
buffer.beginDraw(); | |||
buffer.loadPixels(); | |||
int [][] dest_pxls = new int[3][renderer.pixels.length]; | |||
if (first_channel_only) { | |||
arrayCopy(pxls[1], dest_pxls[1]); | |||
arrayCopy(pxls[2], dest_pxls[2]); | |||
} | |||
for (int i=0; i< (first_channel_only?1:3); i++) { | |||
for (int y=0; y<renderer.height; y++) { | |||
int off = y * renderer.width; | |||
//reset filters each line | |||
lpf1.resetFilter(map(pxls[i][off], 0, 255, min_phase, max_phase)); | |||
lpf2.resetFilter(map(pxls[i][off], 0, 255, min_phase, max_phase)); | |||
lpf3.resetFilter(map(pxls[i][off], 0, 255, min_phase, max_phase)); | |||
float sig_int = 0; // integral of the signal | |||
float pre_m = 0; // previous value of modulated signal | |||
for (int x=0; x<renderer.width; x++) { | |||
///////////////////////// | |||
// FM part starts here | |||
///////////////////////// | |||
float sig = map(pxls[i][x+off], 0, 255, min_phase, max_phase); // current signal value | |||
sig_int += sig; // current value of signal integral | |||
float m = cos(omega * x + sig_int); // modulate signal | |||
if ( quantval > 0) { | |||
m = map((int)map(m, -1, 1, 0, quantval), 0, quantval, -1, 1); // quantize | |||
} | |||
float dem = abs(m-pre_m); // demodulate signal, derivative | |||
pre_m = m; // remember current value | |||
// lowpass filter chain | |||
if (lowpass1_on) dem = lpf1.lowpass(dem); | |||
if (lowpass2_on) dem = lpf2.lowpass(dem); | |||
if (lowpass3_on) dem = lpf3.lowpass(dem); | |||
// remap signal back to channel value | |||
int v = constrain( (int)map(2*(dem-omega), min_phase, max_phase, 0, 255), 0, 255); | |||
////////////////////// | |||
// FM part ends here | |||
////////////////////// | |||
dest_pxls[i][x+off] = negate?255-v:v; | |||
} | |||
} | |||
} | |||
for (int i=0; i<buffer.pixels.length; i++) { | |||
buffer.pixels[i] = fromColorspace(0xff000000 | (dest_pxls[0][i] << 16) | (dest_pxls[1][i] << 8) | (dest_pxls[2][i]), colorspace); | |||
} | |||
buffer.updatePixels(); | |||
if (do_blend) | |||
buffer.blend(renderer, 0, 0, renderer.width, renderer.height, 0, 0, buffer.width, buffer.height, blend_mode); | |||
buffer.endDraw(); | |||
renderer.beginDraw(); | |||
renderer.image(buffer, 0, 0, renderer.width, renderer.height); | |||
renderer.endDraw(); | |||
} | |||
// | |||
final int[] blends = { | |||
ADD, SUBTRACT, DARKEST, LIGHTEST, DIFFERENCE, EXCLUSION, MULTIPLY, SCREEN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN | |||
}; | |||
class LowpassFilter { | |||
float alpha; | |||
float prev; | |||
public LowpassFilter(float rate, float hz) { | |||
alpha = 0.0; | |||
prev = 0.0; | |||
setFilter(rate, hz); | |||
} | |||
void setFilter(float rate, float hz) { | |||
float timeInterval = 1.0/rate; | |||
float tau = 1.0 / (hz * TWO_PI); | |||
alpha = timeInterval / (tau + timeInterval); | |||
} | |||
void resetFilter(float val) { | |||
prev = val; | |||
} | |||
void resetFilter() { | |||
resetFilter(0); | |||
} | |||
float lowpass(float sample) { | |||
float stage1 = sample * alpha; | |||
float stage2 = prev - (prev * alpha); | |||
prev = (stage1 + stage2); | |||
return prev; | |||
} | |||
float highpass(float sample) { | |||
return sample - lowpass(sample); | |||
} | |||
} | |||
} |
@@ -0,0 +1,56 @@ | |||
class GRAUZONE extends Shader { | |||
float inc1, inc2; | |||
int nFrames = 20; | |||
int iWrite = 0, iRead = 1; | |||
PImage[] buffer; | |||
PGraphics grauz; | |||
GRAUZONE() { | |||
name = "fxGRAUZONE"; | |||
//params.add(new Param ("discance", 3, 100)); | |||
params.get(0).setValue(.2); | |||
buffer = new PImage[nFrames]; | |||
} | |||
void animate() { | |||
inc1+=.03; | |||
inc2+=.04; | |||
//params.get(0).setValue((sin(inc1)+1)/2); | |||
if (random(1) > .99) { | |||
for (int i = 0; i < params.size(); i++) | |||
params.get(i).randomize(); | |||
} | |||
iWrite++; | |||
iRead++; | |||
if (iRead >= nFrames-1) { | |||
iRead = 0; | |||
} | |||
if (iWrite >= nFrames-1) { | |||
iWrite = 0; | |||
} | |||
} | |||
void apply() { | |||
//buffer[iWrite] = renderer.get(); | |||
grauz = createGraphics(renderer.width, renderer.height); | |||
grauz.beginDraw(); | |||
// grauz.resize(renderer.width, renderer.height); | |||
buffer[iWrite] = renderer.get(); | |||
if (buffer[iRead] != null) { | |||
grauz.tint(255, 127); | |||
if (this.animating) { | |||
buffer[iRead].filter(INVERT); | |||
} | |||
grauz.image(buffer[iRead], 0, 0, renderer.width, renderer.height); | |||
grauz.tint(255, 255); | |||
} | |||
grauz.endDraw(); | |||
renderer.beginDraw(); | |||
renderer.image(grauz, 0, 0, renderer.width, renderer.height); | |||
renderer.endDraw(); | |||
} | |||
} |
@@ -0,0 +1,188 @@ | |||
class SLITSCAN extends Shader { | |||
int[] fx; | |||
int[] fy; | |||
float[] phx; | |||
float[] phy; | |||
int[] sx, sy; | |||
boolean[] skipfx; | |||
boolean[] skipfy; | |||
boolean dox, doy; | |||
PImage buffer; | |||
float[][] ft = new float[2][32]; | |||
int depth; // number of octaves | |||
int fxnum; | |||
int fynum; | |||
SLITSCAN() { | |||
name = "fxSlitSscan"; | |||
buffer = createImage(renderer.width, renderer.height, ARGB); | |||
for (int i=0; i<32; i++) { | |||
ft[0][i] = pow(2.0, i); | |||
ft[1][i] = 0.5*1.0/ft[0][i]; | |||
} | |||
} | |||
void animate() { | |||
buffer.resize(renderer.width, renderer.height); | |||
buffer = renderer.get(0, 0, renderer.width, renderer.height); | |||
int s = buffer.width>buffer.height?buffer.height:buffer.width; | |||
depth = (int)(log(s)/log(2)); | |||
fxnum = (int)random(depth); | |||
fynum = (int)random(depth); | |||
fx = new int[fxnum+1]; | |||
fy = new int[fynum+1]; | |||
sx = new int[fxnum+1]; | |||
sy = new int[fynum+1]; | |||
phx = new float[fxnum+1]; | |||
phy = new float[fynum+1]; | |||
skipfx = new boolean[fxnum+1]; | |||
skipfy = new boolean[fynum+1]; | |||
for (int i=0; i<fxnum; i++) { | |||
//fx[i]=(int)random(6); | |||
fx[i]=(int)random(6); | |||
phx[i] = random(1); | |||
skipfx[i] = random(1)<0.2; | |||
sx[i] = random(1)<0.2?-1:1; | |||
} | |||
for (int i=0; i<fynum; i++) { | |||
fy[i]=(int)random(6); | |||
//fy[i]=6; | |||
phy[i] = random(1); | |||
skipfy[i] = random(1)<0.2; | |||
sy[i] = random(1)<0.2?-1:1; | |||
} | |||
dox = random(1)<0.8; | |||
doy = dox?random(1)<0.8:true; | |||
} | |||
void apply() { | |||
renderer.beginDraw(); | |||
renderer.colorMode(RGB); | |||
renderer.noStroke(); | |||
colorMode(RGB); | |||
renderer.fill(255); | |||
if (!this.animating) { | |||
// buffer = createImage(renderW, renderH, ARGB); | |||
buffer.resize(renderer.width, renderer.height); | |||
buffer = renderer.get(0, 0, renderer.width, renderer.height); | |||
// int s = buffer.width>buffer.height?buffer.height:buffer.width; | |||
// depth = (int)(log(s)/log(2)); | |||
// fxnum = (int)map(knobZero, 0, 255, 0, depth); | |||
// fynum = (int)map(knobOne, 0, 255, 0, depth); | |||
// fx = new int[fxnum+1]; | |||
// fy = new int[fynum+1]; | |||
// sx = new int[fxnum+1]; | |||
// sy = new int[fynum+1]; | |||
// | |||
// phx = new float[fxnum+1]; | |||
// phy = new float[fynum+1]; | |||
// | |||
// skipfx = new boolean[fxnum+1]; | |||
// skipfy = new boolean[fynum+1]; | |||
// | |||
// | |||
// for (int i=0; i<fxnum; i++) { | |||
// fx[i]=(int)random(6); | |||
// phx[i] = random(1); | |||
// skipfx[i] = random(1)<0.2; | |||
// sx[i] = random(1)<0.2?-1:1; | |||
// } | |||
// for (int i=0; i<fynum; i++) { | |||
// fy[i]=(int)random(6); | |||
// phy[i] = random(1); | |||
// skipfy[i] = random(1)<0.2; | |||
// sy[i] = random(1)<0.2?-1:1; | |||
// } | |||
// dox = random(1)<0.8; | |||
// doy = dox?random(1)<0.8:true; | |||
// } else { | |||
// println("ratatata"); | |||
// buffer = createImage(renderW, renderH, ARGB); | |||
// buffer = renderer.get(0, 0, renderer.width, renderer.height); | |||
} | |||
float v=0; | |||
for (int y=0; y<buffer.height; y++) | |||
for (int x=0; x<buffer.width; x++) { | |||
float iy = map(y, 0, buffer.height, 0, 1); | |||
v=0; | |||
if (doy) for (int i=0; i<fy.length; i++) | |||
if (!skipfy[i]) v+=sy[i]*getValue(fy[i], iy, i, phy[i]); | |||
float ry = 2*iy+v; | |||
float y2 = (3*buffer.height+ry * buffer.height/2)%buffer.height; | |||
float ix = map(x, 0, buffer.width, 0, 1); | |||
v=0; | |||
if (dox) for (int i=0; i<fx.length; i++) | |||
if (!skipfx[i]) v+=sx[i]*getValue(fx[i], ix, i, phx[i]); | |||
float rx = 2*ix+v; | |||
float x2 = (3*buffer.width+rx * buffer.width/2)%buffer.width; | |||
renderer.fill(buffer.get((int)x2, (int)y2)); | |||
renderer.rect(x, y, 1, 1); | |||
} | |||
renderer.endDraw(); | |||
} | |||
float getValue(int fun, float idx, int freq, float phase) { | |||
switch(fun) { | |||
case 0: | |||
return getSin(idx, freq, phase); | |||
case 1: | |||
return getSaw(idx, freq, phase); | |||
case 2: | |||
return getTriangle(idx, freq, phase); | |||
case 3: | |||
return getCutTriangle(idx, freq, phase); | |||
case 4: | |||
return getSquare(idx, freq, phase); | |||
case 5: | |||
return getNoise(idx, freq, phase); | |||
default: | |||
return getSin(idx, freq, phase); | |||
} | |||
} | |||
float getNoise(float idx, int freq, float phase) { | |||
return 2*ft[1][freq]*(noise((idx+phase)*ft[0][freq])-0.5); | |||
} | |||
float getSin(float idx, int freq, float phase) { | |||
float p = ft[0][freq]; | |||
return ft[1][freq] * sin(idx*TWO_PI*p+phase*TWO_PI); | |||
} | |||
float getSaw(float idx, int freq, float phase) { | |||
float p = ft[0][freq]; | |||
float rp = 2.0*ft[1][freq]; | |||
float p2 = p*((idx+phase+ft[1][freq])%1.0); | |||
return rp*(p2-floor(p2)-0.5); | |||
} | |||
float getSquare(float idx, int freq, float phase) { | |||
float p = ft[0][freq]; | |||
float rp = ft[1][freq]; | |||
return (((idx*p)+phase)%1.0)<0.5?rp:-rp; | |||
} | |||
float getTriangle(float idx, int freq, float phase) { | |||
return 2*abs(getSaw(idx, freq, phase+0.5*ft[1][freq]))-ft[1][freq]; | |||
} | |||
float getCutTriangle(float idx, int freq, float phase) { | |||
return constrain(getTriangle(idx, freq, phase), -ft[1][freq+1], ft[1][freq+1]); | |||
} | |||
} |
@@ -0,0 +1,250 @@ | |||
class WZIP extends Shader { | |||
final float sqrt05 = sqrt(0.5); | |||
float[] raw, raw1, raw2, raw3; | |||
float[] in, w, out; | |||
float[] in1, in2, in3, out1, out2, out3; | |||
int n, n2, s; | |||
float scalingfactorin, scalingfactorout; | |||
PImage img; | |||
String sessionid; | |||
WZIP() { | |||
name = "fxWZIP";/* | |||
params.add(new Param ("scale", 0, 1000)); | |||
params.add(new Param ("factor1", 0, 1)); | |||
params.add(new Param ("factor2", 0, 1)); | |||
params.add(new Param ("hsb", 2)); | |||
params.add(new Param ("mode", 2)); | |||
*/ | |||
sessionid = hex((int)random(0xffff), 4); | |||
img = createImage(renderer.width, renderer.height, ARGB); | |||
img = renderer.get(0, 0, renderer.width, renderer.height); | |||
// printOption(); | |||
// printScale(); | |||
} | |||
/* | |||
float inc1, inc2; | |||
void animate() { | |||
inc1+=.03; | |||
inc2+=.04; | |||
//gui.brickP5.getController("knobZero-"+str(brick)).setValue( map(sin(inc1), -1, 1, 0, 255)); | |||
//gui.brickP5.getController("knobOne-"+str(brick)).setValue(map(cos(inc2), -1, 1, 0, 255)); | |||
if (random(1) > .99) { | |||
for (int i = 0; i < params.size(); i++) | |||
params.get(i).randomize(); | |||
} | |||
} | |||
*/ | |||
void apply() { | |||
// img = createImage(renderer.width, renderer.height, ARGB); | |||
img.resize(renderer.width, renderer.height); | |||
img = renderer.get(0, 0, renderer.width, renderer.height); | |||
s = img.width*img.height; | |||
raw = new float[s*3]; | |||
raw1 = new float[s]; | |||
raw2 = new float[s]; | |||
raw3 = new float[s]; | |||
renderer.beginDraw(); | |||
renderer.background(0); | |||
renderer.noStroke(); | |||
if (boolean((int)params.get(3).value)) { | |||
renderer.colorMode(HSB, 255); | |||
colorMode(HSB, 255); | |||
} else { | |||
renderer.colorMode(RGB, 255); | |||
colorMode(RGB, 255); | |||
} | |||
scalingfactorin = map(params.get(1).value, 0, 1, 0, params.get(0).value); | |||
scalingfactorout = map(params.get(2).value, 0, 1, 0, params.get(0).value); | |||
int iter=0; | |||
int iter2 = 0; | |||
for (int y=0; y<img.height; y++) { | |||
for (int x=0; x<img.width; x++) { | |||
color c = img.get(x, y); | |||
float r, g, b; | |||
if (boolean((int)params.get(3).value)) { | |||
r = hue(c)>127?hue(c)-256:hue(c); | |||
g = saturation(c)>127?saturation(c)-256:saturation(c); | |||
b = brightness(c)>127?brightness(c)-256:brightness(c); | |||
} else { | |||
r = red(c)>127?red(c)-256:red(c); | |||
g = green(c)>127?green(c)-256:green(c); | |||
b = blue(c)>127?blue(c)-256:blue(c); | |||
} | |||
raw[iter++] = r; | |||
raw[iter++] = g; | |||
raw[iter++] = b; | |||
raw1[iter2] = r; | |||
raw2[iter2] = g; | |||
raw3[iter2] = b; | |||
iter2++; | |||
} | |||
} | |||
n = (int)pow(2, ceil(log(s*3)/log(2))); | |||
n2 = (int)pow(2, ceil(log(s)/log(2))); | |||
in = new float[n]; | |||
w = new float[n]; | |||
out = new float[n]; | |||
out1 = new float[n2]; | |||
out2 = new float[n2]; | |||
out3 = new float[n2]; | |||
in1 = new float[n2]; | |||
in2 = new float[n2]; | |||
in3 = new float[n2]; | |||
arrayCopy(raw, 0, in, 0, raw.length); | |||
for (int i=raw.length; i<n; i++) in[i] = raw[raw.length-1]; | |||
arrayCopy(raw1, 0, in1, 0, s); | |||
arrayCopy(raw2, 0, in2, 0, s); | |||
arrayCopy(raw3, 0, in3, 0, s); | |||
for (int i=s; i<n2; i++) { | |||
in1[i] = raw1[s-1]; | |||
in2[i] = raw2[s-1]; | |||
in3[i] = raw3[s-1]; | |||
} | |||
if (boolean((int)params.get(4).value)) option1(); | |||
else option2(); | |||
renderer.colorMode(RGB); | |||
colorMode(RGB); | |||
renderer.endDraw(); | |||
} | |||
// void printOption() { | |||
// String str1, str2; | |||
// if (do_hsb) { | |||
// str1 = "HSBHSBHSB..."; | |||
// str2 = "HHH...SSS...BBB..."; | |||
// } else { | |||
// str1 = "RGBRGBRGB..."; | |||
// str2 = "RRR...GGG...BBB..."; | |||
// } | |||
// if (option1) println("channels combined: " + str1); | |||
// else println("channels separated: " + str2); | |||
// } | |||
// | |||
// void printScale() { | |||
// println("Scale: 0.."+sc); | |||
// } | |||
float clamp(float c) { | |||
return(abs(c<0?256+c:c)%255.0); | |||
} | |||
void option2() { | |||
wtrafo(in1, n2); | |||
wbtrafo(out1, n2); | |||
wtrafo(in2, n2); | |||
wbtrafo(out2, n2); | |||
wtrafo(in3, n2); | |||
wbtrafo(out3, n2); | |||
for (int i=0; i<s; i++) { | |||
float r = clamp(out1[i]); | |||
float g = clamp(out2[i]); | |||
float b = clamp(out3[i]); | |||
renderer.fill(r, g, b); | |||
renderer.rect(i%img.width, i/img.width, 1, 1); | |||
} | |||
} | |||
void option1() { | |||
wtrafo(in, n); | |||
wbtrafo(out, n); | |||
float r=0, g=0, b=0; | |||
int state = 0; | |||
for (int i=0; i<raw.length; i++) { | |||
float c = clamp(out[i]); | |||
switch(state) { | |||
case 0: | |||
r = c; | |||
break; | |||
case 1: | |||
g = c; | |||
break; | |||
case 2: | |||
b = c; | |||
break; | |||
default: | |||
{ | |||
r = c; | |||
renderer.fill(r, g, b); | |||
renderer.rect(floor(i/3.0)%img.width, floor(i/3.0)/img.width, 1, 1); | |||
state = 0; | |||
} | |||
} | |||
state++; | |||
} | |||
} | |||
void wbtrafo(float[] y, int n) { | |||
float[] d = new float[n]; | |||
d[n-2] = w[n-1]; | |||
int b1 = n-4; | |||
int b2 = n-2; | |||
int a=1; | |||
while (a<n/2) { | |||
for (int i=0; i<a; i++) { | |||
d[2*i+b1]=(d[i+b2]+w[i+b2])*sqrt05; | |||
d[2*i+1+b1]=(d[i+b2]-w[i+b2])*sqrt05; | |||
} | |||
b2=b1; | |||
b1=b1-4*a; | |||
a*=2; | |||
} | |||
for (int i=0; i<a; i++) { | |||
y[2*i]=(d[i]+w[i])*sqrt05; | |||
y[2*i+1]=(d[i]-w[i])*sqrt05; | |||
} | |||
for (int i=0; i<n; i++) y[i] *= scalingfactorout; | |||
} | |||
void wtrafo(float[] y, int n) { | |||
float[] d = new float[n]; | |||
int a = n/2; | |||
for (int i=0; i<a; i++) { | |||
w[i] = (y[2*i]-y[2*i+1])*sqrt05; | |||
d[i] = (y[2*i]+y[2*i+1])*sqrt05; | |||
} | |||
int b1 = 0; | |||
int b2 = a; | |||
a/=2; | |||
while (a>0) { | |||
for (int i=0; i<a; i++) { | |||
w[i+b2]=(d[2*i+b1]-d[2*i+1+b1])*sqrt05; | |||
d[i+b2]=(d[2*i+b1]+d[2*i+1+b1])*sqrt05; | |||
} | |||
b1=b2; | |||
b2=b2+a; | |||
a/=2; | |||
} | |||
w[b2] = d[b1]; | |||
for (int i=0; i<n-1; i++) w[i] = (int)(w[i]/scalingfactorin); | |||
if (w[n-1]>0) w[n-1] = (int)(w[n-1]/scalingfactorin+0.5); | |||
else w[n-1] = (int)(w[n-1]/scalingfactorin-0.5); | |||
} | |||
} |
@@ -0,0 +1,800 @@ | |||
//from tomasz sulej's FM effect | |||
final static int COLORSPACES = 16; | |||
final static int OHTA = 0; | |||
// RGB == 1; defined in processing | |||
final static int CMY = 2; | |||
// HSB == 3; defined in processing | |||
final static int XYZ = 4; | |||
final static int YXY = 5; | |||
final static int HCL = 6; | |||
final static int LUV = 7; | |||
final static int LAB = 8; | |||
final static int HWB = 9; | |||
final static int RGGBG = 10; | |||
final static int YPbPr = 11; | |||
final static int YCbCr = 12; | |||
final static int YDbDr = 13; | |||
final static int GS = 14; | |||
final static int YUV = 15; | |||
// name | |||
String getColorspaceName(int cs) { | |||
switch(cs) { | |||
case OHTA: | |||
return "OHTA"; | |||
case CMY: | |||
return "CMY"; | |||
case XYZ: | |||
return "XYZ"; | |||
case YXY: | |||
return "YXY"; | |||
case HCL: | |||
return "HCL"; | |||
case LUV: | |||
return "LUV"; | |||
case LAB: | |||
return "LAB"; | |||
case HWB: | |||
return "HWB"; | |||
case HSB: | |||
return "HSB"; | |||
case RGGBG: | |||
return "R-GGB-G"; | |||
case YPbPr: | |||
return "YPbPr"; | |||
case YCbCr: | |||
return "YCbCr"; | |||
case YDbDr: | |||
return "YDbDr"; | |||
case GS: | |||
return "Greyscale"; | |||
case YUV: | |||
return "YUV"; | |||
default: | |||
return "RGB"; | |||
} | |||
} | |||
// colorspace converters | |||
color fromColorspace(color c, int cs) { | |||
switch(cs) { | |||
case OHTA: | |||
return fromOHTA(c); | |||
case CMY: | |||
return fromCMY(c); | |||
case XYZ: | |||
return fromXYZ(c); | |||
case YXY: | |||
return fromYXY(c); | |||
case HCL: | |||
return fromHCL(c); | |||
case LUV: | |||
return fromLUV(c); | |||
case LAB: | |||
return fromLAB(c); | |||
case HWB: | |||
return fromHWB(c); | |||
case HSB: | |||
return fromHSB(c); | |||
case RGGBG: | |||
return fromRGGBG(c); | |||
case YPbPr: | |||
return fromYPbPr(c); | |||
case YCbCr: | |||
return fromYCbCr(c); | |||
case YDbDr: | |||
return fromYDbDr(c); | |||
case GS: | |||
return tofromGS(c); | |||
case YUV: | |||
return fromYUV(c); | |||
default: | |||
return c; | |||
} | |||
} | |||
color toColorspace(color c, int cs) { | |||
switch(cs) { | |||
case OHTA: | |||
return toOHTA(c); | |||
case CMY: | |||
return toCMY(c); | |||
case XYZ: | |||
return toXYZ(c); | |||
case YXY: | |||
return toYXY(c); | |||
case HCL: | |||
return toHCL(c); | |||
case LUV: | |||
return toLUV(c); | |||
case LAB: | |||
return toLAB(c); | |||
case HWB: | |||
return toHWB(c); | |||
case HSB: | |||
return toHSB(c); | |||
case RGGBG: | |||
return toRGGBG(c); | |||
case YPbPr: | |||
return toYPbPr(c); | |||
case YCbCr: | |||
return toYCbCr(c); | |||
case YDbDr: | |||
return toYDbDr(c); | |||
case YUV: | |||
return toYUV(c); | |||
case GS: | |||
return tofromGS(c); | |||
default: | |||
return c; | |||
} | |||
} | |||
// Colorspace converters | |||
final int getR(color c) { | |||
return (c & 0xff0000) >> 16; | |||
} | |||
final int getG(color c) { | |||
return (c & 0xff00) >> 8; | |||
} | |||
final int getB(color c) { | |||
return c & 0xff; | |||
} | |||
final int getLuma(color c) { | |||
return constrain((int)(0.2126*getR(c)+0.7152*getG(c)+0.0722*getB(c)), 0, 255); | |||
} | |||
int getChannel(color c, int ch) { | |||
switch(ch) { | |||
case 0 : | |||
return getR(c); | |||
case 1 : | |||
return getG(c); | |||
case 2 : | |||
return getB(c); | |||
default: | |||
return 0; | |||
} | |||
} | |||
// normalized versions | |||
final float getNR(color c) { | |||
return r255[(c & 0xff0000) >> 16]; | |||
} | |||
final float getNG(color c) { | |||
return r255[(c & 0xff00) >> 8]; | |||
} | |||
final float getNB(color c) { | |||
return r255[c & 0xff]; | |||
} | |||
final float getNLuma(color c) { | |||
return r255[getLuma(c)]; | |||
} | |||
color blendRGB(color c, int r, int g, int b) { | |||
return (c & 0xff000000) | (constrain(r, 0, 255) << 16) | (constrain(g, 0, 255) << 8 ) | constrain(b, 0, 255); | |||
} | |||
color blendRGB(color c, float r, float g, float b) { | |||
return blendRGB(c, (int)(r*255), (int)(g*255), (int)(b*255)); | |||
} | |||
/************** | |||
* Greyscale | |||
**************/ | |||
color tofromGS(color c) { | |||
int l = getLuma(c); | |||
return blendRGB(c, l, l, l); | |||
} | |||
/************** | |||
* YUV | |||
**************/ | |||
final static float Umax = 0.436 * 255.0; | |||
final static float Vmax = 0.615 * 255.0; | |||
color toYUV(color c) { | |||
int R = getR(c); | |||
int G = getG(c); | |||
int B = getB(c); | |||
int Y = (int)( 0.299*R+0.587*G+0.114*B); | |||
int U = (int)map(-0.14713*R-0.28886*G+0.436*B,-Umax,Umax,0,255); | |||
int V = (int)map(0.615*R-0.51499*G-0.10001*B,-Vmax,Vmax,0,255); | |||
return blendRGB(c, Y, U, V); | |||
} | |||
color fromYUV(color c) { | |||
int Y = getR(c); | |||
float U = map(getG(c),0,255,-Umax,Umax); | |||
float V = map(getB(c),0,255,-Vmax,Vmax); | |||
int R = (int)(Y + 1.13983*V); | |||
int G = (int)(Y - 0.39465*U - 0.58060*V); | |||
int B = (int)(Y + 2.03211*U); | |||
return blendRGB(c, R, G, B); | |||
} | |||
/************** | |||
* YDbDr | |||
**************/ | |||
color toYDbDr(color c) { | |||
int R = getR(c); | |||
int G = getG(c); | |||
int B = getB(c); | |||
int Y = (int)( 0.299*R+0.587*G+0.114*B); | |||
int Db = (int)(127.5+(-0.450*R-0.883*G+1.333*B)/2.666); | |||
int Dr = (int)(127.5+(-1.333*R+1.116*G+0.217*B)/2.666); | |||
return blendRGB(c, Y, Db, Dr); | |||
} | |||
color fromYDbDr(color c) { | |||
int Y = getR(c); | |||
float Db = (getG(c)-127.5)*2.666; | |||
float Dr = (getB(c)-127.5)*2.666; | |||
int R = (int)(Y + 9.2303716147657e-05*Db-0.52591263066186533*Dr); | |||
int G = (int)(Y - 0.12913289889050927*Db+0.26789932820759876*Dr); | |||
int B = (int)(Y + 0.66467905997895482*Db-7.9202543533108e-05*Dr); | |||
return blendRGB(c, R, G, B); | |||
} | |||
/************** | |||
* YCbCr | |||
**************/ | |||
color toYCbCr(color c) { | |||
int R = getR(c); | |||
int G = getG(c); | |||
int B = getB(c); | |||
int Y = (int)( 0.2988390*R+0.5868110*G+0.1143500*B); | |||
int Cb = (int)(-0.168736*R-0.3312640*G+0.5000000*B+127.5); | |||
int Cr = (int)( 0.5000000*R-0.4186880*G-0.0813120*B+127.5); | |||
return blendRGB(c, Y, Cb, Cr); | |||
} | |||
color fromYCbCr(color c) { | |||
int Y = getR(c); | |||
float Cb = getG(c) - 127.5; | |||
float Cr = getB(c) - 127.5; | |||
int R = (int)(Y + 1.402*Cr)+1; // some fix | |||
int G = (int)(Y-0.344136*Cb-0.714136*Cr); | |||
int B = (int)(Y+1.772000*Cb)+1; // some fix | |||
return blendRGB(c, R, G, B); | |||
} | |||
/************** | |||
* YPbPr | |||
**************/ | |||
color toYPbPr(color c) { | |||
int R = getR(c); | |||
int B = getB(c); | |||
int Y = getLuma(c); | |||
int Pb = B - Y; | |||
int Pr = R - Y; | |||
if(Pb<0) Pb+=256; | |||
if(Pr<0) Pr+=256; | |||
return blendRGB(c, Y, Pb, Pr); | |||
} | |||
color fromYPbPr(color c) { | |||
int Y = getR(c); | |||
int B = getG(c) + Y; | |||
int R = getB(c) + Y; | |||
if(R>255) R-=256; | |||
if(B>255) B-=256; | |||
int G = (int)((Y-0.2126*R-0.0722*B)/0.7152); | |||
return blendRGB(c, R, G, B); | |||
} | |||
/************** | |||
* R-G,G,B-G | |||
**************/ | |||
color toRGGBG(color c) { | |||
int G = getG(c); | |||
int R = getR(c)-G; | |||
int B = getB(c)-G; | |||
if(R<0) R+=256; | |||
if(B<0) B+=256; | |||
return blendRGB(c, R, G, B); | |||
} | |||
color fromRGGBG(color c) { | |||
int G = getG(c); | |||
int R = getR(c)+G; | |||
int B = getB(c)+G; | |||
if(R>255) R-=256; | |||
if(B>255) B-=256; | |||
return blendRGB(c, R, G, B); | |||
} | |||
/************** | |||
* HWB | |||
**************/ | |||
color toHSB(color c) { | |||
int R = getR(c); | |||
int G = getG(c); | |||
int B = getB(c); | |||
int _min = min(R, G, B); | |||
int _max = max(R, G, B); | |||
float delta = _max-_min; | |||
float saturation = delta/_max; | |||
float brightness = r255[_max]; | |||
if (delta == 0.0) return blendRGB(c, 0.0, saturation, brightness); | |||
float hue = 0; | |||
if (R == _max) hue = (G-B)/delta; | |||
else if (G == _max) hue = 2.0 + (B-R)/delta; | |||
else hue = 4.0 + (R-G)/delta; | |||
hue /= 6.0; | |||
if (hue < 0.0) hue += 1.0; | |||
return blendRGB(c, hue, saturation, brightness); | |||
} | |||
color fromHSB(color c) { | |||
float S = getNG(c); | |||
float B = getNB(c); | |||
if (S == 0.0) return blendRGB(c, B, B, B); | |||
float h = 6.0 * getNR(c); | |||
float f = h-floor(h); | |||
float p = B*(1.0-S); | |||
float q = B*(1.0-S*f); | |||
float t = B*(1.0-(S*(1.0-f))); | |||
float r, g, b; | |||
switch((int)h) { | |||
case 1: | |||
r=q; | |||
g=B; | |||
b=p; | |||
break; | |||
case 2: | |||
r=p; | |||
g=B; | |||
b=t; | |||
break; | |||
case 3: | |||
r=p; | |||
g=q; | |||
b=B; | |||
break; | |||
case 4: | |||
r=t; | |||
g=p; | |||
b=B; | |||
break; | |||
case 5: | |||
r=B; | |||
g=p; | |||
b=q; | |||
break; | |||
default: | |||
r=B; | |||
g=t; | |||
b=p; | |||
break; | |||
} | |||
return blendRGB(c, r, g, b); | |||
} | |||
/************** | |||
* HWB | |||
**************/ | |||
color toHWB(color c) { | |||
int R = getR(c); | |||
int G = getG(c); | |||
int B = getB(c); | |||
int w = min(R, G, B); | |||
int v = max(R, G, B); | |||
int hue; | |||
if (v == w) hue = 255; | |||
else { | |||
float f = ((R == w) ? G-B : ((G == w) ? B-R : R-G)); | |||
float p = (R == w) ? 3.0 : ((G == w) ? 5.0 : 1.0); | |||
hue = (int)map((p-f/(v-w))/6.0, 0, 1, 0, 254); | |||
} | |||
return blendRGB(c, hue, w, 255-v); | |||
} | |||
color fromHWB(color c) { | |||
int H = getR(c); | |||
int B = 255-getB(c); | |||
if (H == 255) return blendRGB(c, B, B, B); | |||
else { | |||
float hue = map(H, 0, 254, 0, 6); | |||
float v = r255[B]; | |||
float whiteness = getNG(c); | |||
int i = (int)floor(hue); | |||
float f = hue-i; | |||
if ((i&0x01)!= 0) f=1.0-f; | |||
float n = whiteness+f*(v-whiteness); | |||
float r, g, b; | |||
switch(i) { | |||
case 1: | |||
r=n; | |||
g=v; | |||
b=whiteness; | |||
break; | |||
case 2: | |||
r=whiteness; | |||
g=v; | |||
b=n; | |||
break; | |||
case 3: | |||
r=whiteness; | |||
g=n; | |||
b=v; | |||
break; | |||
case 4: | |||
r=n; | |||
g=whiteness; | |||
b=v; | |||
break; | |||
case 5: | |||
r=v; | |||
g=whiteness; | |||
b=n; | |||
break; | |||
default: | |||
r=v; | |||
g=n; | |||
b=whiteness; | |||
break; | |||
} | |||
return blendRGB(c, r, g, b); | |||
} | |||
} | |||
/************** | |||
* Lab | |||
**************/ | |||
final static float D65X=0.950456; | |||
final static float D65Y=1.0; | |||
final static float D65Z=1.088754; | |||
final static float CIEEpsilon=(216.0/24389.0); | |||
final static float CIEK=(24389.0/27.0); | |||
final static float CIEK2epsilon = CIEK * CIEEpsilon; | |||
final static float D65FX_4 = 4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z); | |||
final static float D65FY_9 = 9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z); | |||
final static float RANGE_X = 100.0 * (0.4124+0.3576+0.1805); | |||
final static float RANGE_Y = 100.0; | |||
final static float RANGE_Z = 100.0 * (0.0193+0.1192+0.9505); | |||
final static float mepsilon = 1.0e-10; | |||
final static float corrratio = 1.0/2.4; | |||
final static float One_Third = 1.0/3.0; | |||
final static float one_hsixteen = 1.0/116.0; | |||
color toLAB(color c) { | |||
PVector xyz = _toXYZ(getNR(c), getNG(c), getNB(c)); | |||
xyz.div(100.0); | |||
xyz.x /= D65X; | |||
xyz.y /= D65Y; | |||
xyz.z /= D65Z; | |||
float x, y, z; | |||
if (xyz.x > CIEEpsilon) { | |||
x = pow(xyz.x, One_Third); | |||
} else { | |||
x= (CIEK*xyz.x+16.0)*one_hsixteen; | |||
} | |||
if (xyz.y > CIEEpsilon) { | |||
y = pow(xyz.y, One_Third); | |||
} else { | |||
y = (CIEK*xyz.y+16.0)*one_hsixteen; | |||
} | |||
if (xyz.z > CIEEpsilon) { | |||
z = pow(xyz.z, One_Third); | |||
} else { | |||
z = (CIEK*xyz.z+16.0)*one_hsixteen; | |||
} | |||
float L = 255.0*(((116.0*y)-16.0)*0.01); | |||
float a = 255.0*(0.5*(x-y)+0.5); | |||
float b = 255.0*(0.5*(y-z)+0.5); | |||
return blendRGB(c, round(L), round(a), round(b)); | |||
} | |||
color fromLAB(color c) { | |||
float L = 100*getNR(c); | |||
float a = getNG(c)-0.5; | |||
float b = getNB(c)-0.5; | |||
float y = (L+16.0)*one_hsixteen; | |||
float x = y+a; | |||
float z = y-b; | |||
float xxx=x*x*x; | |||
if (xxx>CIEEpsilon) { | |||
x = xxx; | |||
} else { | |||
x = (116.0*x-16.0)/CIEK; | |||
} | |||
float yyy=y*y*y; | |||
if (yyy>CIEEpsilon) { | |||
y = yyy; | |||
} else { | |||
y = L/CIEK; | |||
} | |||
float zzz=z*z*z; | |||
if (zzz>CIEEpsilon) { | |||
z = zzz; | |||
} else { | |||
z = (116.0*z-16.0)/CIEK; | |||
} | |||
return _fromXYZ(c, RANGE_X*x, RANGE_Y*y, RANGE_Z*z); | |||
} | |||
/************** | |||
* Luv | |||
**************/ | |||
final float PerceptibleReciprocal(float x) { | |||
float sgn = x < 0.0 ? -1.0 : 1.0; | |||
if ((sgn * x) >= mepsilon) return (1.0 / x); | |||
return (sgn/mepsilon); | |||
} | |||
color toLUV(color c) { | |||
PVector xyz = _toXYZ(getNR(c), getNG(c), getNB(c)); | |||
xyz.div(100.0); | |||
float d = xyz.y; // / D65Y; | |||
float L; | |||
if (d > CIEEpsilon) L = 116.0*pow(d, One_Third)-16.0; | |||
else L = CIEK * d; | |||
float alpha = PerceptibleReciprocal(xyz.x + 15.0 * xyz.y + 3.0 * xyz.z); | |||
float L13 = 13.0 * L; | |||
float u = L13 * ((4.0 * alpha * xyz.x)-D65FX_4); | |||
float v = L13 * ((9.0 * alpha * xyz.y)-D65FY_9); | |||
L /= 100.0; | |||
u=(u+134.0)/354.0; | |||
v=(v+140.0)/262.0; | |||
return blendRGB(c, round(L*255), round(u*255), round(v*255)); | |||
} | |||
color fromLUV(color c) { | |||
float L = 100.0*getNR(c); | |||
float u = 354.0*getNG(c)-134.0; | |||
float v = 262.0*getNB(c)-140.0; | |||
float X, Y, Z; | |||
if (L > CIEK2epsilon) Y = pow((L+16.0)*one_hsixteen, 3.0); | |||
else Y = L/CIEK; | |||
float L13 = 13.0*L; | |||
float L52 = 52.0*L; | |||
float Y5 = 5.0*Y; | |||
float L13u = L52/(u+L13*D65FX_4); | |||
X=((Y*((39.0*L/(v+L13*D65FY_9))-5.0))+Y5)/((((L13u)-1.0)/3.0)+One_Third); | |||
Z=(X*(((L13u)-1.0)/3.0))-Y5; | |||
return _fromXYZ(c, 100*X, 100*Y, 100*Z); | |||
} | |||
/************** | |||
* HCL | |||
**************/ | |||
color toHCL(color c) { | |||
float r = getNR(c); | |||
float g = getNG(c); | |||
float b = getNB(c); | |||
float max = max(r, max(g, b)); | |||
float chr = max - min(r, min(g, b)); | |||
float h = 0.0; | |||
if ( chr != 0) { | |||
if (r == max) { | |||
h = ((g-b)/chr+6.0) % 6.0; | |||
} else if (g == max) { | |||
h = (b-r)/chr + 2.0; | |||
} else { | |||
h = (r-g)/chr + 4.0; | |||
} | |||
} | |||
return blendRGB(c, round((h/6.0)*255), round(chr*255), round(255*(0.298839*r+0.586811*g+0.114350*b))); | |||
} | |||
color fromHCL(color c) { | |||
float h = 6.0*getNR(c); | |||
float chr = getNG(c); | |||
float l = getNB(c); | |||
float x = chr*(1.0-abs((h%2.0)-1.0)); | |||
float r = 0.0; | |||
float g = 0.0; | |||
float b = 0.0; | |||
if ((0.0 <= h) && (h < 1.0)) { | |||
r=chr; | |||
g=x; | |||
} else if ((1.0 <= h) && (h < 2.0)) { | |||
r=x; | |||
g=chr; | |||
} else if ((2.0 <= h) && (h < 3.0)) { | |||
g=chr; | |||
b=x; | |||
} else if ((3.0 <= h) && (h < 4.0)) { | |||
g=x; | |||
b=chr; | |||
} else if ((4.0 <= h) && (h < 5.0)) { | |||
r=x; | |||
b=chr; | |||
} else {//if ((5.0 <= h) && (h < 6.0)) { | |||
r=chr; | |||
b=x; | |||
} | |||
float m = l - (0.298839*r+0.586811*g+0.114350*b); | |||
return blendRGB(c, round(255*(r+m)), round(255*(g+m)), round(255*(b+m))); | |||
} | |||
/************** | |||
* Yxy | |||
**************/ | |||
color toYXY(color c) { | |||
PVector xyz = _toXYZ(getNR(c), getNG(c), getNB(c)); | |||
float sum = xyz.x + xyz.y + xyz.z; | |||
float x = xyz.x > 0 ? xyz.x / sum : 0.0; | |||
float y = xyz.y > 0 ? xyz.y / sum : 0.0; | |||
return blendRGB(c, | |||
(int)map(xyz.y, 0, RANGE_Y, 0, 255), | |||
(int)map(x, 0.0, 1.0, 0, 255), | |||
(int)map(y, 0.0, 1.0, 0, 255)); | |||
} | |||
color fromYXY(color c) { | |||
float Y = map(getR(c), 0, 255, 0, RANGE_Y); | |||
float x = map(getG(c), 0, 255, 0, 1.0); | |||
float y = map(getB(c), 0, 255, 0, 1.0); | |||
float divy = Y / (y>0 ? y : 1.0e-6); | |||
return _fromXYZ(c, x * divy, Y, (1-x-y)*divy); | |||
} | |||
/************** | |||
* XYZ | |||
**************/ | |||
// FIXME: range from 0 to 1 | |||
float correctionxyz(float n) { | |||
return (n > 0.04045 ? pow((n + 0.055) / 1.055, 2.4) : n / 12.92) * 100.0; | |||
} | |||
PVector _toXYZ(float rr, float gg, float bb) { | |||
float r = correctionxyz(rr); | |||
float g = correctionxyz(gg); | |||
float b = correctionxyz(bb); | |||
return new PVector(r * 0.4124 + g * 0.3576 + b * 0.1805, | |||
r * 0.2126 + g * 0.7152 + b * 0.0722, | |||
r * 0.0193 + g * 0.1192 + b * 0.9505); | |||
} | |||
color toXYZ(color c) { | |||
PVector xyz = _toXYZ(getNR(c), getNG(c), getNB(c)); | |||
return blendRGB(c, | |||
(int)map(xyz.x, 0, RANGE_X, 0, 255), | |||
(int)map(xyz.y, 0, RANGE_Y, 0, 255), | |||
(int)map(xyz.z, 0, RANGE_Z, 0, 255)); | |||
} | |||
float recorrectionxyz(float n) { | |||
return n > 0.0031308 ? 1.055 * pow(n, corrratio) - 0.055 : 12.92 * n; | |||
} | |||
// FIXME: range from 0 to 1 | |||
color _fromXYZ(color c, float xx, float yy, float zz) { | |||
float x = xx/100.0; | |||
float y = yy/100.0; | |||
float z = zz/100.0; | |||
int r = round(255.0*recorrectionxyz(x * 3.2406 + y * -1.5372 + z * -0.4986)); | |||
int g = round(255.0*recorrectionxyz(x * -0.9689 + y * 1.8758 + z * 0.0415)); | |||
int b = round(255.0*recorrectionxyz(x * 0.0557 + y * -0.2040 + z * 1.0570)); | |||
return blendRGB(c, r, g, b); | |||
} | |||
color fromXYZ(color c) { | |||
float x = map(getR(c), 0, 255, 0, RANGE_X); | |||
float y = map(getG(c), 0, 255, 0, RANGE_Y); | |||
float z = map(getB(c), 0, 255, 0, RANGE_Z); | |||
return _fromXYZ(c, x, y, z); | |||
} | |||
/************** | |||
* CMY | |||
**************/ | |||
color toCMY(color c) { | |||
return blendRGB(c, 255-getR(c), 255-getG(c), 255-getB(c)); | |||
} | |||
color fromCMY(color c) { | |||
return toCMY(c); | |||
} | |||
/************** | |||
* OHTA | |||
**************/ | |||
color fromOHTA(color c) { | |||
int I1 = getR(c); | |||
float I2 = map(getG(c), 0, 255, -127.5, 127.5); | |||
float I3 = map(getB(c), 0, 255, -127.5, 127.5); | |||
int R = (int)(I1+1.00000*I2-0.66668*I3); | |||
int G = (int)(I1+1.33333*I3); | |||
int B = (int)(I1-1.00000*I2-0.66668*I3); | |||
return blendRGB(c, R, G, B); | |||
} | |||
color toOHTA(color c) { | |||
int R = getR(c); | |||
int G = getG(c); | |||
int B = getB(c); | |||
int I1 = (int)(0.33333*R+0.33334*G+0.33333*B); | |||
int I2 = (int)map(0.5*(R-B), -127.5, 127.5, 0, 255); | |||
int I3 = (int)map(-0.25000*R+0.50000*G-0.25000*B, -127.5, 127.5, 0, 255); | |||
return blendRGB(c, I1, I2, I3); | |||
} | |||
//// | |||
// 1/n table for n=0..255 - to speed up color conversions things | |||
final static float[] r255 = { | |||
0.0, 0.003921569, 0.007843138, 0.011764706, 0.015686275, 0.019607844, 0.023529412, 0.02745098, 0.03137255, 0.03529412, 0.039215688, | |||
0.043137256, 0.047058824, 0.050980393, 0.05490196, 0.05882353, 0.0627451, 0.06666667, 0.07058824, 0.07450981, 0.078431375, 0.08235294, | |||
0.08627451, 0.09019608, 0.09411765, 0.09803922, 0.101960786, 0.105882354, 0.10980392, 0.11372549, 0.11764706, 0.12156863, 0.1254902, | |||
0.12941177, 0.13333334, 0.13725491, 0.14117648, 0.14509805, 0.14901961, 0.15294118, 0.15686275, 0.16078432, 0.16470589, 0.16862746, | |||
0.17254902, 0.1764706, 0.18039216, 0.18431373, 0.1882353, 0.19215687, 0.19607843, 0.2, 0.20392157, 0.20784314, 0.21176471, 0.21568628, | |||
0.21960784, 0.22352941, 0.22745098, 0.23137255, 0.23529412, 0.23921569, 0.24313726, 0.24705882, 0.2509804, 0.25490198, 0.25882354, | |||
0.2627451, 0.26666668, 0.27058825, 0.27450982, 0.2784314, 0.28235295, 0.28627452, 0.2901961, 0.29411766, 0.29803923, 0.3019608, 0.30588236, | |||
0.30980393, 0.3137255, 0.31764707, 0.32156864, 0.3254902, 0.32941177, 0.33333334, 0.3372549, 0.34117648, 0.34509805, 0.34901962, 0.3529412, | |||
0.35686275, 0.36078432, 0.3647059, 0.36862746, 0.37254903, 0.3764706, 0.38039216, 0.38431373, 0.3882353, 0.39215687, 0.39607844, 0.4, | |||
0.40392157, 0.40784314, 0.4117647, 0.41568628, 0.41960785, 0.42352942, 0.42745098, 0.43137255, 0.43529412, 0.4392157, 0.44313726, | |||
0.44705883, 0.4509804, 0.45490196, 0.45882353, 0.4627451, 0.46666667, 0.47058824, 0.4745098, 0.47843137, 0.48235294, 0.4862745, 0.49019608, | |||
0.49411765, 0.49803922, 0.5019608, 0.5058824, 0.50980395, 0.5137255, 0.5176471, 0.52156866, 0.5254902, 0.5294118, 0.53333336, 0.5372549, | |||
0.5411765, 0.54509807, 0.54901963, 0.5529412, 0.5568628, 0.56078434, 0.5647059, 0.5686275, 0.57254905, 0.5764706, 0.5803922, 0.58431375, | |||
0.5882353, 0.5921569, 0.59607846, 0.6, 0.6039216, 0.60784316, 0.6117647, 0.6156863, 0.61960787, 0.62352943, 0.627451, 0.6313726, 0.63529414, | |||
0.6392157, 0.6431373, 0.64705884, 0.6509804, 0.654902, 0.65882355, 0.6627451, 0.6666667, 0.67058825, 0.6745098, 0.6784314, 0.68235296, | |||
0.6862745, 0.6901961, 0.69411767, 0.69803923, 0.7019608, 0.7058824, 0.70980394, 0.7137255, 0.7176471, 0.72156864, 0.7254902, 0.7294118, | |||
0.73333335, 0.7372549, 0.7411765, 0.74509805, 0.7490196, 0.7529412, 0.75686276, 0.7607843, 0.7647059, 0.76862746, 0.77254903, 0.7764706, | |||
0.78039217, 0.78431374, 0.7882353, 0.7921569, 0.79607844, 0.8, 0.8039216, 0.80784315, 0.8117647, 0.8156863, 0.81960785, 0.8235294, 0.827451, | |||
0.83137256, 0.8352941, 0.8392157, 0.84313726, 0.84705883, 0.8509804, 0.85490197, 0.85882354, 0.8627451, 0.8666667, 0.87058824, 0.8745098, | |||
0.8784314, 0.88235295, 0.8862745, 0.8901961, 0.89411765, 0.8980392, 0.9019608, 0.90588236, 0.9098039, 0.9137255, 0.91764706, 0.92156863, | |||
0.9254902, 0.92941177, 0.93333334, 0.9372549, 0.9411765, 0.94509804, 0.9490196, 0.9529412, 0.95686275, 0.9607843, 0.9647059, 0.96862745, | |||
0.972549, 0.9764706, 0.98039216, 0.9843137, 0.9882353, 0.99215686, 0.99607843, 1.0 | |||
}; |
@@ -0,0 +1,2 @@ | |||
//globals | |||
uptime = 116617879 |
@@ -0,0 +1,47 @@ | |||
ffmpeg version 3.4.8-0ubuntu0.2 Copyright (c) 2000-2020 the FFmpeg developers | |||
built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04) | |||
configuration: --prefix=/usr --extra-version=0ubuntu0.2 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared | |||
WARNING: library configuration mismatch | |||
avcodec configuration: --prefix=/usr --extra-version=0ubuntu0.2 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared --enable-version3 --disable-doc --disable-programs --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libtesseract --enable-libvo_amrwbenc | |||
libavutil 55. 78.100 / 55. 78.100 | |||
libavcodec 57.107.100 / 57.107.100 | |||
libavformat 57. 83.100 / 57. 83.100 | |||
libavdevice 57. 10.100 / 57. 10.100 | |||
libavfilter 6.107.100 / 6.107.100 | |||
libavresample 3. 7. 0 / 3. 7. 0 | |||
libswscale 4. 8.100 / 4. 8.100 | |||
libswresample 2. 9.100 / 2. 9.100 | |||
libpostproc 54. 7.100 / 54. 7.100 | |||
Input #0, rawvideo, from 'pipe:': | |||
Duration: N/A, start: 0.000000, bitrate: 88957 kb/s | |||
Stream #0:0: Video: rawvideo (RGB[24] / 0x18424752), rgb24, 468x264, 88957 kb/s, 30 tbr, 30 tbn, 30 tbc | |||
Stream mapping: | |||
Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264)) | |||
[swscaler @ 0x562d1e168ac0] Warning: data is not aligned! This can lead to a speed loss | |||
[libx264 @ 0x562d1e156d20] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 | |||
[libx264 @ 0x562d1e156d20] profile High 4:4:4 Predictive, level 2.1, 4:2:0 8-bit | |||
[libx264 @ 0x562d1e156d20] 264 - core 152 r2854 e9a5903 - H.264/MPEG-4 AVC codec - Copyleft 2003-2017 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x1:0x111 me=hex subme=7 psy=0 mixed_ref=1 me_range=16 chroma_me=1 trellis=0 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=0 chroma_qp_offset=0 threads=8 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc=cqp mbtree=0 qp=0 | |||
Output #0, mp4, to '/media/giers/projekte/Gerkzeuk/gerkzeuk2/gerkzeuk2_p5_0001/data/videos/116618113.mp4': | |||
Metadata: | |||
comment : Made with Video Export for Processing - https://git.io/vAXLk | |||
encoder : Lavf57.83.100 | |||
Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 468x264, q=-1--1, 30 fps, 15360 tbn, 30 tbc | |||
Metadata: | |||
encoder : Lavc57.107.100 libx264 | |||
Side data: | |||
cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1 | |||
frame= 17 fps=0.0 q=0.0 size= 256kB time=00:00:00.23 bitrate=8986.9kbits/s speed=0.438x frame= 33 fps= 32 q=0.0 size= 1280kB time=00:00:00.76 bitrate=13676.4kbits/s speed=0.733x frame= 49 fps= 31 q=0.0 size= 1792kB time=00:00:01.30 bitrate=11292.1kbits/s speed=0.824x frame= 53 fps= 30 q=-1.0 Lsize= 2709kB time=00:00:01.73 bitrate=12804.1kbits/s speed=0.973x | |||
video:2708kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.041469% | |||
[libx264 @ 0x562d1e156d20] frame I:2 Avg QP: 0.00 size: 80171 | |||
[libx264 @ 0x562d1e156d20] frame P:51 Avg QP: 0.00 size: 51222 | |||
[libx264 @ 0x562d1e156d20] mb I I16..4: 26.1% 0.0% 73.9% | |||
[libx264 @ 0x562d1e156d20] mb P I16..4: 13.7% 0.0% 14.2% P16..4: 20.1% 18.3% 13.0% 0.0% 0.0% skip:20.7% | |||
[libx264 @ 0x562d1e156d20] 8x8 transform intra:0.0% inter:55.0% | |||
[libx264 @ 0x562d1e156d20] coded y,uvDC,uvAC intra: 93.2% 96.6% 96.4% inter: 68.7% 70.2% 70.1% | |||
[libx264 @ 0x562d1e156d20] i16 v,h,dc,p: 85% 14% 1% 0% | |||
[libx264 @ 0x562d1e156d20] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 62% 22% 3% 2% 2% 2% 2% 3% 2% | |||
[libx264 @ 0x562d1e156d20] i8c dc,h,v,p: 4% 27% 69% 0% | |||
[libx264 @ 0x562d1e156d20] Weighted P-Frames: Y:0.0% UV:0.0% | |||
[libx264 @ 0x562d1e156d20] ref P L0: 62.1% 11.1% 17.6% 9.3% | |||
[libx264 @ 0x562d1e156d20] kb/s:12555.43 | |||
Exiting normally, received signal 15. |
@@ -0,0 +1,48 @@ | |||
class FX { | |||
//img in and out | |||
Shader shader; | |||
String[] params; // IS THIS NECESSARY? I DOUBT IT | |||
FX(Shader shader_) { | |||
shader = shader_; | |||
} | |||
} | |||
FXManager fxManager = new FXManager(); | |||
class FXManager { | |||
ArrayList<FX> fxList = new ArrayList<FX>(); | |||
void addFx(Shader shader) { | |||
this.fxList.add(new FX(shader)); | |||
println("Added " + shader + " to fxList at spot. List length: " + this.fxList.size()); | |||
} | |||
void addFx(Shader shader, int pos) { | |||
fxList.add(new FX(shader)); | |||
swapFx(this.fxList.size(), pos); | |||
println("Added " + shader + " to fxList at spot. List length: " + this.fxList.size()); | |||
} | |||
void swapFx(int pos1, int pos2) { | |||
if (pos1 >= 0 && pos2 < this.fxList.size()) Collections.swap(fxList, pos1, pos2); | |||
} | |||
void removeFx(int pos) { | |||
if (pos >= 0 && this.fxList.size() > pos) this.fxList.remove(pos); | |||
} | |||
void run(boolean animate, boolean apply) { | |||
for (int i = 0; i < fxManager.fxList.size(); i++) { | |||
if (animate) { | |||
for (int j = 0; j < this.fxList.get(i).shader.params.size(); j++) { | |||
if (this.fxList.get(i).shader.params.get(j).animating) { | |||
this.fxList.get(i).shader.params.get(j).animate(); | |||
} | |||
} | |||
} | |||
if (apply) this.fxList.get(i).shader.apply(); | |||
if (i > maxFx) break; | |||
} | |||
} | |||
} |
@@ -0,0 +1,155 @@ | |||
import drop.*; | |||
import test.*; | |||
import java.util.*; | |||
import processing.net.*; | |||
import java.awt.event.KeyEvent; | |||
import java.awt.event.KeyListener; | |||
import processing.video.*; | |||
import com.hamoid.*; | |||
VideoExport videoExport; | |||
boolean greenBackground = false; //else: black | |||
boolean roundMask = false; // show a circle | |||
boolean drawGUI = true; //draws fx-informations | |||
int mode = 1; //0: webcam, 1: image | |||
boolean harvester = true; | |||
int maxFx = 5; //possible amount of effect layers | |||
int frameRate = 30; | |||
int fpm = frameRate * 60; | |||
int bpm = 128; | |||
SDrop drop; | |||
PImage source; | |||
PGraphics renderer; | |||
PImage viewport; | |||
SourceManager sourceManager; | |||
PImage roundMaskImage; | |||
PGraphics roundMaskGraphics; | |||
String frameName; //to save frame as image | |||
float uptime; //logs how many frames this software has rendered before (inaccurate, it's actually way, way more) | |||
boolean recording; //save every frame? | |||
int renderSize = 500; //px | |||
String[] saveData; | |||
int w, h; | |||
void setup() { | |||
size(640, 800); | |||
w = width; | |||
h = height; | |||
surface.setResizable(true); | |||
frameRate(frameRate); | |||
noSmooth(); //saves resources but makes sum look shiddy | |||
drop = new SDrop(this); | |||
saveData = loadStrings(dataPath("saves.sav")); | |||
println("Loading Savefile..."); | |||
for (int i = 0; i < saveData.length; i ++) { | |||
float[] temp; | |||
if (saveData[i].contains("uptime")) { | |||
temp = float(split(saveData[i], " = ")); | |||
println("Uptime: " + temp[1]); | |||
uptime = temp[1]; | |||
} | |||
} | |||
fallbackImage = loadImage(dataPath("0.png")); | |||
/* | |||
String[] cameras = Capture.list(); | |||
if (cameras == null || cameras.length == 0) { | |||
println(cameras == null ? "Failed to retrieve the list of available cameras." : "There are no cameras available for capture."); | |||
if (mode == 0) { | |||
println("Switching to image mode"); | |||
mode = 1; | |||
} | |||
} else { | |||
println("Available cameras:"); | |||
printArray(cameras); | |||
cam = new Capture(this, cameras[0]); | |||
cam.start(); | |||
} | |||
*/ | |||
composiorServer = new Server(this, port); // 10002 | |||
renderer = createGraphics(width, height); | |||
viewport = createImage(renderer.width, renderer.height, ARGB); | |||
roundMaskGraphics = createGraphics(renderer.width, renderer.height); | |||
sourceManager = new SourceManager(); | |||
masksRender = new PImage[masksRenderAmount]; | |||
sobel = new SobelEdgeDetection(); | |||
sourceManager.importURI("/home/giers/.local/bin/fast-style-transfer/data/train2014"); | |||
//sourceManager.importURI(dataPath("")); | |||
} | |||
void draw() { | |||
updateServer(); | |||
sourceManager.update(); //will write some image to the renderer | |||
sourceManager.setSource(); | |||
fxManager.run(true, true); //boolean animate (iterative calcs), boolean apply (draw) | |||
render(); | |||
background(greenBackground ? color(0, 255, 0) : color(0)); | |||
imageMode(CENTER); | |||
viewport = renderer.get(); | |||
if (renderer.width < renderer.height) { | |||
viewport.resize(0, height); | |||
if (viewport.width > width) viewport.resize(width, 0); | |||
} else { | |||
viewport.resize(width, 0); | |||
if (viewport.height > height) viewport.resize(0, height); | |||
} | |||
if (roundMask) { | |||
roundMaskGraphics.setSize(viewport.width, viewport.height); | |||
roundMaskGraphics.beginDraw(); | |||
roundMaskGraphics.noStroke(); | |||
roundMaskGraphics.background(0); | |||
roundMaskGraphics.fill(255); | |||
roundMaskGraphics.ellipse(viewport.width/2, viewport.height/2, min(viewport.width, viewport.height), min(viewport.width, viewport.height)); | |||
roundMaskGraphics.endDraw(); | |||
roundMaskImage = roundMaskGraphics.get(); | |||
viewport.mask(roundMaskImage); | |||
} | |||
//sourceManager.setSource(); | |||
//viewport = getEdges(viewport); | |||
//viewport = cannyEdge(viewport); | |||
image(viewport, width/2, height/2); | |||
if (videoRecord) { | |||
videoExport.saveFrame(); | |||
fill(#ff0000); | |||
ellipse(width-100,height-100,30,30); | |||
} | |||
if (drawGUI) drawGUI(guiOffsetTop); | |||
if (recording) { | |||
snapshot(); | |||
if (airisRendering) { | |||
airisRendering = false; | |||
recording = previousRecordState; | |||
renderSize = previousRenderSize; | |||
println("i rendered something big, oops"); | |||
} | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
/* | |||
artifactUri — the original artwork digital file. | |||
displayUri — a smaller-scale version of the artwork used for the HEN website feed. | |||
thumbnailUri — currently, this points to the same image for all of the artwork on HEN. | |||
{ | |||
"name": "HEN-Mesh", | |||
"description": "Mesh design of the HicEtNunc logo", | |||
"tags": [ | |||
"CG", | |||
"3D", | |||
"B3D", | |||
"GEO", | |||
"WIREFRAME", | |||
"B&W", | |||
"COMPLEX" | |||
], | |||
"symbol": "OBJKT", | |||
"artifactUri": | |||
"ipfs://QmS1r91dZadi4XQ6TuFcUVTUBnhphS7B428YdfETfjs6yL", | |||
"displayUri": | |||
"ipfs://QmXNMJVFtnCiZuLDgRFgoMCLG3JyMZXX4JP8qQ9cKtvG8g", | |||
"thumbnailUri": | |||
"ipfs://QmNrhZHUaEqxhyLfqoq1mtHSipkWHeT31LNHb1QEbDHgnc", | |||
"creators": [ | |||
"tz1XtjZTzEM6EQ3TnUPUQviCD6WfcsZRHXbj" | |||
], | |||
"formats": [ | |||
{ | |||
"uri": | |||
"ipfs://QmS1r91dZadi4XQ6TuFcUVTUBnhphS7B428YdfETfjs6yL", | |||
"mimeType": "image/jpeg" | |||
} | |||
], | |||
"decimals": 0, | |||
"isBooleanAmount": false, | |||
"shouldPreferSymbol": false | |||
} | |||
*/ |
@@ -0,0 +1,136 @@ | |||
import processing.net.*; | |||
int port = 10002; | |||
Server composiorServer; | |||
void updateServer() { | |||
Client thisClient = composiorServer.available(); | |||
if (thisClient != null) { | |||
if (thisClient.available() > 0) { | |||
String msg = thisClient.readString().toString(); | |||
println("Bot reads: " + msg); | |||
String arr[] = msg.split(" "); | |||
String cmd = arr[0]; | |||
String[] params = Arrays.copyOfRange(arr, 1, arr.length); | |||
println(cmd); | |||
switch(cmd) { | |||
case("add"): | |||
switch(params[0]) { | |||
case("darker"): | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new DARKER()); | |||
break; | |||
case("asdfpixelsort"): | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new ASDFPIXELSORT()); | |||
break; | |||
case("auecho"): | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new AUECHO()); | |||
break; | |||
case("brighter"): | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new BRIGHTER()); | |||
break; | |||
case("distorter"): | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new DISTORTER()); | |||
break; | |||
case("grauzone"): | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new GRAUZONE()); | |||
break; | |||
case("slitscan"): | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new SLITSCAN()); | |||
break; | |||
case("wzip"): | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new WZIP()); | |||
break; | |||
default: | |||
break; | |||
} | |||
break; | |||
case("remove"): | |||
if (params[0].equals("last")) { | |||
fxManager.removeFx(fxManager.fxList.size()-1); | |||
} else if (params[0].equals("all")) { | |||
for (int i = 0; i < fxManager.fxList.size(); i++) { | |||
fxManager.removeFx(i); | |||
} | |||
fxManager.removeFx(fxManager.fxList.size()-1); | |||
} else { | |||
fxManager.removeFx(int(params[0])-1); | |||
} | |||
break; | |||
case("swap"): | |||
fxManager.swapFx(int(params[0])-1, int(params[1])-1); | |||
break; | |||
case("play"): | |||
if (fxManager.fxList.size() > int(params[0])-1) { | |||
//fxManager.fxList.get(int(params[0])-1).shader.play(); | |||
} | |||
break; | |||
case("random"): | |||
if (fxManager.fxList.size() > int(params[0])-1) { | |||
for (int j = 0; j < fxManager.fxList.get(int(params[0])-1).shader.params.size(); j++) { | |||
fxManager.fxList.get(int(params[0])-1).shader.params.get(j).randomize(); | |||
} | |||
} | |||
break; | |||
case("pause"): | |||
if (fxManager.fxList.size() > int(params[0])-1) { | |||
//fxManager.fxList.get(int(params[0])-1).shader.pause(); | |||
} | |||
break; | |||
case("render"): | |||
airisRender(5000); | |||
break; | |||
case("set"): | |||
if (fxManager.fxList.size() > int(params[0])-1) { | |||
for (int i = 0; i < params.length; i++) { | |||
if (Arrays.asList(fxManager.fxList.get(int(params[0])-1).shader.getParamNames()).contains(params[i])) { | |||
String attemptedCommand = params[i]; | |||
println(fxManager.fxList.get(int(params[0])-1).shader.paramIdByName(params[i])); | |||
try { | |||
if (isNumeric(params[i+1])) { | |||
attemptedCommand += params[i+1]; | |||
println(attemptedCommand); | |||
if (fxManager.fxList.get(int(params[0])-1).shader.animating) { | |||
//fxManager.fxList.get(int(params[0])-1).shader.pause(); | |||
} | |||
fxManager.fxList.get(int(params[0])-1).shader.params.get(fxManager.fxList.get(int(params[0])-1).shader.paramIdByName(params[i])).setValue(float(params[i+1])); | |||
} | |||
} | |||
catch(Exception e) { | |||
println(e); | |||
println("Error parsing parameters in set"); | |||
} | |||
} | |||
} | |||
/* | |||
println(params); | |||
println(fxManager.fxList.get(int(params[0])-1).shader.commands); | |||
if (Arrays.asList(fxManager.fxList.get(int(params[0])-1).shader.commands).contains(params[1])) { | |||
fxManager.fxList.get(int(params[0])-1).shader.pause(); | |||
fxManager.fxList.get(int(params[0])-1).shader.setValue(params[1], float(params[2])); | |||
} else { | |||
println("Parameter not found " + params[1]); | |||
} | |||
*/ | |||
} | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
public static boolean isNumeric(String strNum) { | |||
if (strNum == null) { | |||
return false; | |||
} | |||
try { | |||
double d = Double.parseDouble(strNum); | |||
} | |||
catch (NumberFormatException nfe) { | |||
return false; | |||
} | |||
return true; | |||
} |
@@ -0,0 +1,114 @@ | |||
//Osci osci, osci_shifted; | |||
final static int SIN = 0; //add 0.25 to phase to get cos | |||
final static int TAN = 1; | |||
final static int LINE = 2; | |||
final static int SQUARE = 3; //switches between -1 and 1, that's all | |||
final static int RAMP = 4; //line for half the sequence up to 1, then stay at 1 for the other half | |||
final static int RAMPUPDOWN = 5; //line up, stay, line down, stay. use this when drawing a square once for x and once for y with a phaseshift of .. what was it.. 0.5 or 0.25. try it | |||
final static int COS = 6; | |||
final static int RANDOM = 7; | |||
final static int INTVAL = 100; | |||
final static int FLOATVAL = 101; | |||
class Osci { //it's a wave generator | |||
float delta; | |||
float beats; | |||
float inc; | |||
boolean playing; | |||
int mode; | |||
int[] modes; | |||
float phaseshift; | |||
float value; | |||
float startFrame; //resets after every playthrough | |||
//color c; | |||
Osci(float beats_, float phaseshift_, int mode_) { //how many beats one cycle takes, the more, the longer. | |||
beats = beats_; | |||
phaseshift = phaseshift_; | |||
inc = phaseshift * TWO_PI; | |||
mode = mode_; | |||
modes = new int[1]; | |||
modes[0] = mode; | |||
start(); | |||
} | |||
/* | |||
Osci(int[] modes_) { //for random | |||
int[] possibleBeats = {1, 2, 4, 8, 16, 32, 64}; | |||
beats = possibleBeats[(int)random(possibleBeats.length)]; | |||
modes = modes_; | |||
phaseshift = (random(1) > .8) ? .25 : 0; | |||
inc = phaseshift * TWO_PI; | |||
mode = modes[0]; | |||
start(); | |||
}*/ | |||
void start() { /// start - reset | |||
delta = (8 * TWO_PI / beats) / ((60 * frameRate) / bpm); | |||
playing = true; | |||
startFrame = frameCount; | |||
} | |||
void stop() { | |||
playing = false; | |||
} | |||
void update() { | |||
if (playing) { | |||
inc += delta; | |||
if (inc > beats*16*TWO_PI) inc -= beats*16*TWO_PI; | |||
switch(mode) { | |||
case(SIN): | |||
value = sin(inc); | |||
break; | |||
case(COS): | |||
value = cos(inc); | |||
break; | |||
case(TAN): | |||
value = tan(inc); | |||
break; | |||
case(LINE): | |||
value = ((inc % TWO_PI)-PI)/PI; | |||
//value = ((inc % (TWO_PI-(TWO_PI*phaseshift)))-PI)/PI*1+2*phaseshift; | |||
//println(inc % TWO_PI); | |||
break; | |||
case(SQUARE): | |||
value = sin(inc+(phaseshift*TWO_PI)) > 0 ? 1 : -1; | |||
break; | |||
case(RAMP): | |||
value = sin(inc) > 0 ? ((inc % TWO_PI)-PI)/PI : 0; | |||
break; | |||
case(RAMPUPDOWN): | |||
if (sin(inc) < -0.666666666) { | |||
value = -0.666666666; | |||
} else if (sin(inc) < 0.666666666 && sin(inc) > -0.666666666) { | |||
value = sin(inc); | |||
} else if (sin(inc) < 1 && sin(inc) > 0.666666666) { | |||
value = 0.666666666; | |||
} | |||
value *= 1.5; | |||
break; | |||
default: | |||
break; | |||
} | |||
value = constrain(value, -1, 1); | |||
if (frameCount > startFrame + (((60 * frameRate) / bpm) * beats) /2) { | |||
value = (mode == RANDOM) ? random(-1, 1) : value; | |||
//println("beat hit. that's " + str(frameCount - startFrame) + " frames since the last beat"); | |||
startFrame += (((60 * frameRate) / bpm) * beats) /2; | |||
onRepeat(); | |||
} | |||
value = map(value, -1, 1, 0, 1); | |||
} | |||
} | |||
void onRepeat() { | |||
//println("beat played.."); | |||
//background(c); | |||
} | |||
/* | |||
void display() { | |||
fill(0); | |||
stroke(2); | |||
strokeWeight(3); | |||
point(width/2, ((value + 1) / 2)* height); | |||
}*/ | |||
} |
@@ -0,0 +1,751 @@ | |||
//"rendering" in terms of "render to disk", not to screen. that is given in draw() | |||
PImage sobelEdgeImg; | |||
PImage sobelEdgeImg2; | |||
PImage cannyEdgeImg; | |||
PImage cannyEdgeImg2; | |||
PGraphics renderFiltered; | |||
PImage[] masksRender; | |||
int masksRenderAmount = 3; //for airis | |||
int masksSize = 1024; | |||
//PImage roundMaskImage; //for obs-studio greenscreenremoval // have the source be in a circle | |||
void render() { | |||
if (airisRendering) { | |||
//render grayscale image | |||
renderFiltered = createGraphics((renderer.width < renderer.height) ? int(map(renderer.width, 0, renderer.height, 0, masksSize)) : masksSize, (renderer.width < renderer.height) ? masksSize : int(map(renderer.height, 0, renderer.width, 0, masksSize))); | |||
renderFiltered.beginDraw(); | |||
renderFiltered.image(renderer, 0, 0, renderFiltered.width, renderFiltered.height); | |||
renderFiltered.endDraw(); | |||
//sobelEdgeImg = sobelEdge(renderFiltered); | |||
//sobelEdgeImg = sobelEdge(sobelEdgeImg); | |||
//sobelEdgeImg.filter(INVERT); //<- best sobel results here | |||
//cannyEdgeImg = cannyEdge(renderFiltered); //better look bellow | |||
renderFiltered.beginDraw(); | |||
renderFiltered.filter(GRAY); | |||
renderFiltered.filter(POSTERIZE, masksRenderAmount); | |||
//renderFiltered. giers PUT A CONTRAST CORRECTION HERE! | |||
renderFiltered.loadPixels(); | |||
renderFiltered.endDraw(); | |||
cannyEdgeImg2 = cannyEdge(renderFiltered); //<- best canny results here | |||
//sobelEdgeImg2 = sobelEdge(renderFiltered); //better look above | |||
//render mask layers | |||
PImage imgRenderFiltered = renderFiltered.get(); | |||
imgRenderFiltered.loadPixels(); | |||
color[] c = new color[masksRender.length]; | |||
int cc = 0; | |||
for (int i = 0; i < renderFiltered.width*renderFiltered.height; i ++) { | |||
boolean exists = false; | |||
for (int j = 0; j < c.length; j++) { | |||
if (color(renderFiltered.pixels[i]) == c[j]) exists = true; | |||
} | |||
if (!exists) { | |||
c[cc] = color(renderFiltered.pixels[i]); | |||
cc++; | |||
} | |||
} | |||
for (int i = 0; i < masksRender.length; i ++) { | |||
masksRender[i] = createImage(renderFiltered.width, renderFiltered.height, ARGB); | |||
masksRender[i].loadPixels(); | |||
for (int j = 0; j < masksRender[i].width*masksRender[i].height; j++) { | |||
if (c[i] == color(imgRenderFiltered.pixels[j])) { | |||
masksRender[i].pixels[j] = color(255); | |||
} else { | |||
masksRender[i].pixels[j] = color(0); | |||
} | |||
} | |||
} | |||
// render edge image | |||
/* old, processing edge detection example | |||
float[][] kernel = {{ -1, -1, -1}, | |||
{ -1, 9, -1}, | |||
{ -1, -1, -1}}; | |||
edgeImg = createImage(renderFiltered.width, renderFiltered.height, RGB); | |||
for (int y = 1; y < renderFiltered.height-1; y++) { | |||
for (int x = 1; x < renderFiltered.width-1; x++) { | |||
float sum = 0; | |||
for (int ky = -1; ky <= 1; ky++) { | |||
for (int kx = -1; kx <= 1; kx++) { | |||
int pos = (y + ky)*renderFiltered.width + (x + kx); | |||
float val = red(renderFiltered.pixels[pos]); | |||
sum += kernel[ky+1][kx+1] * val; | |||
} | |||
} | |||
edgeImg.pixels[y*renderFiltered.width + x] = color(sum, sum, sum); | |||
} | |||
} | |||
edgeImg.updatePixels(); | |||
*/ | |||
} | |||
} | |||
void airisRender(int size) { | |||
if (!airisRendering) { | |||
airisRendering = true; | |||
previousRenderSize = renderSize; | |||
previousRecordState = recording; | |||
renderSize = size; | |||
recording = true; | |||
} | |||
} | |||
boolean airisRendering; | |||
int previousRenderSize; | |||
boolean previousRecordState; | |||
void snapshot() { | |||
frameName = str(frameCount + int(uptime)); | |||
if (airisRendering) { | |||
String renderPath = dataPath("")+"/snapshots/" + frameName + "_rendered/"; | |||
renderer.save(renderPath + frameName + ".png"); | |||
//edgeImg.save(renderPath + frameName + "_edges.bmp"); | |||
//exec(dataPath("potrace"), "--svg", renderPath + frameName + "_edges.bmp", "-o", renderPath + frameName + "_edges.svg"); | |||
//sobelEdgeImg.save(renderPath + frameName + "_edgeSobel.png"); | |||
//cannyEdgeImg.save(renderPath + frameName + "_edgeCanny.png"); | |||
//cannyEdgeImg2.save(renderPath + frameName + "_edgeCanny2.png"); | |||
cannyEdgeImg2.save(renderPath + frameName + "_edge.png"); | |||
//edgeImg2.save(renderPath + frameName + "_edges2.png"); | |||
//renderFiltered.save(renderPath + frameName + "_filtered.png"); | |||
//pack 3 masks into one image | |||
PImage packedMasks = createImage(masksRender[0].width, masksRender[0].height, RGB); | |||
packedMasks.loadPixels(); | |||
for (int i = 0; i < masksRender.length; i ++) { | |||
masksRender[i].save(renderPath + frameName + "_mask_" + i + ".png"); | |||
} | |||
for (int j = 0; j < masksRender[0].pixels.length; j++) { | |||
packedMasks.pixels[j] = color(red(masksRender[0].pixels[j]), green(masksRender[1].pixels[j]), blue(masksRender[2].pixels[j])); | |||
} | |||
packedMasks.updatePixels(); | |||
packedMasks.save(renderPath + frameName + "_masks_packed.png"); | |||
composiorServer.write("images " + renderer.width + " " + renderer.height + " " + renderPath); | |||
println("Rendered & Message sent"); | |||
} else { | |||
renderer.save(dataPath("")+"/snapshots/" + frameName + ".png"); | |||
} | |||
saveData[1] = "uptime = " + frameName; | |||
println("Rendered " + frameName + ".png at " + dataPath("")+"/snapshots/ with a resolution of " + renderer.width + " x " + renderer.height); | |||
saveStrings(dataPath("saves.sav"), saveData); | |||
} | |||
//the following two effects were not implemented as fx-shaders. | |||
//these are just for iris // vector tracing | |||
/******************************************* | |||
* CANNY EDGE DETECTOR FOR VECTOR TRACING | |||
*******************************************/ | |||
import java.awt.image.BufferedImage; | |||
import java.util.Arrays; | |||
PImage cannyEdge(PImage img){ | |||
CannyEdgeDetector detector = new CannyEdgeDetector(); | |||
detector.setLowThreshold(0.5f); | |||
detector.setHighThreshold(1f); | |||
detector.setSourceImage((java.awt.image.BufferedImage)img.getImage()); | |||
detector.process(); | |||
BufferedImage edges = detector.getEdgesImage(); | |||
PImage changed = new PImage(edges); | |||
return changed; | |||
} | |||
// The code below is taken from "http://www.tomgibara.com/computer-vision/CannyEdgeDetector.java" | |||
// I have stripped the comments for conciseness | |||
public class CannyEdgeDetector { | |||
// statics | |||
private final static float GAUSSIAN_CUT_OFF = 0.005f; | |||
private final static float MAGNITUDE_SCALE = 100F; | |||
private final static float MAGNITUDE_LIMIT = 1000F; | |||
private final static int MAGNITUDE_MAX = (int) (MAGNITUDE_SCALE * MAGNITUDE_LIMIT); | |||
// fields | |||
private int height; | |||
private int width; | |||
private int picsize; | |||
private int[] data; | |||
private int[] magnitude; | |||
private BufferedImage sourceImage; | |||
private BufferedImage edgesImage; | |||
private float gaussianKernelRadius; | |||
private float lowThreshold; | |||
private float highThreshold; | |||
private int gaussianKernelWidth; | |||
private boolean contrastNormalized; | |||
private float[] xConv; | |||
private float[] yConv; | |||
private float[] xGradient; | |||
private float[] yGradient; | |||
// constructors | |||
/** | |||
* Constructs a new detector with default parameters. | |||
*/ | |||
public CannyEdgeDetector() { | |||
lowThreshold = 2.5f; | |||
highThreshold = 7.5f; | |||
gaussianKernelRadius = 2f; | |||
gaussianKernelWidth = 16; | |||
contrastNormalized = false; | |||
} | |||
public BufferedImage getSourceImage() { | |||
return sourceImage; | |||
} | |||
public void setSourceImage(BufferedImage image) { | |||
sourceImage = image; | |||
} | |||
public BufferedImage getEdgesImage() { | |||
return edgesImage; | |||
} | |||
public void setEdgesImage(BufferedImage edgesImage) { | |||
this.edgesImage = edgesImage; | |||
} | |||
public float getLowThreshold() { | |||
return lowThreshold; | |||
} | |||
public void setLowThreshold(float threshold) { | |||
if (threshold < 0) throw new IllegalArgumentException(); | |||
lowThreshold = threshold; | |||
} | |||
public float getHighThreshold() { | |||
return highThreshold; | |||
} | |||
public void setHighThreshold(float threshold) { | |||
if (threshold < 0) throw new IllegalArgumentException(); | |||
highThreshold = threshold; | |||
} | |||
public int getGaussianKernelWidth() { | |||
return gaussianKernelWidth; | |||
} | |||
public void setGaussianKernelWidth(int gaussianKernelWidth) { | |||
if (gaussianKernelWidth < 2) throw new IllegalArgumentException(); | |||
this.gaussianKernelWidth = gaussianKernelWidth; | |||
} | |||
public float getGaussianKernelRadius() { | |||
return gaussianKernelRadius; | |||
} | |||
public void setGaussianKernelRadius(float gaussianKernelRadius) { | |||
if (gaussianKernelRadius < 0.1f) throw new IllegalArgumentException(); | |||
this.gaussianKernelRadius = gaussianKernelRadius; | |||
} | |||
public boolean isContrastNormalized() { | |||
return contrastNormalized; | |||
} | |||
public void setContrastNormalized(boolean contrastNormalized) { | |||
this.contrastNormalized = contrastNormalized; | |||
} | |||
// methods | |||
public void process() { | |||
width = sourceImage.getWidth(); | |||
height = sourceImage.getHeight(); | |||
picsize = width * height; | |||
initArrays(); | |||
readLuminance(); | |||
if (contrastNormalized) normalizeContrast(); | |||
computeGradients(gaussianKernelRadius, gaussianKernelWidth); | |||
int low = Math.round(lowThreshold * MAGNITUDE_SCALE); | |||
int high = Math.round( highThreshold * MAGNITUDE_SCALE); | |||
performHysteresis(low, high); | |||
thresholdEdges(); | |||
writeEdges(data); | |||
} | |||
// private utility methods | |||
private void initArrays() { | |||
if (data == null || picsize != data.length) { | |||
data = new int[picsize]; | |||
magnitude = new int[picsize]; | |||
xConv = new float[picsize]; | |||
yConv = new float[picsize]; | |||
xGradient = new float[picsize]; | |||
yGradient = new float[picsize]; | |||
} | |||
} | |||
private void computeGradients(float kernelRadius, int kernelWidth) { | |||
//generate the gaussian convolution masks | |||
float kernel[] = new float[kernelWidth]; | |||
float diffKernel[] = new float[kernelWidth]; | |||
int kwidth; | |||
for (kwidth = 0; kwidth < kernelWidth; kwidth++) { | |||
float g1 = gaussian(kwidth, kernelRadius); | |||
if (g1 <= GAUSSIAN_CUT_OFF && kwidth >= 2) break; | |||
float g2 = gaussian(kwidth - 0.5f, kernelRadius); | |||
float g3 = gaussian(kwidth + 0.5f, kernelRadius); | |||
kernel[kwidth] = (g1 + g2 + g3) / 3f / (2f * (float) Math.PI * kernelRadius * kernelRadius); | |||
diffKernel[kwidth] = g3 - g2; | |||
} | |||
int initX = kwidth - 1; | |||
int maxX = width - (kwidth - 1); | |||
int initY = width * (kwidth - 1); | |||
int maxY = width * (height - (kwidth - 1)); | |||
//perform convolution in x and y directions | |||
for (int x = initX; x < maxX; x++) { | |||
for (int y = initY; y < maxY; y += width) { | |||
int index = x + y; | |||
float sumX = data[index] * kernel[0]; | |||
float sumY = sumX; | |||
int xOffset = 1; | |||
int yOffset = width; | |||
for (; xOffset < kwidth; ) { | |||
sumY += kernel[xOffset] * (data[index - yOffset] + data[index + yOffset]); | |||
sumX += kernel[xOffset] * (data[index - xOffset] + data[index + xOffset]); | |||
yOffset += width; | |||
xOffset++; | |||
} | |||
yConv[index] = sumY; | |||
xConv[index] = sumX; | |||
} | |||
} | |||
for (int x = initX; x < maxX; x++) { | |||
for (int y = initY; y < maxY; y += width) { | |||
float sum = 0f; | |||
int index = x + y; | |||
for (int i = 1; i < kwidth; i++) | |||
sum += diffKernel[i] * (yConv[index - i] - yConv[index + i]); | |||
xGradient[index] = sum; | |||
} | |||
} | |||
for (int x = kwidth; x < width - kwidth; x++) { | |||
for (int y = initY; y < maxY; y += width) { | |||
float sum = 0.0f; | |||
int index = x + y; | |||
int yOffset = width; | |||
for (int i = 1; i < kwidth; i++) { | |||
sum += diffKernel[i] * (xConv[index - yOffset] - xConv[index + yOffset]); | |||
yOffset += width; | |||
} | |||
yGradient[index] = sum; | |||
} | |||
} | |||
initX = kwidth; | |||
maxX = width - kwidth; | |||
initY = width * kwidth; | |||
maxY = width * (height - kwidth); | |||
for (int x = initX; x < maxX; x++) { | |||
for (int y = initY; y < maxY; y += width) { | |||
int index = x + y; | |||
int indexN = index - width; | |||
int indexS = index + width; | |||
int indexW = index - 1; | |||
int indexE = index + 1; | |||
int indexNW = indexN - 1; | |||
int indexNE = indexN + 1; | |||
int indexSW = indexS - 1; | |||
int indexSE = indexS + 1; | |||
float xGrad = xGradient[index]; | |||
float yGrad = yGradient[index]; | |||
float gradMag = hypot(xGrad, yGrad); | |||
//perform non-maximal supression | |||
float nMag = hypot(xGradient[indexN], yGradient[indexN]); | |||
float sMag = hypot(xGradient[indexS], yGradient[indexS]); | |||
float wMag = hypot(xGradient[indexW], yGradient[indexW]); | |||
float eMag = hypot(xGradient[indexE], yGradient[indexE]); | |||
float neMag = hypot(xGradient[indexNE], yGradient[indexNE]); | |||
float seMag = hypot(xGradient[indexSE], yGradient[indexSE]); | |||
float swMag = hypot(xGradient[indexSW], yGradient[indexSW]); | |||
float nwMag = hypot(xGradient[indexNW], yGradient[indexNW]); | |||
float tmp; | |||
if (xGrad * yGrad <= (float) 0 /*(1)*/ | |||
? Math.abs(xGrad) >= Math.abs(yGrad) /*(2)*/ | |||
? (tmp = Math.abs(xGrad * gradMag)) >= Math.abs(yGrad * neMag - (xGrad + yGrad) * eMag) /*(3)*/ | |||
&& tmp > Math.abs(yGrad * swMag - (xGrad + yGrad) * wMag) /*(4)*/ | |||
: (tmp = Math.abs(yGrad * gradMag)) >= Math.abs(xGrad * neMag - (yGrad + xGrad) * nMag) /*(3)*/ | |||
&& tmp > Math.abs(xGrad * swMag - (yGrad + xGrad) * sMag) /*(4)*/ | |||
: Math.abs(xGrad) >= Math.abs(yGrad) /*(2)*/ | |||
? (tmp = Math.abs(xGrad * gradMag)) >= Math.abs(yGrad * seMag + (xGrad - yGrad) * eMag) /*(3)*/ | |||
&& tmp > Math.abs(yGrad * nwMag + (xGrad - yGrad) * wMag) /*(4)*/ | |||
: (tmp = Math.abs(yGrad * gradMag)) >= Math.abs(xGrad * seMag + (yGrad - xGrad) * sMag) /*(3)*/ | |||
&& tmp > Math.abs(xGrad * nwMag + (yGrad - xGrad) * nMag) /*(4)*/ | |||
) { | |||
magnitude[index] = gradMag >= MAGNITUDE_LIMIT ? MAGNITUDE_MAX : (int) (MAGNITUDE_SCALE * gradMag); | |||
//NOTE: The orientation of the edge is not employed by this | |||
//implementation. It is a simple matter to compute it at | |||
//this point as: Math.atan2(yGrad, xGrad); | |||
} else { | |||
magnitude[index] = 0; | |||
} | |||
} | |||
} | |||
} | |||
private float hypot(float x, float y) { | |||
return (float) Math.hypot(x, y); | |||
} | |||
private float gaussian(float x, float sigma) { | |||
return (float) Math.exp(-(x * x) / (2f * sigma * sigma)); | |||
} | |||
private void performHysteresis(int low, int high) { | |||
Arrays.fill(data, 0); | |||
int offset = 0; | |||
for (int y = 0; y < height; y++) { | |||
for (int x = 0; x < width; x++) { | |||
if (data[offset] == 0 && magnitude[offset] >= high) { | |||
follow(x, y, offset, low); | |||
} | |||
offset++; | |||
} | |||
} | |||
} | |||
private void follow(int x1, int y1, int i1, int threshold) { | |||
int x0 = x1 == 0 ? x1 : x1 - 1; | |||
int x2 = x1 == width - 1 ? x1 : x1 + 1; | |||
int y0 = y1 == 0 ? y1 : y1 - 1; | |||
int y2 = y1 == height -1 ? y1 : y1 + 1; | |||
data[i1] = magnitude[i1]; | |||
for (int x = x0; x <= x2; x++) { | |||
for (int y = y0; y <= y2; y++) { | |||
int i2 = x + y * width; | |||
if ((y != y1 || x != x1) | |||
&& data[i2] == 0 | |||
&& magnitude[i2] >= threshold) { | |||
follow(x, y, i2, threshold); | |||
return; | |||
} | |||
} | |||
} | |||
} | |||
private void thresholdEdges() { | |||
for (int i = 0; i < picsize; i++) { | |||
data[i] = data[i] > 0 ? -1 : 0xff000000; | |||
} | |||
} | |||
private int luminance(float r, float g, float b) { | |||
return Math.round(0.299f * r + 0.587f * g + 0.114f * b); | |||
} | |||
private void readLuminance() { | |||
int type = sourceImage.getType(); | |||
if (type == BufferedImage.TYPE_INT_RGB || type == BufferedImage.TYPE_INT_ARGB) { | |||
int[] pixels = (int[]) sourceImage.getData().getDataElements(0, 0, width, height, null); | |||
for (int i = 0; i < picsize; i++) { | |||
int p = pixels[i]; | |||
int r = (p & 0xff0000) >> 16; | |||
int g = (p & 0xff00) >> 8; | |||
int b = p & 0xff; | |||
data[i] = luminance(r, g, b); | |||
} | |||
} else if (type == BufferedImage.TYPE_BYTE_GRAY) { | |||
byte[] pixels = (byte[]) sourceImage.getData().getDataElements(0, 0, width, height, null); | |||
for (int i = 0; i < picsize; i++) { | |||
data[i] = (pixels[i] & 0xff); | |||
} | |||
} else if (type == BufferedImage.TYPE_USHORT_GRAY) { | |||
short[] pixels = (short[]) sourceImage.getData().getDataElements(0, 0, width, height, null); | |||
for (int i = 0; i < picsize; i++) { | |||
data[i] = (pixels[i] & 0xffff) / 256; | |||
} | |||
} else if (type == BufferedImage.TYPE_3BYTE_BGR) { | |||
byte[] pixels = (byte[]) sourceImage.getData().getDataElements(0, 0, width, height, null); | |||
int offset = 0; | |||
for (int i = 0; i < picsize; i++) { | |||
int b = pixels[offset++] & 0xff; | |||
int g = pixels[offset++] & 0xff; | |||
int r = pixels[offset++] & 0xff; | |||
data[i] = luminance(r, g, b); | |||
} | |||
} else { | |||
throw new IllegalArgumentException("Unsupported image type: " + type); | |||
} | |||
} | |||
private void normalizeContrast() { | |||
int[] histogram = new int[256]; | |||
for (int i = 0; i < data.length; i++) { | |||
histogram[data[i]]++; | |||
} | |||
int[] remap = new int[256]; | |||
int sum = 0; | |||
int j = 0; | |||
for (int i = 0; i < histogram.length; i++) { | |||
sum += histogram[i]; | |||
int target = sum*255/picsize; | |||
for (int k = j+1; k <=target; k++) { | |||
remap[k] = i; | |||
} | |||
j = target; | |||
} | |||
for (int i = 0; i < data.length; i++) { | |||
data[i] = remap[data[i]]; | |||
} | |||
} | |||
private void writeEdges(int pixels[]) { | |||
if (edgesImage == null) { | |||
edgesImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); | |||
} | |||
edgesImage.getWritableTile(0, 0).setDataElements(0, 0, width, height, pixels); | |||
} | |||
} | |||
/*************************************** | |||
* SOBELEDGE DETECTION FOR VECTOR TRACING | |||
***************************************/ | |||
SobelEdgeDetection sobel; | |||
PImage sobelEdge(PImage img) { | |||
PImage g_img = sobel.findEdgesAll(img, 90); | |||
g_img = sobel.noiseReduction(g_img, 1); | |||
return(g_img); | |||
} | |||
class SobelEdgeDetection | |||
{ | |||
// Sobel Edge Detection strandard, this applies the edge detection algorithm across the entire image and returns the edge image | |||
public PImage findEdgesAll(PImage img, int tolerance) | |||
{ | |||
PImage buf = createImage( img.width, img.height, ARGB ); | |||
int GX[][] = new int[3][3]; | |||
int GY[][] = new int[3][3]; | |||
int sumRx = 0; | |||
int sumGx = 0; | |||
int sumBx = 0; | |||
int sumRy = 0; | |||
int sumGy = 0; | |||
int sumBy = 0; | |||
int finalSumR = 0; | |||
int finalSumG = 0; | |||
int finalSumB = 0; | |||
// 3x3 Sobel Mask for X | |||
GX[0][0] = -1; | |||
GX[0][1] = 0; | |||
GX[0][2] = 1; | |||
GX[1][0] = -2; | |||
GX[1][1] = 0; | |||
GX[1][2] = 2; | |||
GX[2][0] = -1; | |||
GX[2][1] = 0; | |||
GX[2][2] = 1; | |||
// 3x3 Sobel Mask for Y | |||
GY[0][0] = 1; | |||
GY[0][1] = 2; | |||
GY[0][2] = 1; | |||
GY[1][0] = 0; | |||
GY[1][1] = 0; | |||
GY[1][2] = 0; | |||
GY[2][0] = -1; | |||
GY[2][1] = -2; | |||
GY[2][2] = -1; | |||
buf.loadPixels(); | |||
for(int y = 0; y < img.height; y++) | |||
{ | |||
for(int x = 0; x < img.width; x++) | |||
{ | |||
if(y==0 || y==img.height-1) { | |||
} | |||
else if( x==0 || x == img.width-1 ) { | |||
} | |||
else | |||
{ | |||
// Convolve across the X axis and return gradiant aproximation | |||
for(int i = -1; i <= 1; i++) | |||
for(int j = -1; j <= 1; j++) | |||
{ | |||
color col = img.get(x + i, y + j); | |||
float r = red(col); | |||
float g = green(col); | |||
float b = blue(col); | |||
sumRx += r * GX[ i + 1][ j + 1]; | |||
sumGx += g * GX[ i + 1][ j + 1]; | |||
sumBx += b * GX[ i + 1][ j + 1]; | |||
} | |||
// Convolve across the Y axis and return gradiant aproximation | |||
for(int i = -1; i <= 1; i++) | |||
for(int j = -1; j <= 1; j++) | |||
{ | |||
color col = img.get(x + i, y + j); | |||
float r = red(col); | |||
float g = green(col); | |||
float b = blue(col); | |||
sumRy += r * GY[ i + 1][ j + 1]; | |||
sumGy += g * GY[ i + 1][ j + 1]; | |||
sumBy += b * GY[ i + 1][ j + 1]; | |||
} | |||
finalSumR = abs(sumRx) + abs(sumRy); | |||
finalSumG = abs(sumGx) + abs(sumGy); | |||
finalSumB = abs(sumBx) + abs(sumBy); | |||
// I only want to return a black or a white value, here I determine the greyscale value, | |||
// and if it is above a tolerance, then set the colour to white | |||
float gray = (finalSumR + finalSumG + finalSumB) / 3; | |||
if(gray > tolerance) | |||
{ | |||
finalSumR = 0; | |||
finalSumG = 0; | |||
finalSumB = 0; | |||
} | |||
else | |||
{ | |||
finalSumR = 255; | |||
finalSumG = 255; | |||
finalSumB = 255; | |||
} | |||
buf.pixels[ x + (y * img.width) ] = color(finalSumR, finalSumG, finalSumB); | |||
sumRx=0; | |||
sumGx=0; | |||
sumBx=0; | |||
sumRy=0; | |||
sumGy=0; | |||
sumBy=0; | |||
} | |||
} | |||
} | |||
buf.updatePixels(); | |||
return buf; | |||
} | |||
public PImage noiseReduction(PImage img, int kernel) | |||
{ | |||
PImage buf = createImage( img.width, img.height, ARGB ); | |||
buf.loadPixels(); | |||
for(int y = 0; y < img.height; y++) | |||
{ | |||
for(int x = 0; x < img.width; x++) | |||
{ | |||
int sumR = 0; | |||
int sumG = 0; | |||
int sumB = 0; | |||
// Convolute across the image, averages out the pixels to remove noise | |||
for(int i = -kernel; i <= kernel; i++) | |||
{ | |||
for(int j = -kernel; j <= kernel; j++) | |||
{ | |||
color col = img.get(x+i,y+j); | |||
float r = red(col); | |||
float g = green(col); | |||
float b = blue(col); | |||
if(r==255) sumR++; | |||
if(g==255) sumG++; | |||
if(b==255) sumB++; | |||
} | |||
} | |||
int halfKernel = (((kernel*2)+1) * ((kernel*2)+1)) / 2 ; | |||
if(sumR > halfKernel ) sumR=255; | |||
else sumR= 0; | |||
if(sumG > halfKernel ) sumG=255; | |||
else sumG= 0; | |||
if(sumB > halfKernel ) sumB=255; | |||
else sumB= 0; | |||
buf.pixels[ x + (y * img.width) ] = color(sumR, sumG, sumB); | |||
} | |||
} | |||
buf.updatePixels(); | |||
return buf; | |||
} | |||
} |
@@ -0,0 +1,112 @@ | |||
class Shader { | |||
int id; | |||
int number; | |||
String name; | |||
boolean animating = true; | |||
ArrayList<Param> params = new ArrayList<Param>(); | |||
class Param { | |||
int type; | |||
String name; | |||
float minValue, maxValue; | |||
float value; | |||
float inc; | |||
boolean animating; | |||
int[] osciModes; | |||
//Osci[] oscis; | |||
Osci osci; | |||
//incrementer -- in bpm | |||
Param(String paramName, int maxValue_, int[] osciModes_) { | |||
name = paramName; | |||
maxValue = maxValue_; | |||
minValue = 0; | |||
type = INTVAL; //int | |||
osciModes = osciModes_; | |||
makeOsci(); | |||
play(); | |||
} | |||
Param(String paramName, float minValue_, float maxValue_, int[] osciModes_) { | |||
name = paramName; | |||
minValue = minValue_; | |||
maxValue = maxValue_; | |||
type = FLOATVAL; //float | |||
osciModes = osciModes_; | |||
makeOsci(); | |||
play(); | |||
} | |||
void makeOsci() { | |||
int[] possibleBeats = {1, 2, 4, 8, 16, 32, 64}; | |||
int beats = possibleBeats[(int)random(possibleBeats.length)]; | |||
int mode = osciModes[(int)random(osciModes.length)]; | |||
float phaseshift = (random(1) > .8) ? .25 : 0; | |||
osci = new Osci(beats, phaseshift, mode); | |||
} | |||
void play() { | |||
animating = true; | |||
} | |||
void pause() { | |||
animating = false; | |||
} | |||
void animate() { | |||
osci.update(); | |||
value = getValue(osci.value, false); | |||
}; | |||
void randomize() { | |||
if (type == INTVAL) { | |||
value = (int)random(minValue, maxValue); | |||
} else if (type == FLOATVAL) { | |||
//value = random(minValue, maxValue); | |||
value = random(minValue, maxValue); | |||
} | |||
} | |||
String formattedValue() { | |||
if (type == INTVAL) { | |||
return str((int)value); | |||
} else if (type == FLOATVAL) { | |||
return nf(getValue(value, true), 0, 2).replace(',', '.').replace(' ', ','); | |||
} else { | |||
return ""; | |||
} | |||
} | |||
float getValue(float val, boolean normalize) { //used for other function, dont use it | |||
return normalize ? map(val, minValue, maxValue, 0, 1) : map(val, 0, 1, minValue, maxValue); | |||
} | |||
void setValue(float value_) { | |||
if (type == INTVAL) { | |||
value = constrain((int)value_, 0, maxValue); | |||
} else if (type == FLOATVAL) { | |||
value = getValue(value_, false); | |||
} | |||
} | |||
} | |||
void apply() { | |||
}; //override me | |||
String[] getParamNames() { | |||
String[] pnames = new String[params.size()]; | |||
for (int i = 0; i < params.size(); i++) { | |||
pnames[i] = params.get(i).name; | |||
} | |||
return pnames; | |||
} | |||
int paramIdByName(String name_) { | |||
for (int i = 0; i < params.size(); i ++) { | |||
if (params.get(i).name.equals(name_)) { | |||
return i; | |||
} | |||
} | |||
return -1; | |||
} | |||
} | |||
/* | |||
*/ |
@@ -0,0 +1,153 @@ | |||
Capture cam; | |||
Movie movie; | |||
boolean moviePlaying; | |||
PImage fallbackImage; | |||
void movieEvent(Movie m) { | |||
if (moviePlaying) { | |||
m.read(); | |||
if (mode == 1) { | |||
sourceManager.setImage(movie.get()); | |||
movie.jump(random(movie.duration())); | |||
} | |||
} | |||
} | |||
void newMovie(String path) { | |||
movie = new Movie(this, path); | |||
} | |||
boolean isVideo(String path) { | |||
String fpl = path.toLowerCase(); | |||
if (fpl.endsWith(".mp4") || fpl.endsWith(".avi") || fpl.endsWith(".webm") || fpl.endsWith(".mkv") || fpl.endsWith(".mov")) return true; | |||
else return false; | |||
} | |||
boolean isImage(String path) { | |||
String fpl = path.toLowerCase(); | |||
if (fpl.endsWith(".bmp") || fpl.endsWith(".png") || fpl.endsWith(".jpg") || fpl.endsWith(".jpeg") || fpl.endsWith(".gif")) return true; //gif = special case! | |||
else return false; | |||
} | |||
class SourceManager { //no constructor | |||
// This function returns all the files in a directory as an array of Strings | |||
String[] listFileNames(String dir) { | |||
File file = new File(dir); | |||
if (file.isDirectory()) { | |||
String names[] = file.list(); | |||
return names; | |||
} else { | |||
return null; | |||
} | |||
} | |||
String dir; | |||
String[] selection; | |||
int selId; | |||
void importURI(String path) { | |||
File file = new File(path); | |||
if (file.isDirectory()) { | |||
dir = path; | |||
String names[] = file.list(); | |||
ArrayList<String> usableFiles = new ArrayList<String>(); | |||
for (int i = 0; i < names.length; i++) { | |||
if (isImage(names[i]) || isVideo(names[i])) { | |||
usableFiles.add(names[i]); | |||
} | |||
} | |||
selection = new String[usableFiles.size()]; | |||
for (int i = 0; i < usableFiles.size(); i++) selection[i] = usableFiles.get(i); | |||
println("Got new selection from folder. " + selection.length + " usable files."); | |||
path = dir + "/" + selection[(int)random(selection.length)]; | |||
} | |||
if (isImage(path) || isVideo(path)) { | |||
println("Importing file " + path); | |||
if (moviePlaying) movie.stop(); | |||
if (isImage(path)) { | |||
moviePlaying = false; | |||
setImage(loadImage(path)); | |||
} else if (isVideo(path)) { | |||
moviePlaying = true; | |||
newMovie(path); | |||
movie.loop(); | |||
} | |||
} | |||
} | |||
void fallback() { | |||
println("Fallback"); | |||
mode = 1; | |||
setImage(fallbackImage); //fallbackImage should always be a copy of the last image that worked | |||
} | |||
void update() { | |||
//check if source image is present | |||
if (mode == 0) { | |||
try { | |||
if (cam.available() == true) { | |||
cam.read(); | |||
if (cam != null) { | |||
source = cam.get(); | |||
} else { | |||
fallback(); | |||
} | |||
} | |||
} | |||
catch (Exception e) { | |||
println(e); | |||
println("No cam available, falling back to image.."); | |||
fallback(); | |||
} | |||
} | |||
if (source == null) { | |||
fallback(); | |||
} | |||
int toW, toH; | |||
if (source.width > source.height) { | |||
toW = renderSize; | |||
toH = int(map(source.height, 0, source.width, 0, renderSize)); | |||
} else { | |||
toW = int(map(source.width, 0, source.height, 0, renderSize)); | |||
toH = renderSize; | |||
} | |||
toW = (toW % 2 == 0) ? toW : toW+1; | |||
toH = (toH % 2 == 0) ? toH : toH+1; | |||
renderer.setSize(toW, toH); | |||
} | |||
void setImage(PImage img) { //set image to source | |||
source = img.get(); | |||
fallbackImage = source; | |||
} | |||
void setSource() { //set source to renderer | |||
renderer.beginDraw(); | |||
if (mode == 0) { | |||
try { //final check for source image being present & valid | |||
renderer.beginDraw(); //pre-fx | |||
renderer.tint(255, 220, 200); //beautify me (color correct webcam image) | |||
renderer.image(source, 0, 0, renderer.width, renderer.height); | |||
renderer.noTint(); | |||
} | |||
catch(Exception e) { | |||
println("error here as well"); | |||
} | |||
} | |||
if (mode == 1) { | |||
//else if (mode == 1){ | |||
renderer.image(source, 0, 0, renderer.width, renderer.height); | |||
} | |||
renderer.endDraw(); | |||
} | |||
} |
@@ -0,0 +1,179 @@ | |||
void mousePressed() | |||
{ | |||
if (mouseButton == LEFT) { | |||
if (sourceManager.dir != null) { | |||
sourceManager.importURI(sourceManager.dir + "/" + sourceManager.selection[(int)random(sourceManager.selection.length)]); | |||
} | |||
} | |||
if (mouseButton == RIGHT) { | |||
snapshot(); | |||
} | |||
} | |||
boolean videoRecord; | |||
void mouseWheel(MouseEvent event) { | |||
if (event.getCount() < 0) renderSize += 8; | |||
else renderSize -= 8; | |||
renderSize = constrain(renderSize, 8, 15000); | |||
println("Render size: " + renderSize); | |||
} | |||
String[] params; | |||
void keyPressed() { | |||
if (key == 'c') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new DARKER()); | |||
} | |||
if (key == 'r') { | |||
for (int i = 0; i < fxManager.fxList.size(); i ++) { | |||
for (int j = 0; j < fxManager.fxList.get(i).shader.params.size(); j++) { | |||
fxManager.fxList.get(i).shader.params.get(j).randomize(); | |||
} | |||
} | |||
} | |||
if (key == 'x') { | |||
videoRecord = !videoRecord; | |||
if (videoRecord) { | |||
println("Started video recording"); | |||
videoExport = new VideoExport(this, "data/videos/" + str(frameCount + int(uptime)) + ".mp4", renderer); | |||
//String[] settings = {"[ffmpeg]","-y","-f","rawvideo","-vcodec","rawvideo","-s",str(renderer.width)+"x"+str(renderer.height),}; | |||
videoExport.setFrameRate(frameRate); | |||
videoExport.setQuality(100, 0); // (crf, audiobitrate) | |||
String videoSize = str(renderer.width)+"x"+str(renderer.height); | |||
videoExport.setFfmpegVideoSettings( | |||
new String[]{ | |||
"[ffmpeg]", // ffmpeg executable | |||
"-y", // overwrite old file | |||
"-f", "rawvideo", // format rgb raw | |||
"-vcodec", "rawvideo", // in codec rgb raw | |||
"-s", videoSize, // size | |||
"-pix_fmt", "rgb24", // pix format rgb24 | |||
"-r", "[fps]", // frame rate | |||
"-i", "-", // pipe input | |||
//"-vf", "scale="+str(renderer.width)+":"+str(renderer.height)+":force_original_aspect_ratio=decrease", | |||
"-an", // no audio | |||
"-vcodec", "h264", // out codec h264 | |||
"-pix_fmt", "yuv420p", // color space yuv420p | |||
"-crf", "[crf]", // quality | |||
"-metadata", "comment=[comment]", // comment | |||
"[output]" // output file | |||
}); | |||
videoExport.setDebugging(true); | |||
videoExport.startMovie(); | |||
} else { | |||
println("Ended video recording"); | |||
videoExport.endMovie(); | |||
videoExport.dispose(); | |||
} | |||
} | |||
if (key == 'f') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new FM()); | |||
} | |||
if (key == 'j') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new DRAWSTROKES()); | |||
} | |||
if (key == 'h') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new DRAWGENERATIVE()); | |||
} | |||
if (key == 'd') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new ASDFPIXELSORT()); | |||
} | |||
if (key == 'b') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new BRIGHTER()); | |||
} | |||
if (key == 'e') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new DISTORTER()); | |||
} | |||
if (key == 'w') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new WZIP()); | |||
} | |||
if (key == 'g') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new GRAUZONE()); | |||
} | |||
if (key == 'q') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new SLITSCAN()); | |||
} | |||
if (key == ' ') { | |||
} | |||
if (key == 'o') { | |||
renderSize = 10000; | |||
} | |||
if (key == '1') { | |||
mode = 0; | |||
} | |||
if (key == '2') { | |||
if (mode != 1) sourceManager.fallback(); | |||
mode = 1; | |||
} | |||
if (keyCode == KeyEvent.VK_F10) { | |||
airisRender(5000); //15000 would be fine as well i guess | |||
} | |||
if (key == 'a') { | |||
if (fxManager.fxList.size() < maxFx) fxManager.addFx(new AUECHO()); | |||
} | |||
if (key == 'v') { | |||
fxManager.removeFx(fxManager.fxList.size()-1); //remove last in arraylist | |||
// fxManager.removeFx(2); //remove at position in arraylist | |||
} | |||
/* if (key == 'a') { | |||
params = loadStrings(dataPath("params.txt")); | |||
for (int i = 0; i < params.length; i++) { | |||
println(params[i]); | |||
} | |||
}*/ | |||
} | |||
int guiOffsetTop = 0; | |||
boolean guiHidden; | |||
String noparams = "no directly controllable parameters, try play/ pausing to randomize"; | |||
void drawGUI(int topOffset) { | |||
fill(255); | |||
for (int i = 0; i < fxManager.fxList.size(); i++) { | |||
textSize(20); | |||
textAlign(RIGHT); | |||
int fi = i+1; | |||
float textOffset = textWidth(fxManager.fxList.get(i).shader.name); | |||
fill(0, 0, 0, 255); | |||
rect(width-(textOffset+54), 8+(i*65)+topOffset, textOffset+54, 30); | |||
fill(255); | |||
text("[" + fi + "] " + fxManager.fxList.get(i).shader.name, -10, 10+(i*65)+topOffset, width, 100); | |||
String playText = (fxManager.fxList.get(i).shader.animating) ? "animated" : "manual set"; | |||
fill(75, 75, 75, 255); | |||
rect(width-(textOffset+54+textWidth(playText)), 10+(i*65)+5+topOffset, textWidth(playText), 25); | |||
fill(255); | |||
textAlign(RIGHT); | |||
textSize(15); | |||
text(playText, -(textOffset+65), 10+(i*65)+5+topOffset, width, 100); | |||
textOffset = 0; | |||
for (int j = 0; j < fxManager.fxList.get(i).shader.params.size(); j ++) { | |||
textOffset += textWidth(fxManager.fxList.get(i).shader.params.get(j).name) + textWidth(fxManager.fxList.get(i).shader.params.get(j).formattedValue()) +15; | |||
} | |||
fill(75, 75, 75, 255); | |||
textOffset = (textOffset == 0) ? textWidth(noparams)+15 : textOffset; | |||
rect(width-textOffset-15, 37+(i*65)+topOffset, textOffset+15, 25); | |||
fill(255); | |||
textOffset = 0; | |||
textAlign(RIGHT); | |||
if (fxManager.fxList.get(i).shader.params.size()>0) { | |||
for (int j = 0; j < fxManager.fxList.get(i).shader.params.size(); j ++) { | |||
text(fxManager.fxList.get(i).shader.params.get(j).name + ": " + fxManager.fxList.get(i).shader.params.get(j).formattedValue(), -textOffset-10, 40+(i*65)+topOffset, width, 100); | |||
textOffset += textWidth(fxManager.fxList.get(i).shader.params.get(j).name) + textWidth(fxManager.fxList.get(i).shader.params.get(j).formattedValue()) +15; | |||
} | |||
} else { | |||
text(noparams, -textOffset-10, 40+(i*65)+topOffset, width, 100); | |||
} | |||
} | |||
} | |||
PImage droppedImage; | |||
void dropEvent(DropEvent theDropEvent) { | |||
sourceManager.importURI(theDropEvent.filePath()); | |||
} |