【问题标题】:Filling in certain pixels on an HTML canvas在 HTML 画布上填充某些像素
【发布时间】:2016-02-18 08:03:55
【问题描述】:

首先,抱歉标题不好,我想不出更好的方式来描述我正在尝试做的事情。我有一个 HTML 画布,为了论证,它是 x 像素宽和 y 像素高。我一直在尝试编写一个代码,该代码在画布图像数据的数组中获取位于 zz + 1 行的两个像素的位置并填写两个像素之间的较高行中的所有像素都具有某种颜色。恐怕我可能没有多大意义,所以这里有一个图表:

对糟糕的图形感到抱歉,但假设每个矩形都是一个像素。程序应为每个黑色像素获取第一个值(每个都存储为 r,g,b,a,程序获取 r 在表示画布图像数据的数组中的位置),并存储 r较低像素的值为bottomPixel,较高的像素为topPixel。在这种情况下,bottomPixel = 124topPixel = 112 应该使用它来填充两个基本像素之间的所有像素某种颜色。例如,使用之前的像素位置,下图中的红色像素应该被着色,但蓝色像素不应该被着色。

这是我的代码:(假设画布的 Id 为“Canvas”,宽 6 像素,高 10 像素)

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;
   }
}

我想知道为什么我的代码没有像我之前描述的那样做。如果这里有什么需要澄清的,请发表评论。谢谢!

【问题讨论】:

  • 你要rasterize a line吗?
  • 我可能是,不过我承认我没看懂那篇文章。
  • 如果你 edit 你的问题描述了当前代码在做什么这是错误的,它可能会帮助人们解决问题。
  • 是的,我想我是,尽管使用了文章似乎没有提到的公式。
  • @Kristján 我现在没有时间,但我会在明天的某个时间尝试这样做,谢谢。

标签: javascript html canvas


【解决方案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();
#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 */
}
&lt;canvas id="Canvas" width="128" height="64" style="width:320px"&gt;&lt;/canvas&gt;

【讨论】:

    猜你喜欢
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    相关资源
    最近更新 更多