Solved

Draw a line only over a specific color

Posted on 2012-03-13
3
419 Views
Last Modified: 2013-11-19
I have created a simple sketching script in Java that draws a line over an image except  I only want the line to draw over one color (#FFCC99) and stop drawing when it leaves that color.   How do I do that? TIA

Below is my script:
// Keep everything in anonymous function, called on window load.
if(window.addEventListener) {
window.addEventListener('load', function () {
  var canvas, context, tool;

  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);
	};
	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;
      }
    };
  }

  // 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); }

// vim:set spell spl=en fo=wan1croql tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix:

Open in new window

0
Comment
Question by:thenelson
  • 2
3 Comments
 
LVL 38

Accepted Solution

by:
Tom Beck earned 500 total points
ID: 37715168
Starting with an image is going to be problematic because the chances of getting a precise hex color value under the cursor are slim. This is especially true of a jpeg because the compression changes the original pixel colors.

For demonstration purposes, this modification starts with squares of pure rgb color so that a precise hex value can be tested for a match. When a match is found, the color stroke starts, then ends when the cursor leaves the target color.

To do this with an image you would have to add logic to test for a color range that is within a predetermined amount, + or -, of your target color.

// Keep everything in anonymous function, called on window load.
if(window.addEventListener) {
window.addEventListener('load', function () {
  var canvas, context, tool;

  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;
    }
    context.fillStyle = "rgb(0,255,0)";
    context.fillRect(0, 0, 80, 80);
    context.fillStyle = "rgb(0,0,255)";
    context.fillRect(85, 0, 80, 80);
	
    // 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.05;
        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) {      
        var p = context.getImageData(ev._x, ev._y, 1, 1).data; 
        var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
        hex = hex.toLowerCase();
        if(hex == "#00ff00"){
            context.moveTo(ev._x, ev._y);
            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;
      }
    };
  }

  // 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); }

function rgbToHex(r, g, b) {
    if (r > 255 || g > 255 || b > 255)
        throw "Invalid color component";
    return ((r << 16) | (g << 8) | b).toString(16);
}

Open in new window

0
 
LVL 39

Author Comment

by:thenelson
ID: 37715615
That works. The issue of needing a precise color value is not a problem in this case since I designed the image with a consistent color in the area l want to draw.

However, I see this approach creates  a major problem:  The additional logic slows the mousemove function down to where the drawing is not smooth. I tried speeding the logic up by not using the rgbToHex to hex function replacing it with:
      var p = context.getImageData(ev._x, ev._y, 1, 1).data;
        if(p[0]==255 && p[1]==204 && p[2]==153){  ...
but this is still not fast enough.

 Unless you have any ideas to further speed up the logic,  I think a better approach would be to use the clip method.  I have another question asking about that: http:Q_27629937.html
0
 
LVL 39

Author Closing Comment

by:thenelson
ID: 37732838
Thanks for your help.
0

Featured Post

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

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

This is a PowerShell web interface I use to manage some task as a network administrator. Clicking an action button on the left frame will display a form in the middle frame to input some data in textboxes, process this data in PowerShell and display…
Not sure what the best email signature size is? Are you worried about email signature image size? Follow this best practice guide.
Learn how to create interesting presentations by including videos to keep your audience engaged using Prezi. Select "Insert" from the top menu in your Prezi editor: Select "YouTube Video": Paste the video URL into the prompt: "Select "Insert":…
In addition to being a great web-based presentation tool, Prezi also makes it easy to save your presentation as a PDF to share with others as well. Learn how in this tutorial. Select the share icon from the top menu in your Prezi editor: Select "D…

813 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

8 Experts available now in Live!

Get 1:1 Help Now