Solved

Draw a line only over a specific color

Posted on 2012-03-13
3
409 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Technology opened people to different means of presenting information, but PowerPoint remains to be above competition. Know why PPT still works today.
This article discusses four methods for overlaying images in a container on a web page
Learn the basics of inputting and editing your text components in Prezi. We will cover how to set styles, position, and group your text components. In your Prezi editor, click anywhere on the canvas to add text: A flashing cursor informs you that yo…
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

910 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

22 Experts available now in Live!

Get 1:1 Help Now