在处理中,如何将 window 的一部分保存为图像?

In Processing, how can I save part of the window as an image?

我正在使用 Fedora 20 下的 Processing,我想显示在屏幕的一部分上移动的对象的延伸轨迹的图像,每个对象都显示在轨迹末端的当前位置。为避免必须记录轨迹的所有坐标,我使用 save("image.png"); 保存目前的轨迹,然后绘制对象。在下一帧中,我使用 img = loadImage("image.png"); 来恢复到目前为止制作的轨道,没有对象,它们仍然在它们以前的位置。我将轨道扩展到它们的新位置,然后使用 save("image.png"); 来保存扩展轨道,仍然没有对象,为下一轮循环做好准备。然后,我将对象绘制在它们延伸轨道末端的新位置。通过这种方式,连续的循环显示了物体在前进,它们之前的位置作为它们后面的轨迹。

这在图像是整个框架的测试中效果很好,但现在我需要将该显示放在整个框架的一角,其余部分保持不变。我希望 createImage(...) 会是答案,但我找不到任何详细信息。

此处提出的类似问题有以下建议:"The PImage class contains a save() function that exports to file. The API should be your first stop for questions like this." 当然我已经看过了 API,但我认为它在这里没有帮助,除非我必须创建图像逐个像素地保存,在这种情况下,我希望它能大大降低速度。

所以我的问题是:在 Processing 中,我可以仅将帧的一部分保存和恢复为图像,而不影响帧的其余部分吗?

我一直在研究这个。我能找到大量的草图参考、教程和示例,它们可以保存和加载整个框架,但没有简单的方法可以将框架的一部分保存和恢复为图像,这对我来说似乎很奇怪。我可能可以使用 Pimage 来做到这一点,但这似乎需要在要在那里绘制的所有内容之前使用大量的 image.

我费了九牛二虎之力:我创建了一个蒙版图像(参见 this Processing reference)整个帧的大小。遮罩被定义为代表不透明度的灰色区域,因此白色,零不透明度 (0) 是透明的,黑色,完全不透明 (255) 完全隐藏背景图像,因此:

{ size (1280,800);
  background(0); // whole frame is transparent..
  fill(255); // ..and..
  rect(680,0,600,600); // ..smaller image area is now opaque
  save("[path to sketch]/mask01.jpg");
}

void draw(){}

然后在我的主要代码中使用:

PImage img, mimg;

img = loadImage("image4.png"); // The image I want to see ..
// .. including the rest of the frame which would obscure previous work
mimg = loadImage("mask01.jpg"); // create the mask
//apply the mask, allowing previous work to show though
img.mask(mimg); 
// display the masked image
image(img, 0, 0); 

如果没有更好的建议,我会接受这个作为答案。

void setup(){
  size(640, 480);
  background(0);

  noStroke();
  fill(255);
  rect(40, 150, 200, 100);
}

void draw(){

}

void mousePressed(){
  PImage img  =get(40, 150, 200, 100);
  img.save("test.jpg");
}

旧闻,但这里有一个答案:您可以使用像素阵列和数学。

假设这是您的视口:

您可以使用 loadPixels(); 将视口的当前内容填充到 pixels[] 数组,然后从该数组中获取您想要的像素。

在给定的示例中,这是一种过滤不需要的像素的方法:

void exportImage() {
  // creating the image to the "desired size"
  PImage img = createImage(600, 900, RGB);
  
  loadPixels();
  int index = 0;
  for(int i=0; i<pixels.length; i++) {
    // filtering the unwanted first 200 pixels on every row
    // remember that the pixels[] array is 1 dimensional, so some math are unavoidable. For this simple example I use the modulo operator.
    if (i % width >= 200) { // "magic numbers" are bad, remember. This is only a simplification.
      img.pixels[index] = pixels[i];
      index++;
    }
  }
  img.updatePixels();
  img.save("test.png");
}

帮助您可能为时已晚,但也许其他人会需要它。不管怎样,玩得开心!