• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 319
  • Last Modified:

Complex canvas clip shape

I would like to clip everything that is grey in the image below.  That is I would like only the two images of the person to show through the clipping. How can I do that?
Pain diagram
0
thenelson
Asked:
thenelson
  • 4
  • 4
1 Solution
 
Tom BeckCommented:
This idea may not be the exact user experience you are looking for, but the end result is the same; only the bodies get drawn upon. On mouseup, the gray background is restored to original leaving the red lines on the bodies where you drew them.
<script type="text/javascript">
// Keep everything in anonymous function, called on window load.

if(window.addEventListener) {
window.addEventListener('load', function () {
  var canvas, context, tool, pixels;

  function init () {
    // Find the canvas element.
    canvas = document.getElementById('imageView');
    if (!canvas) {
      alert('Error: I cannot find the canvas element!');
      return;
    }

    if (!canvas.getContext) {
      alert('Error: no canvas.getContext!');
      return;
    }

    // Get the 2D canvas context.
    context = canvas.getContext('2d');
    if (!context) {
      alert('Error: failed to getContext!');
      return;
    }
	
	var img=new Image();
	img.onload = function(){
	
	context.drawImage(img,0,0);
	var imageData = context.getImageData(0, 0, 525, 482);
    pixels = imageData.data;
    
    
	};
	
	img.src="PainDiagram.png";
    // Pencil tool instance.
    tool = new tool_pencil();
    
    // Attach the mousedown, mousemove and mouseup event listeners.
    canvas.addEventListener('mousedown', ev_canvas, false);
    canvas.addEventListener('mousemove', ev_canvas, false);
    canvas.addEventListener('mouseup',   ev_canvas, false);
  }
   

  // This painting tool works like a drawing pencil which tracks the mouse 
  // movements.
  function tool_pencil () {
    var tool = this;
    this.started = false;

    // This is called when you start holding down the mouse button.
    // This starts the pencil drawing.
    this.mousedown = function (ev) {
		context.beginPath();
		context.lineWidth = 10;
		context.lineCap = "round";
		context.strokeStyle = "red"; // line color
		context.globalAlpha=0.005;
        //context.arc(ev._x, ev._y,5,0,Math.PI*2,false);
        context.moveTo(ev._x, ev._y);
        tool.started = true;
    };

    // This function is called every time you move the mouse. Obviously, it only 
    // draws if the tool.started state is set to true (when you are holding down 
    // the mouse button).
    this.mousemove = function (ev) {
      if (tool.started) {
        //context.arc(ev._x, ev._y,5,0,Math.PI*2,false);
        context.lineTo(ev._x, ev._y);
        context.stroke();
      }
    };

    // This is called when you release the mouse button.
    this.mouseup = function (ev) {
      if (tool.started) {
        tool.mousemove(ev);
        tool.started = false;
	    var imageData2 = context.getImageData(0, 0, 525, 482);
        var newPixels = imageData2.data;
        for (var i = 0, il = pixels.length; i < il; i += 4) {
            if(pixels[i] > 204 && pixels[i] < 209){
                newPixels[i] = pixels[i];
            }
            if(pixels[i+1] > 204 && pixels[i+1] < 209){
                newPixels[i+1] = pixels[i+1];
            }
            if(pixels[i+2] > 204 && pixels[i+2] < 209){
                newPixels[i+2] = pixels[i+2];
            }
        }
        context.putImageData(imageData2, 0, 0);
      }
    };
  }

  // The general-purpose event handler. This function just determines the mouse 
  // position relative to the canvas element.
  function ev_canvas (ev) {
    if (ev.layerX || ev.layerX == 0) { // Firefox
      ev._x = ev.layerX;
      ev._y = ev.layerY;
    } else if (ev.offsetX || ev.offsetX == 0) { // Opera
      ev._x = ev.offsetX;
      ev._y = ev.offsetY;
    }

    // Call the event handler of the tool.
    var func = tool[ev.type];
    if (func) {
      func(ev);
    }
  }

  init();

}, false); }

</script>

Open in new window

0
 
thenelsonAuthor Commented:
I don't believe the for loop is working. I changed the code to what's below to test it but did not see a change. An alert placed just before the for loop showed that the mouseup function is being called.
      this.mouseup = function (ev) 
	  {
	      if (tool.started) 
		  {
	        tool.mousemove(ev);
	        tool.started = false;
		var imageData2 = context.getImageData(0, 0, 700, 643);
	        var newPixels = imageData2.data;
	        for (var i = 0, il = pixels.length; i < il; i += 1) 
			{
	                pixels[i] = 0 ;
	        }
		  }	  
       };	

Open in new window

0
 
Tom BeckCommented:
pixels[i] = 0 ;

Open in new window

would not change the display because you are affecting only the original array of pixels. Plus you are not writing back to the canvas when the loop is done. To affect the new array (after drawing on it), use
newPixels[i] = 0;

Open in new window

. I tried it, and as expected, it set the red channel to zero making the image a turquoise color (mix of green and blue).

I have noticed that this whole script seems to only work in Firefox. Results from my test of the loop as written in the script I posted are attached. I'm using version 9.0.1.
canvas.jpg
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
Tom BeckCommented:
It works in Safari 5.1.4.

In IE7 and IE8, the image never displays.

Drawing on the canvas does not work in Chrome and Opera.

The issues may be the method used for finding the mouse position relative to the canvas. offsetX and layerX may not be recognized in the non-working browsers. Sounds like material for a new question.
0
 
Tom BeckCommented:
You can simplify the loop to this if you first bring the PainDiagram.png into photoshop or similar program and "purify" the gray background by making all pixels in the gray areas rgb(206,206,206).
var imageData2 = context.getImageData(0, 0, 525, 482);
        var newPixels = imageData2.data;
        for (var i = 0, il = pixels.length; i < il; i += 4) {          
            if(pixels[i] == 206 && pixels[i+1] == 206 && pixels[i+2] == 206){
                newPixels[i] = 206;
                newPixels[i+1] = 206;
                newPixels[i+2] = 206;
            }
        }
        context.putImageData(imageData2, 0, 0);

Open in new window

0
 
thenelsonAuthor Commented:
The reason it wasn't working for me is I missed your changes (and didn't copy them) in the onload routine:
        var imageData = context.getImageData(0, 0, 525, 482);
        pixels = imageData.data;

I changed the mouseup code to below. This has the advantage of not writing over the black as well.

The image does show in IE 9 but will not draw after adding your changes. It did work before adding the changes.

Another problem is the mouseup event does not fire if the mouse is moved off the image before being released.

 Here is the URL of the project while I'm working on it:  www.barnwellmd.com/paint.html

Here's a link to another pain diagram that they have solved some of the problems. They have some other problems however: http://www.hommenorthopedics.com/questionnaire.php
          if(pixels[i] != 255 || pixels[i+1] != 204 || pixels[i+2] != 153){
                newPixels[i] = pixels[i];
                newPixels[i+1] = pixels[i+1];
                newPixels[i+2] = pixels[i+2];
          }

Open in new window

0
 
thenelsonAuthor Commented:
With a couple of tweaks, this is the method I used.   Thanks for your help!
0
 
thenelsonAuthor Commented:
tommyBoy,

You have been so helpful with my past questions, I wanted to point out this one: http:Q_27637145.html
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now