模糊边缘不断恢复 100% 不透明度(处理中)

Posted

技术标签:

【中文标题】模糊边缘不断恢复 100% 不透明度(处理中)【英文标题】:Blurred edges keep regaining 100% opacity (Processing) 【发布时间】:2020-02-01 11:03:07 【问题描述】:

我正在尝试通过以下代码在处理中创建一个边缘模糊的圆形画笔。圆形是逐像素绘制的,因为在实际版本中,我尝试使用取自PGraphicpg 的像素进行绘制。

PFont font;
PGraphics pg;
int X;
int Y;
int rad = 20;

void setup ()
    size(800, 800, P2D);
    background(0);
    noStroke();

    pg = createGraphics(800, 800, JAVA2D);
    pg.beginDraw();
    pg.fill(255);
    pg.noStroke();
    pg.textFont(font);
    pg.textSize(400);
    pg.pushMatrix();
    pg.translate(width/2, height/2-140);
    pg.textAlign(CENTER, CENTER);
    pg.text("b", 0 , 0);
    pg.popMatrix();
    pg.endDraw();


void draw () 
    image(pg,0,0);


void mousePressed()
    X = mouseX;
    Y = mouseY;


void mouseDragged()

    for (int x=0; x<rad; x++) 
        for (int y=0; y<rad; y++) 
        float distance = sqrt(pow(x,2)+pow(y,2));
        float alpha = 255-map(distance,0,rad,0,255);

            if (sqrt(pow(x,2)+pow(y,2)) < rad)
                pg.beginDraw();
                pg.set(mouseX+x,mouseY+y,color(255,255,255, alpha));
                pg.set(mouseX-x,mouseY+y,color(255,255,255, alpha));
                pg.set(mouseX+x,mouseY-y,color(255,255,255, alpha));
                pg.set(mouseX-x,mouseY-y,color(255,255,255, alpha));
                pg.endDraw();
            
        
    

【问题讨论】:

【参考方案1】:

添加一个“背景(0);”在“图像(pg,0,0);”之前在您的绘图方法中,这样您每次都重置背景,如果您不这样做,程序将继续在彼此的顶部绘制每一帧图像,这将使低不透明度像素每帧缓慢增加不透明度,直到达到 100 %

void draw () 
  background(0);
  image(pg,0,0);

编辑: 在测试你的代码后,我注意到你创建这些圆圈的方式存在问题,使其运行速度非常慢(每一帧你都通过双 for 循环绘制一个圆圈)并且还给出了奇怪的黑边问题,所以这是我所做的:

首先我使用你的变量 pg 并在启动时在其上画了一个圆圈,然后我声明了另一个 PGraphics 'pg_all',我在每次调用 mousedrag 方法时画了一个 pg,我在多个背景上测试它似乎工作好的,这是最终代码,如果您不了解某个部分或想以不同的方式进行操作,请告诉我:

PFont font;
PGraphics pg;
PGraphics pg_all;
int X;
int Y;
int rad = 20;

void setup ()
  size(800, 800, P2D);
  background(0);
  noStroke();

  pg_all = createGraphics(800, 800, JAVA2D);
  pg_all.beginDraw();
  pg_all.endDraw();

  pg = createGraphics(800, 800, JAVA2D);
  pg.beginDraw();
  for (int x=0; x<rad; x++) 
    for (int y=0; y<rad; y++) 
      float distance = sqrt(pow(x,2)+pow(y,2));
      float alpha = 255-map(distance,0,rad,0,255);

      if (sqrt(pow(x,2)+pow(y,2)) < rad)
        pg.beginDraw();
        pg.set(20+x,20+y,color(255,255,255, alpha));
        pg.set(20-x,20+y,color(255,255,255, alpha));
        pg.set(20+x,20-y,color(255,255,255, alpha));
        pg.set(20-x,20-y,color(255,255,255, alpha));
        pg.endDraw();
      
    
  
  pg.endDraw();


void draw ()    
  background(0);
  image(pg_all,0,0); 


void mouseDragged()
  X = mouseX;
  Y = mouseY;

  pg_all.beginDraw();
  pg_all.image(pg,X-rad,Y-rad);
  pg_all.endDraw();

【讨论】:

谢谢!不幸的是,这只是部分帮助,因为应该透明的东西只是变成了黑色。我用一个例子编辑了我的答案。你知道如何解决这个问题吗? @YOUSFIMohamedWalid 内部循环中的pg.beginDraw()pg.endDraw() 语句是多余的,可能会减慢PGraphics 的生成速度。对于pg,40x40 的大小就足够了。【参考方案2】:

创建一个将单个点绘制到PGraphics 对象的函数:

void DrawPen(PGraphics pg, int cptX, int cptY, int r) 
    pg.beginDraw();
    for (int x = 0; x < r; ++x) 
        for (int y = 0; y < r; ++y) 
          float distance = sqrt(x*x + y*y);
          float alpha = 255-map(distance,0,r,0,255);
          if (distance < r) 
              pg.set(cptX+x,cptY+y,color(255,255,255, alpha));
              pg.set(cptX-x,cptY+y,color(255,255,255, alpha));
              pg.set(cptX+x,cptY-y,color(255,255,255, alpha));
              pg.set(cptX-x,cptY-y,color(255,255,255, alpha));
          
        
    
    pg.endDraw();

setup 中的一个单独的PGraphics 对象上画一个点

PGraphics pg;
PGraphics pg_pen;
int rad = 20;

void setup ()
    size(800, 800, P2D);

    pg = createGraphics(800, 800, JAVA2D);
    pg.beginDraw();
    // [...]
    pg.endDraw();

    pg_pen = createGraphics(2*rad, 2*rad, JAVA2D);
    DrawPen(pg_pen, rad, rad, rad);

当鼠标被拖动时,将pg_pen 混合到当前鼠标位置的公共PGraphics 对象(pg):

void mouseDragged()
    pg.beginDraw();
    pg.image(pg_pen, mouseX-rad, mouseY-rad);
    pg.endDraw();

为了寻求完整性,draw 函数:

void draw () 
    background(0); 
    image(pg,0,0);


[...] 并尝试从白色部分获取颜色以在黑色部分上绘制。

DrawPen函数中添加color参数,并在绘制之前清除笔PGraphics

void DrawPen(PGraphics pg, int cptX, int cptY, int r, color c) 
    pg.beginDraw();
    pg.clear();
    for (int x = 0; x < r; ++x) 
        for (int y = 0; y < r; ++y) 
          float distance = sqrt(x*x + y*y);
          float alpha = 255-map(distance,0,r,0,255);
          if (distance < r) 
              color pc = color(red(c),green(c),blue(c), alpha);
              pg.set(cptX+x,cptY+y,pc);
              pg.set(cptX-x,cptY+y,pc);
              pg.set(cptX+x,cptY-y,pc);
              pg.set(cptX-x,cptY-y,pc);
          
        
    
    pg.endDraw();

在鼠标按下事件回调中获取颜色并改变笔的颜色:

void mousePressed() 
    color c = pg.get(mouseX, mouseY);
    println(c);

    DrawPen(pg_pen, rad, rad, rad, c);

注意,颜色来自pg 对象,而不是来自屏幕。如果你想从屏幕上获取颜色,那么它必须是(没有.pg):

color c = get(mouseX, mouseY);

此外,只要按下任何鼠标(按下而不是拖动),颜色就会发生变化。可能您想在按下鼠标右键时更改颜色并在按下鼠标左键时进行绘画:

void mousePressed() 
    if (mouseButton == RIGHT) 
        color c = pg.get(mouseX, mouseY);
        println(c);
        DrawPen(pg_pen, rad, rad, rad, c);
    

【讨论】:

这就是我的解决方案所做的,还是我错过了什么? @YOUSFIMohamedWalid 我没有阅读您的答案。我只阅读了提到它不能按预期工作的评论。 谢谢,与我尝试的相比,它运行得非常顺利!是否可以通过'c = pg.get(cptX,cptY);'在DrawPen函数中获取鼠标按下的像素的颜色?我简单地尝试过,但没有成功,但这可能是因为我不太了解变量的作用域是如何工作的,这里可能有问题。 @kaktus 你想得到最终图像(pg)中一个点的颜色吗?例如,在mouseDragged 中获取鼠标所在像素的颜色: - void mouseDragged() color c = pg.get(mouseX, mouseY); println(c); ... 谢谢!我觉得你的回答同时也是我对编程的介绍!

以上是关于模糊边缘不断恢复 100% 不透明度(处理中)的主要内容,如果未能解决你的问题,请参考以下文章

jquery赋予图像不透明度并在动画后恢复它

模糊的 IE8 不透明度问题

ULEAD GIF如何制作模糊过渡和透明过渡

使用 CSS 将软边缘应用于图像

Jquery在缩略图上设置不透明度动画,除了选中的那个

c# 用圆角图片做界面 边缘不齐