Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Complex canvas clip shape

Posted on 2012-03-13
8
Medium Priority
?
310 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
8 Comments
 
LVL 38

Accepted Solution

by:
Tom Beck earned 2000 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
The top UI technologies you need to be aware of

An important part of the job as a front-end developer is to stay up to date and in contact with new tools, trends and workflows. That’s why you cannot miss this upcoming webinar to explore the latest trends in UI technologies!

 
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
 
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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article discusses four methods for overlaying images in a container on a web page
This article demonstrates how to create a simple responsive confirmation dialog with Ok and Cancel buttons using HTML, CSS, jQuery and Promises
It’s easy to embed any of your public Prezi presentations on your website or social network to share with others. Learn how simple it is in this tutorial.
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.

721 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