Drawing to p5.Image instead of to canvas

2019-08-03 13:17发布

问题:

Given a loaded png image as a template, I want to enable a user to trace elements of the image. In p5, this is easy:

setup() {
    // Load image
    var img = loadImage('...');
    image(img, 0, 0);
}

draw() {
    ellipse(mouseX, mouseY, 2, 2);
}

However, I want to then be able to save only the ellipses (without the underlying image). Is there a way to write to an Image instead of directly down to the canvas, so that I can lift the pixels of the trace without taking the original image with it?

My current plans are one of:

  • Overlay a second p5 instance, and draw on a transparent canvas overlaid on the image... But this seems harder to maintain, and may suffer from the DOM being out of perfect alignment
  • Instead of using ellipse, write to a createImage-generated pixel array... But this seems slow and unpleasant.

Caveat: The image is a p5.Image, so overlaying on top of a <img> won't be enough.

回答1:

You can use the createGraphics() function to create an instance of p5.Renderer. You can then draw to the p5.Renderer and then overlay it on top of the image. Then you can access the pixel array of the p5.Renderer to get just the overlay, not the image.

Here is an example:

var img;
    var pg;
    
    function preload() {
      img = loadImage("https://www.gravatar.com/avatar/06ce4c0f7ee07cf79c81ac6602f5d502?s=32&d=identicon&r=PG");
    }
    
    function setup(){
      createCanvas(300, 600);
      pg = createGraphics(300, 300);
    }
    
    function mousePressed(){
      pg.fill(255, 0, 0);
      pg.ellipse(mouseX, mouseY, 20, 20);
    }
    
    function draw() {
      image(img, 0, 0, 300, 300);
      image(pg, 0, 0);
      image(pg, 0, 300);
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.js"></script>
Click in the image to draw to the buffer below it! (View as full page to see the buffer.)

More info can be found in the reference.

By the way there is a p5.js tag.