PImage bg, img;
PFont font;
/**
controls
q...i - hilbert sfc dithering with different q
o - 4 color noise diffusion
p - 2 color noise diffusion
a..j - noise diffusion with arbitrary number of gray shades
k - Bill Atkinson's B/W dither
l - Bill Atkinson's COLOR dither
m - grayscale image for reference
spacebar - reset image
*/
void setup() {
size(1024,600);
//size(400,240);
frameRate(15);
textMode(SCREEN);
font=loadFont("Trivia-Regular-24.vlw");
textFont(font, 24);
bg=loadImage("abstracttest.jpg");
img=new PImage(width,height);
img.copy(bg,0,0,bg.width,bg.height,0,0,width,height);
image(img,0,0);
}
void atkinsonDither(PImage img) {
img.loadPixels(); // img.pixels - vstup
loadPixels(); // pixels - vystup
color c1 = color(0,0,0);
color c2 = color(255,255,255);
float bri,err;
for (int i=0; i<(width*height); ++i) {
bri=brightness(img.pixels[i]);
if ( bri<128 ) {
pixels[i]=c1;
err=bri/8;
}
else {
pixels[i]=c2;
err=-((255-bri)/8);
}
//pixels[i]=color(abs(err*16),bri,bri);
if ( i<((width*(height-2))-2) ) {
img.pixels[i+1]= color(constrain(brightness(img.pixels[i+1])+err,0,255));
img.pixels[i+2]= color(constrain(brightness(img.pixels[i+2])+err,0,255));
img.pixels[i+width-1]= color(constrain(brightness(img.pixels[i+width-1])+err,0,255));
img.pixels[i+width]= color(constrain(brightness(img.pixels[i+width])+err,0,255));
img.pixels[i+width+1]= color(constrain(brightness(img.pixels[i+width+1])+err,0,255));
img.pixels[i+(2*width)]= color(constrain(brightness(img.pixels[i+(2*width)])+err,0,255));
}
}
updatePixels();
}
void atkinsonColorDither(PImage img) {
img.loadPixels(); // img.pixels - vstup
loadPixels(); // pixels - vystup
color c1 = color(0,0,0);
color c2 = color(255,255,255);
float r,g,b,rerr,gerr,berr;
int j;
for (int i=0; i<(width*height); ++i) {
r=red(img.pixels[i]);
g=green(img.pixels[i]);
b=blue(img.pixels[i]);
pixels[i]=color(r<128?0:255,g<128?0:255,b<128?0:255);
rerr=(r-red(pixels[i]))/8;
gerr=(g-green(pixels[i]))/8;
berr=(b-blue(pixels[i]))/8;
if ( i<((width*(height-2))-2) ) {
j=i+1;
img.pixels[j]= color( red(img.pixels[j])+rerr, green(img.pixels[j])+gerr, blue(img.pixels[j])+berr );
j=i+2;
img.pixels[j]= color( red(img.pixels[j])+rerr, green(img.pixels[j])+gerr, blue(img.pixels[j])+berr );
j=i+width-1;
img.pixels[j]= color( red(img.pixels[j])+rerr, green(img.pixels[j])+gerr, blue(img.pixels[j])+berr );
j=i+width;
img.pixels[j]= color( red(img.pixels[j])+rerr, green(img.pixels[j])+gerr, blue(img.pixels[j])+berr );
j=i+width+1;
img.pixels[j]= color( red(img.pixels[j])+rerr, green(img.pixels[j])+gerr, blue(img.pixels[j])+berr );
j=i+(2*width);
img.pixels[j]= color( red(img.pixels[j])+rerr, green(img.pixels[j])+gerr, blue(img.pixels[j])+berr );
/*
img.pixels[i+1]= color(constrain(brightness(img.pixels[i+1])+err,0,255));
img.pixels[i+2]= color(constrain(brightness(img.pixels[i+2])+err,0,255));
img.pixels[i+width-1]= color(constrain(brightness(img.pixels[i+width-1])+err,0,255));
img.pixels[i+width]= color(constrain(brightness(img.pixels[i+width])+err,0,255));
img.pixels[i+width+1]= color(constrain(brightness(img.pixels[i+width+1])+err,0,255));
img.pixels[i+(2*width)]= color(constrain(brightness(img.pixels[i+(2*width)])+err,0,255));
*/
}
}
updatePixels();
}
void noiseDither(PImage img) {
img.loadPixels();
loadPixels();
color c1 = color(0,0,0);
color c2 = color(255,255,255);
for (int i=0; i<(width*height); ++i) {
if ( brightness(img.pixels[i])rastr[i % rsize][j % rsize] ) {
pixels[ind]=color(255);
} else {
pixels[ind]=color(0);
}
*/
pixels[ind]=rastr[i % rsize][j % rsize]*16;
}
}
updatePixels();
}
int UP=0;
int RIGHT=1;
int DOWN=2;
int LEFT=3;
int xx=0;
int yy=0;
int step=0;
float err=0;
float errkoef=(31.0/32.0);
void hilbertstep(int xx, int yy) {
if ((xx128) {
pixels[yy*width+xx]=color(255);
err-=255;
} else {
pixels[yy*width+xx]=color(0);
}
err*=errkoef;
}
}
void move( int where ) {
int ox=xx;
int oy=yy;
switch ( where ) {
case 0:
yy--;
break;
case 1:
xx++;
break;
case 2:
yy++;
break;
case 3:
xx--;
break;
}
step++;
step=step%255;
stroke(step);
hilbertstep(xx,yy);
}
void hilbert(int level) {
img.loadPixels();
loadPixels();
hilbert_level( level, 0);
updatePixels();
}
void hilbert_level(int level,int direction)
{
stroke(255);
strokeWeight(1);
if (level==1) {
switch (direction) {
case 3:
move(1); /* move() could draw a line in... */
move(2); /* ...the indicated direction */
move(3);
break;
case 1:
move(3);
move(0);
move(1);
break;
case 0:
move(2);
move(1);
move(0);
break;
case 2:
move(0);
move(3);
move(2);
break;
} /* switch */
}
else {
switch (direction) {
case 3:
hilbert_level(level-1,UP);
move(RIGHT);
hilbert_level(level-1,LEFT);
move(DOWN);
hilbert_level(level-1,LEFT);
move(LEFT);
hilbert_level(level-1,DOWN);
break;
case 1:
hilbert_level(level-1,DOWN);
move(LEFT);
hilbert_level(level-1,RIGHT);
move(UP);
hilbert_level(level-1,RIGHT);
move(RIGHT);
hilbert_level(level-1,UP);
break;
case 0:
hilbert_level(level-1,LEFT);
move(DOWN);
hilbert_level(level-1,UP);
move(RIGHT);
hilbert_level(level-1,UP);
move(UP);
hilbert_level(level-1,RIGHT);
break;
case 2:
hilbert_level(level-1,RIGHT);
move(UP);
hilbert_level(level-1,DOWN);
move(LEFT);
hilbert_level(level-1,DOWN);
move(DOWN);
hilbert_level(level-1,LEFT);
break;
} /* switch */
} /* if */
}
void keyPressed()
{
background(255,0,0);
xx=0;yy=0;
String s="";
switch (key) {
case 'z':
case 'Z':
regularDither(img,2);
s = "regular dither - 2 colors";
break;
case 'm':
case 'M':
copyGray(img);
s = "gray(image)";
break;
case 'q':
case 'Q':
errkoef=1;
hilbert(10);
s = "hilbert sfc, color is important, k=1";
break;
case 'w':
case 'W':
errkoef=(31.0/32.0);
hilbert(10);
s = "hilbert sfc, optimal, k=31/32";
break;
case 'e':
case 'E':
errkoef=(28.0/32.0);
hilbert(10);
s = "hilbert sfc, shape is important, k=7/8";
break;
case 'r':
case 'R':
errkoef=(24.0/32.0);
hilbert(10);
s = "hilbert sfc, shape is important, k=2/3";
break;
case 't':
case 'T':
errkoef=(16.0/32.0);
hilbert(10);
s = "hilbert sfc, shape is important, k=1/2";
break;
case 'y':
case 'Y':
errkoef=(8.0/32.0);
hilbert(10);
s = "hilbert sfc, shape is important, k=1/4";
break;
case 'u':
case 'U':
errkoef=(4.0/32.0);
hilbert(10);
s = "hilbert sfc, shape prevails, k=1/8";
break;
case 'i':
case 'I':
errkoef=0;
hilbert(10);
s = "hilbert sfc, shape prevails, k=0";
break;
case 'p':
case 'P':
noiseDither(img);
s = "noise diffusion";
break;
case 'o':
case 'O':
noiseDither4col(img);
s = "4 color noise diffusion";
break;
case 'a':
case 'A':
noiseDitherNcol(img,2);
s = "noise diffusion 2 colors";
break;
case 's':
case 'S':
noiseDitherNcol(img,3);
s = "noise diffusion 3 colors";
break;
case 'd':
case 'D':
noiseDitherNcol(img,4);
s = "noise diffusion 4 colors";
break;
case 'f':
case 'F':
noiseDitherNcol(img,8);
s = "noise diffusion 8 colors";
break;
case 'g':
case 'G':
noiseDitherNcol(img,16);
s = "noise diffusion 16 colors";
break;
case 'h':
case 'H':
noiseDitherNcol(img,32);
s = "noise diffusion 32 colors";
break;
case 'j':
case 'J':
noiseDitherNcol(img,64);
s = "noise diffusion 64 colors";
break;
case 'k':
case 'K':
atkinsonDither(img);
s = "Bill Atkinson's dither";
break;
case 'l':
case 'L':
atkinsonColorDither(img);
s = "Bill Atkinson's color dither";
break;
case ' ':
img.copy(bg,0,0,bg.width,bg.height,0,0,width,height);
image(img,0,0);
break;
}
fill(0,120);
text(s, 20, height-30, 470, 70);
fill(0);
text(s, 19, height-31, 470, 70);
fill(255);
text(s, 18, height-32, 470, 70);
}
void draw() {
}