【问题标题】:High-Resolution Processing Output高分辨率处理输出
【发布时间】:2022-03-10 20:22:55
【问题描述】:

我正在寻求有关编程语言/环境处理的帮助。

我对 Processing 还很陌生,我正在使用来自 openprocessing.org 的某个人的一段代码进行试验。我真的很喜欢这段代码提供的视觉效果,我想进一步使用它。不幸的是,输出的分辨率非常低。因此,我正在寻找能够帮助我弄清楚如何 a) 增加生成的形状的大小或分辨率以及 b) 将所有内容保存为 pdf 文件的人。

您可以在此处找到正在运行的原始代码:https://www.openprocessing.org/sketch/377730

这是代码:

import java.util.Arrays;
float[][] z, v, a;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  size(512, 512);
  colorMode(RGB, 2);
  z = new float[width][height];
  v = new float[width][height];
  a = new float[width][height];
  loadPixels();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void draw() {
  for (int x = 1; x < width-1; x++) {
    for (int y = 1; y < height-1; y++) {
      a[x][y] = (v[x-1][y] + v[x+1][y] + v[x][y-1] + v[x][y+1])/4 - v[x][y];
    }
  }
  for (int x = 1; x < width-1; x++) {
    for (int y = 1; y < height-1; y++) {
      v[x][y] += a[x][y];
      z[x][y] += v[x][y];
      pixels[width*y+x] = color(sin(z[x][y]) + 1, cos(z[x][y]), 1);
    }
  }
  updatePixels();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void move() {
  if (mouseX > -1    &&    mouseX < width    &&    mouseY > -1    &&    mouseY < height) {
    v[mouseX][mouseY] = randomGaussian() * TAU;
  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void mouseClicked() { move(); }

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void mouseDragged() { move(); }

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void keyPressed() {
  noLoop();
  for (int x = 0; x < width; x++)    Arrays.fill(z[x], 0);
  for (int x = 0; x < width; x++)    Arrays.fill(v[x], 0);
  loop();
}

到目前为止,我已经尝试过一种在 Processing-Forum 上发布的所谓的高分辨率方法,但它并没有为我工作,至少在我正在使用的上述代码的上下文中没有。这是来自论坛的一段代码,它演示了一个用户以高分辨率保存处理输出的输出的方式:

int dim = 5000;
int dimScreen = dim/10;
color c1 = #AFA786;
color c2 = #000000;

void setup() { size(dimScreen,dimScreen); }
void draw()  { exampleSketch(); }

void exampleSketch() {
  for (int y=0; y<=height; y++) {
    stroke(lerpColor(c1,c2,float(y)/height));
    line(0,y,width,y);
  }
  stroke(#FFFFFF);
  fill(#BBBBBB);
  ellipse(width/2, height/2, width/2, height/2);
  line(0, 0, width, height);
}

void keyPressed() {
  if (key ==' ') {
    g = createGraphics(dim,dim,JAVA2D);
    this.height = dim;
    this.width = dim;
    g.beginDraw();
    exampleSketch();
    g.endDraw();
    save("result.png");
    println("screenshot saved");
    this.height = dimScreen;
    this.width = dimScreen;
  }
}

我非常感谢任何精通处理和 Java 的人来帮助我。非常感谢,祝您晚安。

这是我在第一个代码中实现第二个代码的尝试:

import processing.pdf.*;
import java.util.Arrays;
float[][] z, v, a;

int dim = 900;
int dimScreen = dim/10;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  size(900, 900);
  smooth(8);
  colorMode(RGB, 2);
  z = new float[width][height];
  v = new float[width][height];
  a = new float[width][height];
  loadPixels();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void draw()  { exampleSketch(); }


void exampleSketch() {

  for (int x = 1; x < width-1; x++) {
    for (int y = 1; y < height-1; y++) {
      a[x][y] = (v[x-1][y] + v[x+1][y] + v[x][y-1] + v[x][y+1])/4 - v[x][y];
    }
  }
  for (int x = 1; x < width-1; x++) {
    for (int y = 1; y < height-1; y++) {
      v[x][y] += a[x][y];
      z[x][y] += v[x][y];
      pixels[width*y+x] = color(sin(z[x][y]) + 1, cos(z[x][y]), 1);
    }
  }
  updatePixels();


}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void move() {
  if (mouseX > -1    &&    mouseX < width    &&    mouseY > -1    &&    mouseY < height) {
    v[mouseX][mouseY] = randomGaussian() * TAU;

  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void mouseClicked() { move(); }

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void mouseDragged() { move(); }


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void keyPressed() {
  if (key ==' ') {
    g = createGraphics(dim,dim,JAVA2D);
    this.height = dim;
    this.width = dim;
    g.beginDraw();
    exampleSketch();
    g.endDraw();
    save("result2.png");
    println("screenshot saved");
    this.height = 900;
    this.width = 900;
  }
}

编辑:两个屏幕截图比较了在实施 George 的白色背景解决方案之前和之后的不同视觉结果:

【问题讨论】:

  • 您能否更具体地说明第二段代码的哪些问题?另外,你的目标是什么分辨率?您希望效果如何扩展?
  • 感谢您的快速回复!我尝试将第二个代码中的保存方法实现到第一个代码中(我对处理和 Java 工作原理的了解有限)。我将修改后的代码添加到我上面的原始帖子中。不幸的是,保存的 png 不包含任何内容。
  • 您的目标是什么分辨率?您是否希望输出更大,或者草图窗口更大,或者您是否希望草图窗口保持不变但只有更大的颜色斑点?是必须导出为pdf,还是导出为图片文件没问题?
  • 我希望使输出更大或颜色斑点更大。基本上,我打算稍后将结果图像带入 Photoshop 并打印(理想情况下,分辨率为 300dpi,图像不会被像素化)。图像文件导出 (.tiff) 或 pdf 都可以。

标签: java


【解决方案1】:

您实际上是在谈论两个不同的事情:

第一件事:使彩色斑点变大。这有点烦人,因为算法使用的是像素数组,所以并不像调用scale()函数那么简单。

事实上,由于该算法适用于像素,任何改变分辨率的简单方法都会变得像素化。

您在论坛上得到的解决方案是绘制到屏幕外缓冲区,这实际上不会改变 blob 的大小。 更改 blob 大小的唯一方法是更改​​算法。

您也许可以修改操作数组的方式,使 blob 更大,但老实说,我并不完全了解数组现在在做什么,这很难提供帮助。

第二件事:导出为图片。

最简单的方法是调用save("ImageNameHere.png") 函数。这将创建一个与您的草图大小相同的图像,其中包含调用该函数时屏幕上显示的任何内容。

您在论坛上找到的解决方案使用了屏幕外缓冲区,但同样:这对 blob 的大小没有帮助。您确实可以使用屏幕外缓冲区进行绘制到比草图窗口大的图像,但这只是你想要的一半。如果您的 blob 仍然很小,则以这种方式保存是没有用的!

所以,我对您的建议是先修复 Thing One,然后提出一种生成更大 blob 的算法。然后我们可以讨论缩放和导出为图像,一旦算法正常工作,这将非常容易。

【讨论】:

  • 好的。非常感谢您到目前为止的帮助。我将坐下来尝试更全面地了解这里的数组发生了什么,以便操纵 blob 的大小。如果您能给我任何进一步的建议或对我如何去做这件事有任何想法,那就太好了。再次感谢,晚安。
  • 此外,您认为发布这个特定问题是否有意义(创建更大的斑点,甚至使用另一种方法创建相同的效果,而不是像版本 I' m 现在使用)作为 StackOverflow 上的一个新问题?
  • @JohnGalt 老实说,这对于 Stack Overflow 来说可能有点太宽泛了。有很多不同的方法可以解决这个问题,而 Stack Overflow 并不是为一般的“我该怎么做”类型的问题而构建的。与互联网上的大多数地方相同。回答具体的“我尝试了 X,预期 Y,但得到了 Z”类型的问题要容易得多。
  • @JohnGalt 我会说我对“我该怎么做”类型的问题的一般回答是将您的问题分解为更小的步骤。问问自己您是如何做到的会用一张纸和一支铅笔来做这件事,然后用英语写下这些说明。当你把它写下来后,你就可以开始实施你的算法了。
  • 好的,再次感谢您的帮助。从长远来看,当我分解并调查我自己需要的答案时,我会从整个事情中得到更多。
【解决方案2】:

除了 Kevin 的回答,您还可以使用JVisualVM 查看大部分 CPU 时间都花在了哪些地方。在不同时间对 CPU 进行采样和分析后,令人惊讶的是,大部分时间都在计算 RGB 值:

优化时最好从占用CPU最多的函数入手。

这是一个草图版本,它使用默认的 0-255 RGB 范围并计算内联的 RGB 值(将 A、R、G、B 字节放在一起):

import processing.pdf.*;
import java.util.Arrays;
float[][] z, v, a;

int dim = 900;
int dimScreen = dim/10;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  size(900, 900);
  smooth(8);
  //colorMode(RGB, 2);
  z = new float[width][height];
  v = new float[width][height];
  a = new float[width][height];
  loadPixels();

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void draw()  { exampleSketch(); }


void exampleSketch() {

  int r,g,b = 255;
  for (int x = 1; x < width-1; x++) {
    for (int y = 1; y < height-1; y++) {
      a[x][y] = (v[x-1][y] + v[x+1][y] + v[x][y-1] + v[x][y+1]) * .25 - v[x][y];
    //}
  //}
//  //for (int x = 1; x < width-1; x++) {
    //for (int y = 1; y < height-1; y++) {
      v[x][y] += a[x][y];
      z[x][y] += v[x][y];
      r = ((int)((sin(z[x][y]) + 1) * 128) << 16);
      g = ((int)((cos(z[x][y]) * 128)) << 8);
      pixels[width*y+x] = 0xff000000 | r | g | b;
    }
  }
  updatePixels();
  fill(0);
  text((int)frameRate+"fps",15,15);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void move() {
  if (mouseX > -1    &&    mouseX < width    &&    mouseY > -1    &&    mouseY < height) {
    v[mouseX][mouseY] = randomGaussian() * TAU;

  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void mouseClicked() { move(); }

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void mouseDragged() { move(); }


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int screenshotCount=1;
void keyPressed() {
  if (key ==' ') {
    save("result"+nf(screenshotCount,4)+".png");
    println("screenshot saved");
  }
}

//http://stackoverflow.com/questions/40350644/high-resolution-processing-output

更新: 这是一个修改后的函数,它映射值以使背景为白色:

void exampleSketch() {
  float rv,gv;
  int r,g,b = 255;
  for (int x = 1; x < width-1; x++) {
    for (int y = 1; y < height-1; y++) {
      //compute accumulated value of neighbour cells(left+right+top+bottom), average (/4 or * .25) then subtract the current cell from v
      a[x][y] = (v[x-1][y] + v[x+1][y] + v[x][y-1] + v[x][y+1]) * .25 - v[x][y];
      //increment current v cell by the current accumulated cell
      v[x][y] += a[x][y];
      //increment current z (final/result) cell by the updated v cell
      z[x][y] += v[x][y];
      //in short z[x][y] += v[x][y] + ((v[-1][0] + v[+1][0] + v[0][-1] + v[0][+1]) / 4 - v[x][y])
      //scale sin(z) and cos(z) results to 0-255: sin/cos returns -1.0 to 1.0 then 1.0 is added -> 0.0 to 2.0 , then 128 is multiplied = 0-255
      rv = (sin(z[x][y]) + 1.0) * 128;
      gv = (cos(z[x][y]) + 1.0) * 128;
      //contrain to 0-255
      if(rv < 0)   rv = 0;
      if(rv > 255) rv = 255;
      if(gv < 0)   gv = 0;
      if(gv > 255) gv = 255;
      //cast to int and shift
      r = ((int)(rv) << 16);
      g = ((int)(gv) << 8);
      //alpha (0xff000000) cobined with r , g, b 
      int argb = 0xff000000 | r | g | b;
      pixels[width*y+x] = argb;
    }
  }
  updatePixels();
  fill(0);
  text((int)frameRate+"fps",15,15);
}

这是我可以保存的:

更新 2: 这是一个计算透明度值而不是白色的版本:

import processing.pdf.*;
import java.util.Arrays;
float[][] z, v, a;

int dim = 900;
int dimScreen = dim/10;

PImage canvas;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  size(900, 900);
  smooth(8);
  //colorMode(RGB, 2);
  z = new float[width][height];
  v = new float[width][height];
  a = new float[width][height];
  loadPixels();


  canvas = createImage(width,height,ARGB);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void draw()  { exampleSketch(); }


void exampleSketch() {
  float rs,gc,rv,gv;
  int r,g,b = 255;
  for (int x = 1; x < width-1; x++) {
    for (int y = 1; y < height-1; y++) {
      //compute accumulated value of neighbour cells(left+right+top+bottom), average (/4 or * .25) then subtract the current cell from v
      a[x][y] = (v[x-1][y] + v[x+1][y] + v[x][y-1] + v[x][y+1]) * .25 - v[x][y];
      //increment current v cell by the current accumulated cell
      v[x][y] += a[x][y];
      //increment current z (final/result) cell by the updated v cell
      z[x][y] += v[x][y];
      //in short z[x][y] += v[x][y] + ((v[-1][0] + v[+1][0] + v[0][-1] + v[0][+1]) / 4 - v[x][y])
      //scale sin(z) and cos(z) results to 0-255
      rs = sin(z[x][y]) + 1.0;
      gc = cos(z[x][y]) + 1.0;
      rv = rs * 128;
      gv = gc * 128;
      //contrain to 0-255
      if(rv < 0)   rv = 0;
      if(rv > 255) rv = 255;
      if(gv < 0)   gv = 0;
      if(gv > 255) gv = 255;
      //cast to int and shift
      r = ((int)(rv) << 16);
      g = ((int)(gv) << 8);
      //average sin/cos results = use the sin/cos results used for red/green channels, scale them by half (128) brightness and add them up
      //then subtract that from the max (255) to invert the alpha(transparency) value
      int alpha = 255-(int)((rs * 128) + (gc * 128));
      int argb = alpha << 24 | r | g | b;
      canvas.pixels[width*y+x] = argb;
    }
  }
  canvas.updatePixels();
  image(canvas,0,0);
  fill(0);
  text((int)frameRate+"fps",15,15);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void move() {
  if (mouseX > -1    &&    mouseX < width    &&    mouseY > -1    &&    mouseY < height) {
    v[mouseX][mouseY] = randomGaussian() * TAU;

  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void mouseClicked() { move(); }

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void mouseDragged() { move(); }


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int screenshotCount=1;
void keyPressed() {
  if (key ==' ') {
    canvas.save("result"+nf(screenshotCount,4)+".png");
    println("screenshot saved");
  }
}

很遗憾,我没有时间深入了解更多细节并提供快速有效的解决方案,但我可以提供一些可能会有所帮助的建议:

这看起来像是一个简化的BZ or Grey Scott reaction diffusion 模拟:

查看Daniel Shiffman's video tutorial on it:它将帮助您更好地理解算法并编写更高效的实现。

我想到了一些更核心的加速方法:

  1. 在 GPU 上并行化任务,将算法重写为 Processing GLSL shader (PShader) - 此外,如果您不介意实现略有不同,调整 Shadertoy reaction diffusion fragment shaders 以作为 PShader 运行可能会更容易(例如 this onethis one)
  2. 在 CPU 上并行化任务(参见 Java Multiprocessing resources - 排序干材料)

【讨论】:

  • 嗨。乔治。也非常感谢您的所有投入!今天我将彻底检查所有内容,一旦我遇到任何对我当前问题有用的结果,我将再次在这里发布。
  • 当乔治。我永远喜欢你的答案。我几乎没有尝试回答这个问题,因为我知道你会带着把我从水里吹出来的东西过来!
  • 嗨,George,我将继续研究代码以及您提供的所有资源,并寄希望于最终解决这个问题。我有一个小的后续问题,您可能可以帮助我,因为我还没有完全掌握代码。您是否认为有办法将背景颜色(当前为灰色)更改为白色甚至透明?或者,也许您可​​以指出我在代码中确定背景颜色的位置。我还没有完全明白。再次感谢所有帮助。
  • 请注意以下几行:r = ((int)((sin(z[x][y]) + 1) * 128) &lt;&lt; 16); g = ((int)((cos(z[x][y]) * 128)) &lt;&lt; 8); pixels[width*y+x] = 0xff000000 | r | g | b;b 部分很明显,只需在循环之前更改值,在本节中:int r,g,b = 255; rg 被计算,但 sin()cos 被使用,所以玩起来非常灵活with 因为这两个函数都返回一个介于 -1.0 和 1.0 之间的值,因此使用当前的 128。增加/减少这些值将控制红色/绿色的数量
  • @JohnGalt 我实际上在答案中添加了一个示例,将颜色映射为白色。
猜你喜欢
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-16
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多