首先,对于糟糕的标题感到抱歉,我无法想出更好的方式来描述我想要做的事情。我有一个HTML画布,为了论证的缘故, x 像素宽, y 像素高。我一直在尝试编写一个代码来获取画布数组中的位置'行 z 和 z + 1的两个像素的图像数据,并填充两个像素之间的较高行中的所有像素的某种颜色。我担心我可能没有多大意义,所以这是一个图表:
A pair of pixels http://i63.tinypic.com/2jg583k.png
抱歉图形不佳,但假设每个矩形都是一个像素。程序应该为每个黑色像素取第一个值(每个都存储为r,g,b,a,程序获取表示画布的图像数据中r的位置)和存储较低像素的r值为bottomPixel
,较高的值为topPixel
。在这种情况下,bottomPixel = 124
和topPixel = 112
它应使用此功能将两个基本像素之间的所有像素填充为某种颜色。例如,使用前面的像素位置,下图中的红色像素应该着色,但蓝色像素不应该着色。
Colored canvas http://i66.tinypic.com/21blzq8.png
这是我的代码:(假设画布有一个Id" Canvas"并且是6px宽,10px高)
var cnvs = document.getElementById("Canvas");
cnvs.height = 10; //This height and width is here as an example.
cnvs.width = 6;
var cont = cnvs.getContext("2d");
var environment = cont.getImageData(0,0,6,10);
var bottomPixel = 124;//Not neccesarily 124 or 112, just example values
var topPixel = 112;
if ( bottomPixel - topPixel > 6*4 ) //If bottomPixel is to the right of topPixel
{
for ( var i = 0 ; i < ((bottomPixel-6*4)-topPixel)/4 ; i++ )
{
var index = topPixel + i * 4;
environment.data[index] = 0;
environment.data[index + 1 ] = 255;
environment.data[index + 2 ] = 0;
environment.data[index + 3 ] = 255;
}
}
if ( bottomPixel - topPixel > 6*4 ) //If bottomPixel is to the left of topPixel
{
for ( var i = 0 ; i < (topPixel-(bottomPixel-6*4))/4; i++ )
{
var index = topPixel - i * 4;
environment.data[index] = 0;
environment.data[index + 1 ] = 255;
environment.data[index + 2 ] = 0;
environment.data[index + 3 ] = 255;
}
}
我想知道为什么我的代码没有按照我之前的描述进行操作。如果此处有任何需要澄清的话,请发表评论。谢谢!
答案 0 :(得分:1)
这是一种对点坐标起作用的方法,并使用setPixel函数修改imageData。我用蓝色表示开始,黑色表示结束。您需要根据具体情况进行调整,但可以使用setPixel对imageData进行直接x和y编辑。
<强>更新强>
我已经包含了备用线方法和您的线方法。还有一个动画可以帮助您找到错误。
function ptIndex(p, w) {
return ((p.x|0) + ((p.y|0) * w)) * 4;
}
function setPixel(p, w, d, rgba) {
var i = ptIndex(p, w);
d[i] = rgba.r;
d[i + 1] = rgba.g;
d[i + 2] = rgba.b;
d[i + 3] = rgba.a;
}
function yourLine(p1, p2, w, d, rgba) {
var cnvs = document.getElementById("Canvas");
var bottomPixel = ptIndex(p1, w);
var topPixel = ptIndex(p2, w)
if (bottomPixel - topPixel > w * 4) //If bottomPixel is to the right of topPixel
{
for (var i = 0; i < ((bottomPixel - w * 4) - topPixel) / 4; i++) {
var index = topPixel + i * 4;
d[index] = rgba.r;
d[index + 1] = rgba.g;
d[index + 2] = rgba.b;
d[index + 3] = rgba.a
}
}
if (bottomPixel - topPixel > w * 4) //If bottomPixel is to the left of topPixel
{
for (var i = 0; i < (topPixel - (bottomPixel - w * 4)) / 4; i++) {
var index = topPixel - i * 4;
d[index] = rgba.r;
d[index + 1] = rgba.g;
d[index + 2] = rgba.b;
d[index + 3] = rgba.a
}
}
}
function drawRandPoints() {
var cnvs = document.getElementById("Canvas");
var cont = cnvs.getContext("2d");
// ghost last draw
cont.fillStyle = "white";
cont.fillRect(0, 0, cnvs.width, cnvs.height);
// get image data
var environment = cont.getImageData(0, 0, cnvs.width, cnvs.height);
var d = environment.data, w = cnvs.width;
// create colors
var black = {
r: 0,
g: 0,
b: 0,
a: 255
};
var red = {
r: 255,
g: 0,
b: 0,
a: 255
};
var blue = {
r: 0,
g: 0,
b: 255,
a: 255
};
var frames = 0;
var p1 = {x: ((cnvs.width / 2|0)), y: 0, sx: 1, sy:0};
var p2 = {x: cnvs.width, y: ((cnvs.height / 2)|0), sx: -1, sy: 0};
function step(p) {
if (p.x > cnvs.width) {
p.x = cnvs.width;
p.sx = 0;
p.sy = 1;
}
if (p.y > cnvs.height) {
p.y = cnvs.height;
p.sy = 0;
p.sx = -1;
}
if (p.x < 0) {
p.x = 0;
p.sx = 0;
p.sy = -1;
}
if (p.y < 0) {
p.y = 0;
p.sy = 0;
p.sx = 1;
}
}
function ani() {
cont.fillStyle = "white";
cont.fillRect(0, 0, cnvs.width, cnvs.height);
environment = cont.getImageData(0, 0, cnvs.width, cnvs.height);
d = environment.data;
step(p1);
step(p2);
var p3 = {
x: cnvs.width - p1.x,
y: cnvs.height - p2.y
};
var p4 = {
x: cnvs.width - p2.x,
y: cnvs.height - p1.y
};
yourLine(p1, p2, w, d, {r:0,g:255,b:0,a:255});
myDrawLine(p1, p2, w, d, red);
drawLineNoAliasing(p3, p4, w, d, blue);
setPixel(p1, w, d, black);
setPixel(p2, w, d, black);
frames %= 12;
p1.x += p1.sx;
p1.y += p1.sy;
p2.x += p2.sx;
p2.y += p2.sy;
// Put the pixel data on the canvas.
cont.putImageData(environment, 0, 0);
requestAnimationFrame(ani);
}
ani();
}
function myDrawLine(p1, p2, w, d, rgba) {
// Get the max length between x or y
var lenX = Math.abs(p1.x - p2.x);
var lenY = Math.abs(p1.y - p2.y);
var len = Math.sqrt(Math.pow(lenX,2) + Math.pow(lenY,2));
// Calculate the step increment between points
var stepX = lenX / len;
var stepY = lenY / len;
// If the first x or y is greater then make step negetive.
if (p2.x < p1.x) stepX *= -1;
if (p2.y < p1.y) stepY *= -1;
// Start at the first point
var x = p1.x;
var y = p1.y;
for (var i = 0; i < len; i++) {
x += stepX;
y += stepY;
// Make a point from new x and y
var p = {
x: x,
y: y
};
// Draw pixel on data
setPixel(p, w, d, rgba);
// reached goal (removes extra pixel)
if (Math.abs(p.x - p2.x) <= 1 && Math.abs(p.y - p2.y) <= 1) {
break;
}
}
// Draw start and end pixels. (might draw over line start and end)
setPixel(p1, w, d, rgba);
setPixel(p2, w, d, rgba);
}
// alternate from http://stackoverflow.com/questions/4261090/html5-canvas-and-anti-aliasing answer
// some helper functions
// finds the distance between points
function DBP(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
// finds the angle of (x,y) on a plane from the origin
function getAngle(x, y) {
return Math.atan(y / (x == 0 ? 0.01 : x)) + (x < 0 ? Math.PI : 0);
}
// the function
function drawLineNoAliasing(p1, p2, w, d, rgba) {
var dist = DBP(p1.x, p1.y, p2.x, p2.y); // length of line
var ang = getAngle(p2.x - p1.x, p2.y - p1.y); // angle of line
var cos = Math.cos(ang);
var sin = Math.sin(ang);
for (var i = 0; i < dist; i++) {
// for each point along the line
var pt = {
x: p1.x + cos * i,
y: p1.y + sin * i
};
setPixel(pt, w, d, rgba);
}
}
// end alt
drawRandPoints();
&#13;
#Canvas {
border: 1px solid red image-rendering: optimizeSpeed;
/* Older versions of FF */
image-rendering: -moz-crisp-edges;
/* FF 6.0+ */
image-rendering: -webkit-optimize-contrast;
/* Safari */
image-rendering: -o-crisp-edges;
/* OS X & Windows Opera (12.02+) */
image-rendering: pixelated;
/* Awesome future-browsers */
image-rendering: optimize-contrast;
/* CSS3 Proposed */
-ms-interpolation-mode: nearest-neighbor;
/* IE */
}
&#13;
<canvas id="Canvas" width="128" height="64" style="width:320px"></canvas>
&#13;