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