1

I am working on ionic based application.

I want to functionality like user has Filled the red color on image(canvas) with finger. So I have done the filled functionality but I want to crop the Filled portion from canvas. I have attached one image for reference.

enter image description here

I want to crop red portion from above image. I has googling but not found any solution.

Govaadiyo
  • 5,644
  • 9
  • 43
  • 72
  • You should elaborate your question, along with the code or steps that you have taken so far to accomplish what you want, until some effort is shown no one will help you out . – Muhammad Omer Aslam Nov 21 '17 at 09:52
  • Question updated – Govaadiyo Nov 21 '17 at 09:53
  • Possible duplicate of [Canvas: mask an image and preserve its alpha channel?](https://stackoverflow.com/questions/9032050/canvas-mask-an-image-and-preserve-its-alpha-channel) – 3Dos Nov 21 '17 at 09:53
  • @3Dos - It's not duplicate, before mark as duplicate read what i'm asking? I know how to draw/fill red color on image that I already done. **but I want to crop red part from original image** – Govaadiyo Nov 21 '17 at 09:57
  • @TofaaniKaanudo And that's exactly what's explained in the duplicate I tagged – 3Dos Nov 21 '17 at 09:58
  • @MuhammadOmerAslam you getting my question?? – Govaadiyo Nov 21 '17 at 10:08

1 Answers1

5

Creating a image mask.

If you are rendering the selection area (red) then the solution is simple.

Create a second canvas the same size as the drawing, and don't add it to the DOM. Draw the red marking content onto that canvas

The on the display canvas render the image first and then render that marking canvas over the image with composite mode like "overlay" so that the original image can be seen and the marked areas are red.

Now you have two layers, one is the image and the other the mask you can use to get a copy of the marked content.

To do that create a 3rd canvas, draw the original image onto it, then set the composite mode to "destination-in". Then draw the mask over it. Only the marked pixels will remain.

See the example for more details

setTimeout(example,0); // ensures that the run us after parsing
function example(){
  const ctx = canvas.getContext("2d");
  var w = canvas.width;
  var h = canvas.height;
  var cw = w / 2;  // center 
  var ch = h / 2;

  var selectLayer = CImageCtx(w,h); // creates a canvas 
  var selectedContent = CImageCtx(w,h); // the selected content
  document.body.appendChild(selectedContent);
  var image = new Image;  // the image
  image.src = " https://i.stack.imgur.com/QhFct.png";
  // updates the masked result
  function updateSelected(){
    var ctx = selectedContent.ctx;
    ctx.drawImage(image,0,0);
    ctx.globalCompositeOperation = "destination-in";
    ctx.drawImage(selectLayer,0,0);
    ctx.globalCompositeOperation = "source-over";
  }
  function update(){
      // if mouse down then 
      if(mouse.but){
        // clear the mask if on the right image
        if(mouse.oldBut === false && mouse.x > 256){
           selectLayer.ctx.clearRect(0,0,w,h);
           mouse.but = false;
        }else{
           // draw the red 
           selectLayer.ctx.fillStyle = "red";
           fillCircle(mouse.x, mouse.y, 20, selectLayer.ctx);
        }
        // update the masked result
        updateSelected();
      }

      // clear the canvas
      ctx.clearRect(0,0,w,h);
      // draw the image
      ctx.drawImage(image,0,0);
      // then draw the marking layer over it with comp overlay
      ctx.globalCompositeOperation = "overlay";
      ctx.drawImage(selectLayer,0,0);
      ctx.globalCompositeOperation = "source-over";

      mouse.oldBut = mouse.but;
      requestAnimationFrame(update);
  }
  requestAnimationFrame(update);
}






//#############################################################################
// helper functions not part of the answer
//#############################################################################
const mouse  = {
  x : 0, y : 0, but : false,
  events(e){
    const m = mouse;
    const bounds = canvas.getBoundingClientRect();
    m.x = e.pageX - bounds.left - scrollX;
    m.y = e.pageY - bounds.top - scrollY;
    m.but = e.type === "mousedown" ? true : e.type === "mouseup" ? false : m.but;
  }
};
(["down","up","move"]).forEach(name => document.addEventListener("mouse" + name,mouse.events));
const CImage = (w = 128, h = w) => (c = document.createElement("canvas"),c.width = w,c.height = h, c);
const CImageCtx = (w = 128, h = w) => (c = CImage(w,h), c.ctx = c.getContext("2d"), c);
const fillCircle = (l,y=ctx,r=ctx,c=ctx) =>{if(l.p1){c=y; r=leng(l);y=l.p1.y;l=l.p1.x }else if(l.x){c=r;r=y;y=l.y;l=l.x}c.beginPath(); c.arc(l,y,r,0,Math.PI*2); c.fill()}
body { font-family : arial; }
canvas { border : 2px solid black; }
Draw on image and the selected parts are shown on the right<br>
Click right image to reset selection<br>
<canvas id="canvas" width=256 height=256></canvas>

Already masked.

If the red mask is already applied to the image then there is not much you can do apart from do a threshold filter depending on how red the image is. But even then you are going to have problems with darker areas, and areas that already contain red.

Unless you have the original image you will have poor results.

If you have the original image then you will have to access the image data and create a new image as a mask by comparing each pixel and selecting only pixels that are different. That will force you to same domain images only (or with CORS cross origin headers)

Community
  • 1
  • 1
Blindman67
  • 51,134
  • 11
  • 73
  • 136
  • Really you save my day +1 or accept is not enough for you. thanks for your support and Co-operation.if you have any source or links for eraser ( if user select wrong portion. than user can erase it ) . i am waiting for your positive feedback. – Govaadiyo Nov 21 '17 at 11:22
  • its not working in mobile. For mobile what we need to change.? please Suggest me. – Govaadiyo Nov 21 '17 at 11:31
  • @TofaaniKaanudo mobiles will need touch event listeners. The code was only as an example of how to mask an image, the interface is not related to the question. – Blindman67 Nov 21 '17 at 12:12
  • @ Blindman67 Can you plz suggest for the eraser Functionality on that mask? if user select wrong portion. than user can erase it. – Govaadiyo Nov 28 '17 at 12:03