在HTML画布上填充某些像素

时间:2015-11-17 03:32:04

标签: javascript html5 canvas

首先,对于糟糕的标题感到抱歉,我无法想出更好的方式来描述我想要做的事情。我有一个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 = 124topPixel = 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;
   }
}

我想知道为什么我的代码没有按照我之前的描述进行操作。如果此处有任何需要澄清的话,请发表评论。谢谢!

1 个答案:

答案 0 :(得分:1)

这是一种对点坐标起作用的方法,并使用setPixel函数修改imageData。我用蓝色表示开始,黑色表示结束。您需要根据具体情况进行调整,但可以使用setPixel对imageData进行直接x和y编辑。

<强>更新

我已经包含了备用线方法和您的线方法。还有一个动画可以帮助您找到错误。

&#13;
&#13;
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;
&#13;
&#13;