Javascript 画布泛光填充笔划颜色
我正在使用canvas构建一个小应用程序。我的应用程序将有一个选项来填充黑白图像 我下载了一个代码,工作正常,但它只在图像笔划为黑色时工作。我将要使用的所有图像都是灰色笔划 所以,我想知道我需要做什么改变,才能使代码使用灰色笔划,而不是黑色笔划 代码如下: HTML:Javascript 画布泛光填充笔划颜色,javascript,canvas,Javascript,Canvas,我正在使用canvas构建一个小应用程序。我的应用程序将有一个选项来填充黑白图像 我下载了一个代码,工作正常,但它只在图像笔划为黑色时工作。我将要使用的所有图像都是灰色笔划 所以,我想知道我需要做什么改变,才能使代码使用灰色笔划,而不是黑色笔划 代码如下: HTML: JavaScript var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); var $canvas =
JavaScript
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var strokeColor = {
r: 152,
g: 152,
b: 152
};
var fillColor = {
r: 101,
g: 155,
b: 65
};
var fillData;
var strokeData;
// load image
var img = new Image();
img.onload = function () {
start();
}
img.crossOrigin = "anonymous";
img.src = "http://i.imgur.com/kjY1kiE.png";
function matchstrokeColor(r, g, b, a) {
// never recolor the initial black divider strokes
// must check for near black because of anti-aliasing
return (r + g + b < 100 && a === 155);
}
function matchStartColor(pixelPos, startR, startG, startB) {
// get the color to be matched
var r = strokeData.data[pixelPos],
g = strokeData.data[pixelPos + 1],
b = strokeData.data[pixelPos + 2],
a = strokeData.data[pixelPos + 3];
// If current pixel of the outline image is black-ish
if (matchstrokeColor(r, g, b, a)) {
return false;
}
// get the potential replacement color
r = fillData.data[pixelPos];
g = fillData.data[pixelPos + 1];
b = fillData.data[pixelPos + 2];
// If the current pixel matches the clicked color
if (r === startR && g === startG && b === startB) {
return true;
}
// If current pixel matches the new color
if (r === fillColor.r && g === fillColor.g && b === fillColor.b) {
return false;
}
return true;
}
// Thank you William Malone!
function floodFill(startX, startY, startR, startG, startB) {
var newPos;
var x;
var y;
var pixelPos;
var neighborLeft;
var neighborRight;
var pixelStack = [
[startX, startY]
];
while (pixelStack.length) {
newPos = pixelStack.pop();
x = newPos[0];
y = newPos[1];
// Get current pixel position
pixelPos = (y * canvasWidth + x) * 4;
// Go up as long as the color matches and are inside the canvas
while (y >= 0 && matchStartColor(pixelPos, startR, startG, startB)) {
y -= 1;
pixelPos -= canvasWidth * 4;
}
pixelPos += canvasWidth * 4;
y += 1;
neighborLeft = false;
neighborRight = false;
// Go down as long as the color matches and in inside the canvas
while (y <= (canvasHeight - 1) && matchStartColor(pixelPos, startR, startG, startB)) {
y += 1;
fillData.data[pixelPos] = fillColor.r;
fillData.data[pixelPos + 1] = fillColor.g;
fillData.data[pixelPos + 2] = fillColor.b;
fillData.data[pixelPos + 3] = 255;
if (x > 0) {
if (matchStartColor(pixelPos - 4, startR, startG, startB)) {
if (!neighborLeft) {
// Add pixel to stack
pixelStack.push([x - 1, y]);
neighborLeft = true;
}
} else if (neighborLeft) {
neighborLeft = false;
}
}
if (x < (canvasWidth - 1)) {
if (matchStartColor(pixelPos + 4, startR, startG, startB)) {
if (!neighborRight) {
// Add pixel to stack
pixelStack.push([x + 1, y]);
neighborRight = true;
}
} else if (neighborRight) {
neighborRight = false;
}
}
pixelPos += canvasWidth * 4;
}
}
}
// Start a floodfill
// 1. Get the color under the mouseclick
// 2. Replace all of that color with the new color
// 3. But respect bounding areas! Replace only contiguous color.
function paintAt(startX, startY) {
// get the clicked pixel's [r,g,b,a] color data
var pixelPos = (startY * canvasWidth + startX) * 4,
r = fillData.data[pixelPos],
g = fillData.data[pixelPos + 1],
b = fillData.data[pixelPos + 2],
a = fillData.data[pixelPos + 3];
// this pixel's already filled
if (r === fillColor.r && g === fillColor.g && b === fillColor.b) {
return;
}
// this pixel is part of the original black image--don't fill
if (matchstrokeColor(r, g, b, a)) {
return;
}
// execute the floodfill
floodFill(startX, startY, r, g, b);
// put the colorized data back on the canvas
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.putImageData(fillData, 0, 0);
context.drawImage(img, 0, 0);
}
// create a random color object {red,green,blue}
function randomColorRGB() {
var hex = Math.floor(Math.random() * 16777215).toString(16);
//var r = parseInt(hex.substring(0, 2), 16);
var r = 155;
var g = 155;
var b = 255;
//var g = parseInt(hex.substring(2, 4), 16);
//var b = parseInt(hex.substring(4, 6), 16);
return ({
r: r,
g: g,
b: b
});
}
// draw the image to the canvas and get its pixel array
// listen for mouse clicks and do floodfill when clicked
function start() {
context.drawImage(img, 0, 0);
strokeData = context.getImageData(0, 0, canvasWidth, canvasHeight);
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
fillData = context.getImageData(0, 0, canvasWidth, canvasHeight);
context.drawImage(img, 0, 0);
$('#canvas').mousedown(function (e) {
// Mouse down location
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
// set a new random fillColor
fillColor = randomColorRGB();
// floodfill
paintAt(mouseX, mouseY);
});
var canvas=document.getElementById(“canvas”);
var context=canvas.getContext(“2d”);
var$canvas=$(“#canvas”);
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var canvasWidth=canvas.width;
var canvasHeight=canvas.height;
var strokeColor={
r:152,
g:152,
b:152
};
var fillColor={
r:101,
g:155,
b:65
};
var数据;
var-strokeData;
//加载图像
var img=新图像();
img.onload=函数(){
start();
}
img.crossOrigin=“匿名”;
img.src=”http://i.imgur.com/kjY1kiE.png";
函数匹配StrokeColor(r、g、b、a){
//切勿回忆最初的黑色分隔符笔划
//由于抗锯齿,必须检查是否接近黑色
回报率(r+g+b<100&&a==155);
}
功能匹配StartColor(像素位置、startR、startG、startB){
//获取要匹配的颜色
var r=strokeData.data[pixelPos],
g=strokeData.data[pixelPos+1],
b=strokeData.data[pixelPos+2],
a=strokeData.data[pixelPos+3];
//如果轮廓图像的当前像素为黑色
if(匹配strokeColor(r、g、b、a)){
返回false;
}
//获得潜在的替换颜色
r=fillData.data[pixelPos];
g=填充数据。数据[pixelPos+1];
b=fillData.data[pixelPos+2];
//如果当前像素与单击的颜色匹配
如果(r==startR&&g==startG&&b==startB){
返回true;
}
//如果当前像素与新颜色匹配
如果(r==fillColor.r&&g==fillColor.g&&b==fillColor.b){
返回false;
}
返回true;
}
//谢谢威廉·马龙!
功能注水(startX、startY、startR、startG、startB){
var newPos;
var x;
变量y;
var-pixelPos;
var neighborLeft;
邻里关系;
var pixelStack=[
[startX,startY]
];
while(pixelStack.length){
newPos=pixelStack.pop();
x=newPos[0];
y=新位置[1];
//获取当前像素位置
pixelPos=(y*画布宽度+x)*4;
//只要颜色匹配并且在画布内,就可以向上移动
而(y>=0&&matchStartColor(像素点、startR、startG、startB)){
y-=1;
pixelPos-=画布宽度*4;
}
pixelPos+=画布宽度*4;
y+=1;
邻里关系=假;
邻里关系=错误;
//只要颜色匹配,就在画布内向下移动
while(y0){
if(匹配StartColor(像素位置-4、startR、startG、startB)){
如果(!Neightarleft){
//将像素添加到堆栈
pixelStack.push([x-1,y]);
邻里关系=正确;
}
}else if(邻里金融){
邻里关系=假;
}
}
如果(x<(画布宽度-1)){
if(匹配StartColor(像素位置+4、startR、startG、startB)){
如果(!邻居){
//将像素添加到堆栈
pixelStack.push([x+1,y]);
邻里关系=正确;
}
}else if(邻里关系){
邻里关系=错误;
}
}
pixelPos+=画布宽度*4;
}
}
}
//开始注水
// 1. 在鼠标单击下获取颜色
// 2. 用新颜色替换所有该颜色
// 3. 但要尊重边界地区!仅替换连续颜色。
功能油漆(startX、startY){
//获取点击像素的[r,g,b,a]颜色数据
变量pixelPos=(星形*画布宽度+星形)*4,
r=fillData.data[pixelPos],
g=fillData.data[pixelPos+1],
b=填充数据。数据[pixelPos+2],
a=fillData.data[pixelPos+3];
//这个像素已经满了
如果(r==fillColor.r&&g==fillColor.g&&b==fillColor.b){
返回;
}
//此像素是原始黑色图像的一部分--不要填充
if(匹配strokeColor(r、g、b、a)){
返回;
}
//执行洪水填充
漫灌(startX、startY、r、g、b);
//将彩色数据放回画布上
clearRect(0,0,画布宽度,画布高度);
putImageData(fillData,0,0);
drawImage(img,0,0);
}
//创建一个随机颜色对象{红、绿、蓝}
函数randomColorRGB(){
var hex=Math.floor(Math.random()*16777215).toString(16);
//var r=parseInt(十六进制子串(0,2,16);
var r=155;
var g=155;
变量b=255;
//var g=parseInt(十六进制子串(2,4,16);
//var b=parseInt(十六进制子串(4,6,16);
返回({
r:r,
g:g,
b:b
});
}
//将图像绘制到画布并获取其像素阵列
//聆听鼠标点击,点击时进行泛光填充
函数start(){
drawImage(img,0,0);
strokeData=context.getImageData(0,0,画布宽度,画布高度);
clearRect(0,0,context.canvas.width,context.canvas.height);
fillData=context.getImageData(0,0,画布宽度,画布高度);
drawImage(img,0,0);
$(“#画布”).mousedown(函数(e){
//鼠标下键位置
var mouseX=parseInt(e.clientX-offsetX);
var mouseY=parseInt(e.clientY-offsetY);
//设置新的随机填充颜色
fillColor=randomColorRGB();
//填海
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var strokeColor = {
r: 152,
g: 152,
b: 152
};
var fillColor = {
r: 101,
g: 155,
b: 65
};
var fillData;
var strokeData;
// load image
var img = new Image();
img.onload = function () {
start();
}
img.crossOrigin = "anonymous";
img.src = "http://i.imgur.com/kjY1kiE.png";
function matchstrokeColor(r, g, b, a) {
// never recolor the initial black divider strokes
// must check for near black because of anti-aliasing
return (r + g + b < 100 && a === 155);
}
function matchStartColor(pixelPos, startR, startG, startB) {
// get the color to be matched
var r = strokeData.data[pixelPos],
g = strokeData.data[pixelPos + 1],
b = strokeData.data[pixelPos + 2],
a = strokeData.data[pixelPos + 3];
// If current pixel of the outline image is black-ish
if (matchstrokeColor(r, g, b, a)) {
return false;
}
// get the potential replacement color
r = fillData.data[pixelPos];
g = fillData.data[pixelPos + 1];
b = fillData.data[pixelPos + 2];
// If the current pixel matches the clicked color
if (r === startR && g === startG && b === startB) {
return true;
}
// If current pixel matches the new color
if (r === fillColor.r && g === fillColor.g && b === fillColor.b) {
return false;
}
return true;
}
// Thank you William Malone!
function floodFill(startX, startY, startR, startG, startB) {
var newPos;
var x;
var y;
var pixelPos;
var neighborLeft;
var neighborRight;
var pixelStack = [
[startX, startY]
];
while (pixelStack.length) {
newPos = pixelStack.pop();
x = newPos[0];
y = newPos[1];
// Get current pixel position
pixelPos = (y * canvasWidth + x) * 4;
// Go up as long as the color matches and are inside the canvas
while (y >= 0 && matchStartColor(pixelPos, startR, startG, startB)) {
y -= 1;
pixelPos -= canvasWidth * 4;
}
pixelPos += canvasWidth * 4;
y += 1;
neighborLeft = false;
neighborRight = false;
// Go down as long as the color matches and in inside the canvas
while (y <= (canvasHeight - 1) && matchStartColor(pixelPos, startR, startG, startB)) {
y += 1;
fillData.data[pixelPos] = fillColor.r;
fillData.data[pixelPos + 1] = fillColor.g;
fillData.data[pixelPos + 2] = fillColor.b;
fillData.data[pixelPos + 3] = 255;
if (x > 0) {
if (matchStartColor(pixelPos - 4, startR, startG, startB)) {
if (!neighborLeft) {
// Add pixel to stack
pixelStack.push([x - 1, y]);
neighborLeft = true;
}
} else if (neighborLeft) {
neighborLeft = false;
}
}
if (x < (canvasWidth - 1)) {
if (matchStartColor(pixelPos + 4, startR, startG, startB)) {
if (!neighborRight) {
// Add pixel to stack
pixelStack.push([x + 1, y]);
neighborRight = true;
}
} else if (neighborRight) {
neighborRight = false;
}
}
pixelPos += canvasWidth * 4;
}
}
}
// Start a floodfill
// 1. Get the color under the mouseclick
// 2. Replace all of that color with the new color
// 3. But respect bounding areas! Replace only contiguous color.
function paintAt(startX, startY) {
// get the clicked pixel's [r,g,b,a] color data
var pixelPos = (startY * canvasWidth + startX) * 4,
r = fillData.data[pixelPos],
g = fillData.data[pixelPos + 1],
b = fillData.data[pixelPos + 2],
a = fillData.data[pixelPos + 3];
// this pixel's already filled
if (r === fillColor.r && g === fillColor.g && b === fillColor.b) {
return;
}
// this pixel is part of the original black image--don't fill
if (matchstrokeColor(r, g, b, a)) {
return;
}
// execute the floodfill
floodFill(startX, startY, r, g, b);
// put the colorized data back on the canvas
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.putImageData(fillData, 0, 0);
context.drawImage(img, 0, 0);
}
// create a random color object {red,green,blue}
function randomColorRGB() {
var hex = Math.floor(Math.random() * 16777215).toString(16);
//var r = parseInt(hex.substring(0, 2), 16);
var r = 155;
var g = 155;
var b = 255;
//var g = parseInt(hex.substring(2, 4), 16);
//var b = parseInt(hex.substring(4, 6), 16);
return ({
r: r,
g: g,
b: b
});
}
// draw the image to the canvas and get its pixel array
// listen for mouse clicks and do floodfill when clicked
function start() {
context.drawImage(img, 0, 0);
strokeData = context.getImageData(0, 0, canvasWidth, canvasHeight);
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
fillData = context.getImageData(0, 0, canvasWidth, canvasHeight);
context.drawImage(img, 0, 0);
$('#canvas').mousedown(function (e) {
// Mouse down location
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
// set a new random fillColor
fillColor = randomColorRGB();
// floodfill
paintAt(mouseX, mouseY);
});
function matchstrokeColor(r, g, b, a) {
// never recolor the initial black divider strokes
// must check for near black because of anti-aliasing
return (r + g + b < 100 && a === 155);
}
// A small threshold would make it fill closer to stroke.
var strokeThreshold = 1;
function matchstrokeColor(r, g, b, a) {
// Use sqrt difference to decide its storke or not.
var diffr = r - strokeColor.r;
var diffg = g - strokeColor.g;
var diffb= b - strokeColor.b;
var diff = Math.sqrt(diffr * diffr + diffg * diffg + diffb * diffb) / 3;
return (diff < strokeThreshold);
}