我正在尝试在图像中找到第一个包含数据的垂直和水平行。
我很容易得到第一个水平行,就像调用getImageData
时一样,生成的像素数据数据是逐行水平存储的。我有这样的数据:
var data = context.getImageData(0, 0, width, height).data;
var heightFirst = 0;
for (var r = 0; r <= data.length; r += 4) {
if (data[r + 3] > 0) {
var y = (r / width) / 4;
heightFirst = y;
break;
}
}
我现在需要垂直迭代数据。我意识到这可能是使用嵌套的for循环完成的,并做了类似的事情:
for (var r = 0; r <= data.length; r += 4) {
for (var c = 0; c < canvasHeight; c++) {
if (data[(r + 3) + (c * width)] > 0) {
}
}
}
我不确定任何人可以帮助我的确切实施/计算?
修改
正如@bobbybee和@danielpolencic所提到的,增加4 *宽度的循环将增加一个垂直列:
for (var r = 0; r <= data.length; r += (4 * width)) {
if (data[r + 3] > 0) {
// do whatever
}
}
但是,这仅获取第一列像素的信息。我想下一步是重复上面的循环,但是增加它的列数(由于颜色数据乘以4),循环如下:
for (var c = 0; c < canvas.width; c ++) {
for (var r = 0; r <= data.length; r += ((4 * canvas.width) + (c * 4))) {
if (data[r + 3] > 0) {
firstX = c;
}
}
}
这似乎不太正确。我把它放在this fiddle上,因为你可以看到它应该返回10,因为这是左边的第一列,但它正在向日志写入99。感觉我好近了!
答案 0 :(得分:2)
你可以在一个循环中完成所有操作,而不必完全嵌套。
<强> Live Demo 强>
var minX = canvas.width,
minY = canvas.height;
for (var p = 0; p <= data.length; p += 4) {
var curX = (p / 4) % canvas.width,
curY = ((p / 4) - curX) / canvas.width;
/* if what we're checking is higher than our recorded minX and
minY skip to the next row */
if(curX > minX && curY > minY){
// if minY is greater than 0 continue, if its 0 it can be no less so break.
if(minY > 0){
p=(curY+1)*(canvas.width*4);
}else{
break;
}
}
if (data[p + 3] > 0) {
if (curX < minX) {
minX = curX;
};
if (curY < minY) {
minY = curY;
};
}
}
以下是从单维数组中获取x和y的公式
X = Index % Width
Y = (Index - x) / Width
在我们的例子中,由于我们正在处理分成4个分量值(r / g / b / alpha)的像素数据,我们需要将索引除以4,就像我在上面的演示中所做的那样。
接下来,我使用minX
和minY
设置为画布宽度和高度。每当我们点击一个像素时,我们会检查其x
或y
是否低于我们存储的最低x
和y
。如果它们较低,那么我们保持价值并继续前进。
然而,它更容易阅读, faster 使用多个循环来读取数据。
for (var x = 0; x <= canvas.width; x++) {
for (var y = 0; y <= canvas.height; y++) {
if (minY < y) {
break;
}
if (data[((y * canvas.width + x) * 4) + 3] > 0) {
if (x < minX) {
minX = x;
}
if (y < minY) {
minY = y;
}
}
}
}
<强> Demo to get the lastX and lastY 强>
for (var x = 0; x <= canvas.width; x++) {
for (var y = 0; y <= canvas.height; y++) {
if (data[((y * canvas.width + x) * 4) + 3] > 0) {
if (x < firstX) {
firstX = x;
}
if (y < firstY) {
firstY = y;
}
if (x > lastX) {
lastX = x;
}
if (y > lastY) {
lastY = y;
}
}
}
}
答案 1 :(得分:1)
正如@bobbybee正确指出的那样,你的循环步骤为4 * image_width
。
for (var r = 0; r <= data.length; r += (4 * width)) {
for (var c = 0; c < canvasHeight; c++) {
if (data[r + 3] > 0) {
}
}
}
答案 2 :(得分:1)
这可以通过一个循环来完成(这里不需要嵌套循环):
for(var y = 0; y < data.length; y += canvas.width * 4) {
if (data[y + 3] > 0 ) { /*...*/ }
}
或挤出更快的速度:
var y = 0,
length = data.length, /// cache length
width = canvas.width * 4; /// cache width
while(y < length) {
if (data[y + 3] > 0 ) { /*...*/ }
y += width;
}