skip to Main Content

I’m using Paper.js canvas as a source and a simple canvas as a target. Basically copying a part of the visible image via getImageData and pasting it into the target canvas with putImageData.

The pasted image does not have the alpha channel. For example when the copied area includes just a part of an object and the rest should be empty. I tried adding { colorSpace: 'display-p3' } for both functions, but I see that the color space stays srgb and still no alpha channel.

Is it possible to copy/paste the image data with getImageData preserving the alpha channel with Paper.js?

Here’s the copy/paste code.

const rasterTemp = RasterObject.rasterize() // This to reset all the transformations.

const subRasterTemp = rasterTemp.getSubRaster(new data.$paper.Rectangle({
  point: [0, 0], // These and other coordinates are just for the sake of demonstration
  size: [100, 100],
}))

const imageData = subRasterTemp.getImageData(new data.$paper.Rectangle({
  point: [0, 0],
  size: [100, 100],
}), { colorSpace: 'display-p3' })

canvasTargetContext.putImageData(imageData, 0, 0)

2

Answers


  1. Chosen as BEST ANSWER

    Ok, it's not actually the case. Transparency is being preserved. I just visually got an impression that it wasn't. But when I simply saved the canvas as an image I saw the transparency.


  2. I can’t really explain the reason why this works, but a workaround for this can be to first draw the image data on a temporary canvas and then draw this temporary canvas on your target canvas. I got the idea from this thread.

    And here’s a fiddle demonstrating a possible solution.

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="UTF-8">
      <title>Debug Paper.js</title>
      <script src="https://unpkg.com/acorn"></script>
      <script src="https://unpkg.com/paper"></script>
      <style>
        html,
        body {
          margin: 0;
          overflow: hidden;
          height: 100%;
        }
    
        main {
          display: flex;
          gap: 10px;
          justify-content: center;
          margin-top: 20px;
        }
    
        canvas {
          border: 1px solid;
        }
    
        p {
          text-align: center;
        }
      </style>
    </head>
    <body>
    
    <main>
      <div>
        <canvas id="canvas" resize></canvas>
        <p>paper.js canvas</p>
      </div>
      <div>
        <canvas id="target" resize></canvas>
        <p>target canvas</p>
      </div>
    </main>
    
    <script>
      // Setup Paper.js
      paper.setup('canvas');
    
      // Create a circle.
      const circle = new paper.Path.Circle({
        center: paper.view.center,
        radius: 50,
        fillColor: 'orange',
      });
    
      // Rasterize the drawing.
      const raster = paper.project.activeLayer.rasterize();
      // Get the image data from this raster.
      const imageData = raster.getImageData();
    
      // Get the target canvas.
      const targetCanvas = document.getElementById('target');
      const context = targetCanvas.getContext('2d');
      // Draw a black rectangle on it so that we can see the transparency.
      context.fillRect(0, 0, 150, 50);
      putImageDataWithAlpha(targetCanvas, imageData);
    
      function putImageDataWithAlpha(canvas, imageData) {
        // Create a temporary canvas to draw the image data on it.
        const tmpCanvas = document.createElement('canvas');
        // Make it the same size as the given canvas.
        tmpCanvas.width = canvas.width;
        tmpCanvas.height = canvas.height;
        const tmpContext = tmpCanvas.getContext('2d');
        // Draw the image data on it.
        tmpContext.putImageData(imageData, 0, 0);
        // Then draw this temporary canvas on the given canvas.
        canvas.getContext('2d').drawImage(tmpCanvas, 0, 0);
        // Remove the temporary element.
        tmpCanvas.remove();
      };
    </script>
    </body>
    </html>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search