toruwe
toruwe

Reputation: 35

How to cut a transparent hole into an image?

I want to cut a hole out of an image (png with transparent parts). The background has a gradient. I have tried first with svg and mask but this did not work for me cause of synchronizing the gradient in the hole with the gradient outside.

Afaik atm it is not possible to cut a transparent hole into an image using svg's. Css clip path can't be used because of browser compatibility.

So i decided to switch to canvas and js. But just drawing a transparent circle into the image had no effect. Seems that there has to be more advanced processing.

I am getting more and more desperated about this problem. Any help is appreciated.

<!DOCTYPE html>
 <html>
 <head>
 <meta charset="UTF-8">
 <title>test - image processing</title>
 <script 
 src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
 </script>   
<style>
body{
  background: red;
  background: -webkit-linear-gradient(left top, red, yellow);
  background: -o-linear-gradient(bottom right, red, yellow);
  background: -moz-linear-gradient(bottom right, red, yellow);
  background: linear-gradient(to bottom right, red, yellow);
 }
 canvas{
   display: block;
   margin:100px auto;
   }
  </style>
</head>
  <body>
  <div class="canvas-wrapper">
   <canvas id="canvas" ></canvas>
  </div>
   <script>
   $(document).ready(function () {

    showImage();

    function showImage() {
      var ctx = document.getElementById('canvas').getContext('2d');
      var image = new Image();
      // adjust the image path
      image.src = 'yourImagePathHere';
      image.onload = function () {
        document.getElementById('canvas').width = image.width;
        document.getElementById('canvas').height = image.height;
        ctx.drawImage(image, 0, 0);

        var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);

        for (var i = 0; i < imgData.data.length; i += 4) {
          // how to process?
          imgData.data[i] = imgData.data[i];
          imgData.data[i + 1] = imgData.data[i+1];
          imgData.data[i + 2] = imgData.data[i+2];
          imgData.data[i + 3] = imgData.data[i+3];
        }

        ctx.putImageData(imgData, 0, 0);
      };
    }
  });
</script>

Upvotes: 1

Views: 1436

Answers (2)

Paul LeBeau
Paul LeBeau

Reputation: 101820

I don't understand your claim that SVGs don't work. What you appear to be after is very simple with SVG.

body{
  background: red;
  background: -webkit-linear-gradient(left top, red, yellow);
  background: -o-linear-gradient(bottom right, red, yellow);
  background: -moz-linear-gradient(bottom right, red, yellow);
  background: linear-gradient(to bottom right, red, yellow);
 }
<svg width="400" height="300">
  <defs>
    <mask id="hole">
      <rect width="100%" height="100%" fill="white"/>
      <rect x="200" y="100" width="100" height="100"/>
    </mask>
  </defs>
  
  <image width="400" height="300"
         xlink:href="http://placekitten.com/400/300"
         mask="url(#hole)"/>
</svg>

Upvotes: 1

toruwe
toruwe

Reputation: 35

<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8">
  <title>test - image processing</title>
  <script     
    src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
  </script>   
  <style>
   body{
    background: red;
    background: -webkit-linear-gradient(left top, red, yellow);
    background: -o-linear-gradient(bottom right, red, yellow);
    background: -moz-linear-gradient(bottom right, red, yellow);
    background: linear-gradient(to bottom right, red, yellow);
  }
  canvas{
   display: block;
   margin:100px auto;
  }
 </style>
</head>
<body>
 <div class="canvas-wrapper">
  <canvas id="canvas" ></canvas>
 </div>
 <script>
   $(document).ready(function () {

   showImage();

   function showImage() {
    var ctx = document.getElementById('canvas').getContext('2d');
    var image = new Image();
    // adjust the image path
    image.src = 'yourImagePathHere';
    image.onload = function () {
     document.getElementById('canvas').width = image.width;
     document.getElementById('canvas').height = image.height;
     ctx.drawImage(image, 0, 0);

     var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);

     for (var i = 0; i < imgData.data.length; i += 4) {
      // how to process?
      imgData.data[i] = imgData.data[i];
      imgData.data[i + 1] = imgData.data[i+1];
      imgData.data[i + 2] = imgData.data[i+2];
      imgData.data[i + 3] = imgData.data[i+3];
     }

      ctx.putImageData(imgData, 0, 0);
      // this line does the magic, have a look at Amadans link for further possibilities
      ctx.globalCompositeOperation='destination-out';
      // here starts the circle form which is cutted out
      ctx.beginPath();
      ctx.fillStyle='';
      ctx.arc(image.width/2,image.height/2,50,0,2*Math.PI);
      ctx.fill();
  };
 }
});
</script>

Upvotes: 0

Related Questions