当前位置: 首页 > 知识库问答 >
问题:

在PGraphics上永久绘制(处理)

诸超
2023-03-14
void setup (){
  font = createFont("Pano Bold Kopie.otf", 600);
  size(800, 800, P2D);
  pg = createGraphics(800, 800, P2D);
  pg.beginDraw();
  pg.background(0);
  pg.fill(255);
  pg.textFont(font);
  pg.textSize(400);
  pg.pushMatrix();
  pg.translate(width/2, height/2-140);
  pg.textAlign(CENTER, CENTER);
  pg.text("a", 0 , 0);
  pg.popMatrix();
  pg.endDraw();
}

void draw () {
  copy(pg, 0, 0, width, height, 0, 0, width, height);
  loop();
  int c;

  loadPixels();
  for (int x=0; x<width; x++) {
    for (int y=0; y<height; y++) {
      pg.pixels[mouseX+mouseY*width]=0;
    }
  }
  updatePixels();
}

我的最后一个想法,我还没有尝试实现,是将鼠标触摸过的像素附加到一个列表中,并从这个列表中绘制每一帧。但对我来说,这似乎相当复杂,因为它可能会导致超长的数组需要在原始图像的顶部进行处理。所以,我希望还有别的办法!

编辑:我的目标是创建一个涂抹画笔,因此画笔是一种复制区域从一个部分的图像到其他部分。

共有1个答案

蒋招
2023-03-14

没有必要像那样手动复制像素。PGraphics类扩展了pImage,这意味着您可以简单地使用Image(pg,0,0)来呈现它;例如,

你可以做的另一件事是一个老把戏来淡化背景:不完全清除像素,你可以在没有笔画的情况下呈现一个略不透明的草图大小的矩形。

下面是一个基于代码的快速概念证明:

PFont font;
PGraphics pg;

void setup (){
  //font = createFont("Pano Bold Kopie.otf", 600);
  font = createFont("Verdana",600);

  size(800, 800, P2D);
  // clear main background once
  background(0);
  // prep fading background
  noStroke();
  // black fill with 10/255 transparnecy
  fill(0,10);

  pg = createGraphics(800, 800, P2D);
  pg.beginDraw();
  // leave the PGraphics instance transparent
  //pg.background(0);
  pg.fill(255);
  pg.textFont(font);
  pg.textSize(400);
  pg.pushMatrix();
  pg.translate(width/2, height/2-140);
  pg.textAlign(CENTER, CENTER);
  pg.text("a", 0 , 0);
  pg.popMatrix();
  pg.endDraw();
}

void draw () {
  // test with mouse pressed
  if(mousePressed){
    // slowly fade/clear the background by drawing a slightly opaque rectangle
    rect(0,0,width,height);
  }
  // don't clear the background, render the PGraphics layer directly
  image(pg, mouseX - pg.width / 2, mouseY - pg.height / 2);
}
PFont font;
PGraphics pg;

int pressX;
int pressY;

void setup (){
  //font = createFont("Pano Bold Kopie.otf", 600);
  font = createFont("Verdana",600);

  size(800, 800, P2D);
  // clear main background once
  background(0);
  // prep fading background
  noStroke();
  // black fill with 10/255 transparnecy
  fill(0,10);

  pg = createGraphics(800, 800, JAVA2D);
  pg.beginDraw();
  // leave the PGraphics instance transparent
  //pg.background(0);
  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("a", 0 , 0);
  pg.popMatrix();
  pg.endDraw();
}

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

void mousePressed(){
  pressX = mouseX;
  pressY = mouseY;
}

void mouseDragged(){
  // sample the colour where mouse was pressed
  color sample = pg.get(pressX,pressY);
  // calculate the distance from where the "smudge" started to where it is
  float distance = dist(pressX,pressY,mouseX,mouseY);
  // map this distance to transparency so the further the distance the less smudge (e.g. short distance, high alpha, large distnace, small alpha)
  float alpha = map(distance,0,30,255,0);
  // map distance to "brush size"
  float size = map(distance,0,30,30,0);
  // extract r,g,b values
  float r = red(sample);
  float g = green(sample);
  float b = blue(sample);
  // set new r,g,b,a values
  pg.beginDraw();
  pg.fill(r,g,b,alpha);
  pg.ellipse(mouseX,mouseY,size,size);
  pg.endDraw();
}

正如评论提到的,一个想法是样本颜色在压力,然后使用样本颜色和褪色,因为你的拖动远离源区。这显示了简单地读取单个像素。您可能希望尝试采样/读取更多的像素(例如矩形或椭圆)。

此外,上面的代码没有被优化。一些事情可以加快一点,比如读取像素,提取颜色,计算距离,等等。

例如:

void mouseDragged(){
  // sample the colour where mouse was pressed
  color sample = pg.pixels[pressX + (pressY * pg.width)];
  // calculate the distance from where the "smudge" started to where it is (can use manual distance squared if this is too slow)
  float distance = dist(pressX,pressY,mouseX,mouseY);
  // map this distance to transparency so the further the distance the less smudge (e.g. short distance, high alpha, large distnace, small alpha)
  float alpha = map(distance,0,30,255,0);
  // map distance to "brush size"
  float size = map(distance,0,30,30,0);
  // extract r,g,b values
  int r = (sample >> 16) & 0xFF; // Like red(), but faster
  int g = (sample >> 8) & 0xFF;
  int b =  sample & 0xFF;
  // set new r,g,b,a values
  pg.beginDraw();
  pg.fill(r,g,b,alpha);
  pg.ellipse(mouseX,mouseY,size,size);
  pg.endDraw();
}
 类似资料:
  • null null 问题是,在ArrayList中有相当多的形状之后,paintComponent()方法的执行会变慢。 例如,自定义画笔。 在画布上拖动画笔时,我必须向ArrayList添加一个类型为“CustomBrush extends Shape”的新形状 所以只需一次划动,我就可以在ArrayList中得到数百个形状 问题是: 如何将100个形状对象“打包”成一个,使一次笔触成为Arra

  • 问题内容: 我想将“:/ home / me / play /”值添加到PATH ,以安装Play!框架。 所以我运行了这个命令: 有效。但是在我下次检查时,该值又变回了原来的值。 所以我想我没有“保存”新值,对吗? 你是怎样做的? 问题答案: 加 给你并执行 为了立即反映对您当前终端实例的更改。

  • 我的最终目标是创建一个“隧道效果”,因为我将一个rect绘制到一个缓冲区,将该缓冲区复制到另一个缓冲区,在随后的draw()中,将第二个缓冲区复制回第一个缓冲区,只是稍微小一点,然后在该缓冲区上绘制并重复。 我完全被这里发生的事情难倒了。 这是一个非常愚蠢的示例,但它证明了这个概念是正确的:我绘制到,复制到,将复制回,然后输出到主上下文。 但是看看当我在draw()循环中尝试这样做时会发生什么:

  • 问题内容: Android 8的电池消耗改进对用户来说不错,但是我担心我的服务是否能按预期工作。 首先:谢谢您的任何建议,但我不能只安排服务时间。我想让一个-like关键字监听器一直在后台运行。它将基于开源的Pocketsphinx-android库。我知道这会消耗大量电池电量,因此我会通知用户。 我们可以在android 8+上创建永久的后台服务吗?我需要在gradle中定位android 8,

  • 问题内容: 我试图将目录添加到我的路径,以便它始终位于我的Linux路径中。我试过了: 这可行,但是每次我退出终端并启动新的终端实例时,此路径都会丢失,因此我需要再次运行export命令。 我该如何做才能将其永久设置? 问题答案: 有多种方法可以做到这一点。实际解决方案取决于目的。 变量值通常存储在分配列表或在系统或用户会话开始时运行的Shell脚本中。如果使用Shell脚本,则必须使用特定的Sh

  • 问题内容: 这将使用 临时的 302 HTTP状态代码重定向请求: 但是是否可以使用 永久的 301 HTTP状态代码重定向它? 问题答案: 您需要手动设置响应状态和标题。 将状态设置为之前将无效,否则将其设置为之后。