Solved

Complex canvas clip shape

Posted on 2012-03-13
8
301 Views
Last Modified: 2013-11-19
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
Comment
Question by:thenelson
  • 4
  • 4
8 Comments
 
LVL 38

Accepted Solution

by:
Tom Beck earned 500 total points
ID: 37719683
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
 
LVL 39

Author Comment

by:thenelson
ID: 37720451
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
 
LVL 38

Expert Comment

by:Tom Beck
ID: 37720550
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
 
LVL 38

Expert Comment

by:Tom Beck
ID: 37720609
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
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 38

Expert Comment

by:Tom Beck
ID: 37720772
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
 
LVL 39

Author Comment

by:thenelson
ID: 37722325
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
 
LVL 39

Author Closing Comment

by:thenelson
ID: 37732440
With a couple of tweaks, this is the method I used.   Thanks for your help!
0
 
LVL 39

Author Comment

by:thenelson
ID: 37733841
tommyBoy,

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

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Many programs have tried to outwit PowerPoint in terms of technology and skill. These programs, however, still lack several characteristics that PowerPoint has possessed from the start. Here's why PowerPoint replacements won't entirely work for desi…
This article explains how to prepare an HTML email signature template file containing dynamic placeholders for users' Azure AD data. Furthermore, it explains how to use this file to remotely set up a department-wide email signature policy in Office …
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now