Solved

Draw a line only over a specific color

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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
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 …
In this Micro Tutorial viewers will learn how to remove an unwanted object using Photoshop’s feature known as content-aware fill.
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

705 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

18 Experts available now in Live!

Get 1:1 Help Now