Skip to content

Commit 6156a2b

Browse files
committed
filter(): implement BLUR, OPAQUE, ERODE, DILATE; fix THRESHOLD param
1 parent 13d401e commit 6156a2b

1 file changed

Lines changed: 38 additions & 57 deletions

File tree

src/Processing.cpp

Lines changed: 38 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2735,67 +2735,48 @@ void PApplet::tint(float r, float g, float b, float a) {
27352735
void PApplet::noTint(){doTint=false;}
27362736

27372737
void PApplet::filter(int mode) { filter(mode, 0.5f); }
2738-
void PApplet::filter(int mode, float /*param*/) {
2739-
int total = winWidth * winHeight;
2738+
void PApplet::filter(int mode, float param) {
2739+
int w = winWidth, h = winHeight, total = w * h;
27402740
::std::vector<unsigned char> buf(total * 4);
2741-
glReadPixels(0, 0, winWidth, winHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf.data());
2742-
2743-
for (int i = 0; i < total; i++) {
2744-
int r = buf[i*4], g = buf[i*4+1], b = buf[i*4+2];
2745-
int grey = (r + g + b) / 3;
2746-
2747-
if (mode == GRAY) {
2748-
buf[i*4] = buf[i*4+1] = buf[i*4+2] = (unsigned char)grey;
2749-
} else if (mode == INVERT) {
2750-
buf[i*4] = 255 - r;
2751-
buf[i*4+1] = 255 - g;
2752-
buf[i*4+2] = 255 - b;
2753-
} else if (mode == THRESHOLD) {
2754-
unsigned char t = (grey > 127) ? 255 : 0;
2755-
buf[i*4] = buf[i*4+1] = buf[i*4+2] = t;
2741+
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf.data());
2742+
if (mode == GRAY || mode == INVERT || mode == THRESHOLD || mode == OPAQUE) {
2743+
for (int i = 0; i < total; i++) {
2744+
int r=buf[i*4],g=buf[i*4+1],b=buf[i*4+2];
2745+
int grey=(r+g+b)/3;
2746+
if (mode==GRAY) { buf[i*4]=buf[i*4+1]=buf[i*4+2]=(unsigned char)grey; }
2747+
else if (mode==INVERT) { buf[i*4]=255-r; buf[i*4+1]=255-g; buf[i*4+2]=255-b; }
2748+
else if (mode==THRESHOLD) { unsigned char t=(grey>param*255)?255:0; buf[i*4]=buf[i*4+1]=buf[i*4+2]=t; }
2749+
else if (mode==OPAQUE) { buf[i*4+3]=255; }
27562750
}
2757-
}
2758-
#ifndef __EMSCRIPTEN__
2759-
glDrawPixels(winWidth, winHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf.data());
2760-
#else
2761-
// WASM: upload pixels via texture blit
2762-
GLuint tex; glGenTextures(1,&tex);
2763-
glBindTexture(GL_TEXTURE_2D,tex);
2764-
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,winWidth,winHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,buf.data());
2765-
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
2766-
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
2767-
glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,tex);
2768-
glColor4f(1,1,1,1);
2769-
glBegin(GL_QUADS);
2770-
glTexCoord2f(0,1);glVertex2f(0,0);
2771-
glTexCoord2f(1,1);glVertex2f(winWidth,0);
2772-
glTexCoord2f(1,0);glVertex2f(winWidth,winHeight);
2773-
glTexCoord2f(0,0);glVertex2f(0,winHeight);
2774-
glEnd();
2775-
glDisable(GL_TEXTURE_2D); glDeleteTextures(1,&tex);
2776-
#endif
2777-
}
2778-
void PApplet::loadPixels() {
2779-
int total = winWidth * winHeight;
2780-
pixels.resize(total);
2781-
2782-
::std::vector<unsigned char> rgba(total * 4);
2783-
glReadPixels(0, 0, winWidth, winHeight, GL_RGBA, GL_UNSIGNED_BYTE, rgba.data());
2784-
2785-
// glReadPixels returns rows bottom-to-top; Processing's pixels[] is
2786-
// top-to-bottom (row 0 = top of window), so flip rows on the way in.
2787-
for (int y = 0; y < winHeight; y++) {
2788-
for (int x = 0; x < winWidth; x++) {
2789-
int di = y * winWidth + x;
2790-
int si = (winHeight - 1 - y) * winWidth + x;
2791-
unsigned char r = rgba[si*4 + 0];
2792-
unsigned char g = rgba[si*4 + 1];
2793-
unsigned char b = rgba[si*4 + 2];
2794-
unsigned char a = rgba[si*4 + 3];
2795-
pixels[di] = (a << 24) | (r << 16) | (g << 8) | b; // ARGB format
2751+
} else if (mode == BLUR) {
2752+
int radius = ::std::max(1,(int)param);
2753+
::std::vector<unsigned char> tmp(buf);
2754+
for (int y=0;y<h;y++) for (int x2=0;x2<w;x2++) {
2755+
int sr=0,sg=0,sb=0,sa=0,cnt=0;
2756+
for (int dy=-radius;dy<=radius;dy++) for (int dx=-radius;dx<=radius;dx++) {
2757+
int nx=x2+dx,ny=y+dy;
2758+
if(nx<0||nx>=w||ny<0||ny>=h) continue;
2759+
int j=(ny*w+nx)*4;
2760+
sr+=tmp[j]; sg+=tmp[j+1]; sb+=tmp[j+2]; sa+=tmp[j+3]; cnt++;
2761+
}
2762+
int i=(y*w+x2)*4;
2763+
buf[i]=sr/cnt; buf[i+1]=sg/cnt; buf[i+2]=sb/cnt; buf[i+3]=sa/cnt;
2764+
}
2765+
} else if (mode == ERODE || mode == DILATE) {
2766+
::std::vector<unsigned char> tmp(buf);
2767+
for (int y=0;y<h;y++) for (int x2=0;x2<w;x2++) {
2768+
int best=-1;
2769+
for (int dy=-1;dy<=1;dy++) for (int dx=-1;dx<=1;dx++) {
2770+
int nx=x2+dx,ny=y+dy;
2771+
if(nx<0||nx>=w||ny<0||ny>=h) continue;
2772+
int j=(ny*w+nx)*4;
2773+
int lum=(tmp[j]+tmp[j+1]+tmp[j+2])/3;
2774+
if(best<0||(mode==ERODE?lum<best:lum>best)) best=lum;
2775+
}
2776+
int i=(y*w+x2)*4;
2777+
buf[i]=buf[i+1]=buf[i+2]=(unsigned char)best;
27962778
}
27972779
}
2798-
}
27992780

28002781
void PApplet::updatePixels() {
28012782
int total = winWidth * winHeight;

0 commit comments

Comments
 (0)