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; | |||||
} | |||||
} |
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(); | |||||
} | |||||
} |
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(); | |||||
} | |||||
} |
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); | |||||
} | |||||
} |
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; | |||||
} | |||||
} |
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; | |||||
} | |||||
} |
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)); | |||||
} | |||||
} | |||||
} |
// 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); | |||||
} | |||||
} | |||||
} |
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(); | |||||
} | |||||
} |
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]); | |||||
} | |||||
} |
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); | |||||
} | |||||
} |
//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 | |||||
}; |
//globals | |||||
uptime = 116617879 |
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. |
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; | |||||
} | |||||
} | |||||
} |
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"); | |||||
} | |||||
} | |||||
} |
/* | |||||
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 | |||||
} | |||||
*/ |
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; | |||||
} |
//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); | |||||
}*/ | |||||
} |
//"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; | |||||
} | |||||
} |
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; | |||||
} | |||||
} | |||||
/* | |||||
*/ |
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(); | |||||
} | |||||
} |
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()); | |||||
} |