@@ -2735,67 +2735,48 @@ void PApplet::tint(float r, float g, float b, float a) {
27352735void PApplet::noTint (){doTint=false ;}
27362736
27372737void 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
28002781void PApplet::updatePixels () {
28012782 int total = winWidth * winHeight;
0 commit comments