I'm building an image annotation application using Fabric JS and Angular. I would like to be able to apply a mask to the target image from an object that I drew on it (a Rect or a Polygon). I can't get it to work. I appreciate any collaboration.
More specifically, I would like to crop the image as the object I draw on top of it, and then create a new image with that mask. I would not like to change the original image. And if there was more than one object drawn on the image, I would like to obtain a new image for each object, cut into its respective format.
I know my code is not doing this, but I was facing problems at the initial stage, which is simply cropping the image by the mask.
// create canvas
this._canvas = new fabric.Canvas('canvas', {
selectionBorderColor: 'blue'
});
this._canvas.setWidth(this._width, {cssOnly:false});
this._canvas.setHeight(this._height, {cssOnly:false});
this._canvas.calcOffset();
// load image
fabric.Image.fromURL(path, (image) => {
image.set({
left: 0,
top: 0,
dirty: true
});
image.scale(0.1).setCoords();
this._canvas.add(image);
});
//create polygon
var poly = new fabric.Polygon(this._current_polygon_points, {
fill: 'rgba(0,0,0,0)',
stroke: this.color,
strokeWidth: 2,
selectable: true,
left: left,
top: top,
objectCaching: false,
absolutePositioned: true,
strokeUniform: true,
strokeLineCap: "round",
strokeLineJoin: "round",
dirty: true
});
this._canvas.add(poly);
this._canvas.renderAll();
// try to create mask --NOT WORKING
// items is a list of active objects, for the case I want to apply a mask with multiple shapes
// image is the target image
var clippath = new fabric.Group(items);
clippath.setCoords();
clippath.scaleX = 1;
clippath.scaleY = 1;
clippath.scaleX /= image.scaleX;
clippath.scaleY /= image.scaleY;
clippath.originX = image.originX;
clippath.originY = image.originY;
image.clipPath = clippath;
image.setCoords();
image.dirty = true;
this._canvas.add(image);
this._canvas.renderAll();
/*
EXAMPLE OF ITEMS
var items = [{
"type": "polygon",
"version": "5.3.0",
"originX": "left",
"originY": "top",
"left": -65.98,
"top": 10.49,
"width": 207.94,
"height": 113.94,
"fill": "rgba(220,211,82,0.8)",
"stroke": "rgba(220,211,82,1)",
"strokeWidth": 2,
"strokeDashArray": null,
"strokeLineCap": "round",
"strokeDashOffset": 0,
"strokeLineJoin": "round",
"strokeUniform": true,
"strokeMiterLimit": 4,
"scaleX": 1,
"scaleY": 1,
"angle": 0,
"flipX": false,
"flipY": false,
"opacity": 1,
"shadow": null,
"visible": true,
"backgroundColor": "",
"fillRule": "nonzero",
"paintFirst": "fill",
"globalCompositeOperation": "source-over",
"skewX": 0,
"skewY": 0,
"points": [
{
"x": 252.45334489205715,
"y": 194.89111062942803
},
{
"x": 171.47721757110224,
"y": 245.86263187097072
},
{
"x": 269.448334576702,
"y": 298.8330362984563
},
{
"x": 379.4159148891099,
"y": 215.87938408182796
},
{
"x": 300.4391981192897,
"y": 184.89669469971378
},
{
"x": 300.4391981192897,
"y": 184.89669469971378
},
{
"x": 252.45334489205715,
"y": 194.89111062942803
}
]
},
{
"type": "rect",
"version": "5.3.0",
"originX": "left",
"originY": "top",
"left": -143.96,
"top": -126.43,
"width": 219.94,
"height": 79.96,
"fill": "rgba(220,211,82,0.4)",
"stroke": "rgba(220,211,82,1)",
"strokeWidth": 3,
"strokeDashArray": null,
"strokeLineCap": "round",
"strokeDashOffset": 0,
"strokeLineJoin": "miter",
"strokeUniform": true,
"strokeMiterLimit": 4,
"scaleX": 1,
"scaleY": 1,
"angle": 0,
"flipX": false,
"flipY": false,
"opacity": 1,
"shadow": null,
"visible": true,
"backgroundColor": "",
"fillRule": "nonzero",
"paintFirst": "fill",
"globalCompositeOperation": "source-over",
"skewX": 0,
"skewY": 0,
"rx": 0,
"ry": 0
}]
*/
Screenshot Screenshot2 Problems I am facing:
- A kind of mask is created, but it always appears in the wrong place in the image (it appears displaced to the right and down)
- The image is even cropped, but when I move the resulting image (with the mask applied), it leaves traces like in the image shown.
I tried changing the dirty and scale attributes, and I also tried adding setCoords(), but the truth is that I didn't quite understand how I should do it.
My goal in the end is to be able to extract each intersection between an object and the image as a new image, and not a single image with several masks applied to it.