goldjunge
goldjunge

Reputation: 341

Fabric JS pixel by pixel manipulation

I have overlay image with rectangle transparent hole. Beneath is scalable and draggable image. How to cut only visible part of image ?

How to determine size and position of transparent rectangle ? Is it possible to do pixel by pixel alpha channel search only on overlay image ?

Any other ideas ?

EDIT:

Solution to another quoted problem is usefull, although it works only on whole canvas not on individual items like background, overlay or added images or shapes. Is it possible to read pixel values on individual fabric elements ?

I use overlay image as external png files.

Upvotes: 6

Views: 2835

Answers (1)

markE
markE

Reputation: 105035

The FabricJS API does not include a method to fetch the pixel values of an image.

You will have to draw your overlay image onto an html5 canvas and use getImageData to fetch the pixel data from that canvas.

getImageData().data contains the red, green, blue & alpha information for each pixel on the canvas.

You can test each pixel's alpha value and determine the minimum & maximum boundary of the transparent rectangle.

Here's example code and a Demo:

enter image description here

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;


var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="http://masterblocks.co.in/static/img/logo.png";
function start(){
  cw=canvas.width=img.width;
  ch=canvas.height=img.height
  ctx.drawImage(img,0,0);
  // clear a test rectangle
  ctx.clearRect(100,100,100,75);
  // get clear rect bounds
  var bounds=findCutoutBounds();
  // test: stroke the bounds
  ctx.lineWidth=2;
  ctx.strokeStyle='red';
  ctx.strokeRect(bounds.x,bounds.y,bounds.width,bounds.height);
}

// Get the imageData of that canvas
function findCutoutBounds(){
  var minX=1000000;
  var minY=1000000;
  var maxX=-1;
  var maxY=-1;
  var data=ctx.getImageData(0,0,canvas.width,canvas.height).data;
  for(var y=0;y<ch;y++){
    for(var x=0;x<cw;x++){
      var n=(y*cw+x)*4;
      if(data[n+3]<5){
        if(y<minY){minY=y;}
        if(y>maxY){maxY=y;}
        if(x<minX){minX=x;}
        if(x>maxX){maxX=x;}
      }
    }}
  return({x:minX,y:minY,width:maxX-minX,height:maxY-minY});
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<h4>The bounding box of the transparent rectangle is stroked in red</h4>
<canvas id="canvas" width=300 height=300></canvas>

Upvotes: 5

Related Questions