javascriptcolorshtml5-canvasopacityalpha

Can you make semi-transparent pixels opaque without knowing their coords?


My goal is to turn any pixel with any alpha > 0 to have alpha = 1.

Say I have this blank canvas with a gradient background:

blank canvas with background

And I draw a white (#fff) square on it:

enter image description here

And then I color that square red with 20% opacity (#f003):

enter image description here

At this point, is it possible to get back to the second screenshot (all white) without knowing the square's coords, and without getting and putting the image data?

Here is the HTML sample code:

<!doctype html>
<html>

<head>
  <title>test</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <style>
    canvas {
      background:
        linear-gradient(217deg, rgba(255, 0, 0, 0.8), rgba(255, 0, 0, 0) 70.71%),
        linear-gradient(127deg, rgba(0, 255, 0, 0.8), rgba(0, 255, 0, 0) 70.71%),
        linear-gradient(336deg, rgba(0, 0, 255, 0.8), rgba(0, 0, 255, 0) 70.71%);
    }

    body {
      background: #111;
    }
  </style>
</head>

<body>
  <canvas width="320" height="180"></canvas>
  <script>
    const canvas = document.querySelector("canvas")
    const ctx = canvas.getContext('2d')

    // Screenshot 1 taken at this point

    ctx.fillStyle = '#fff'
    ctx.fillRect(10, 10, 100, 100)

    // Screenshot 2 taken at this point

    ctx.globalCompositeOperation = 'source-in'
    ctx.fillStyle = '#f003'
    ctx.fillRect(0, 0, 320, 180)

    // Screenshot 3 taken at this point

    // now what ???

  </script>
</body>

</html>

Solution

  • without getImageData and putImageData you could create a new canvas and save the state there.

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>test</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <style>
            canvas {
                background: linear-gradient(217deg, rgba(255, 0, 0, 0.8), rgba(255, 0, 0, 0) 70.71%),
                linear-gradient(127deg, rgba(0, 255, 0, 0.8), rgba(0, 255, 0, 0) 70.71%),
                linear-gradient(336deg, rgba(0, 0, 255, 0.8), rgba(0, 0, 255, 0) 70.71%);
            }
    
            body {
                background: #111;
            }
        </style>
    </head>
    
    <body>
    <canvas width="320" height="180"></canvas>
    <script>
        const canvas = document.querySelector("canvas")
        const ctx = canvas.getContext('2d')
    
        // Screenshot 1 taken at this point
        ctx.fillStyle = '#fff'
        ctx.fillRect(10, 10, 100, 100)
    
            // ====== Save state on another canvas
        const newCanvas = document.createElement('canvas');
        const nCtx = newCanvas.getContext('2d');
        newCanvas.width = canvas.width;
        newCanvas.height = canvas.height;
        nCtx.drawImage(canvas, 0, 0);
    
        // Screenshot 2 taken at this point
        ctx.globalCompositeOperation = 'source-in'
        ctx.fillStyle = '#f003'
        ctx.fillRect(0, 0, 320, 180)
    
            // ====== Draw the saved canvas
        ctx.globalCompositeOperation = 'source-over'
        ctx.drawImage(newCanvas, 0, 0)
    
    </script>
    </body>
    
    </html>