简体   繁体   中英

Filling in certain pixels on an HTML canvas

First off, sorry about the bad title, I couldn't think of a better way to describe what I was trying to do. I have an HTML canvas, which, for argument's sake, is x pixels wide and y pixels tall. I have been trying to write a code that takes the location in the array of the canvas' image data of two pixels that are on lines z and z + 1 and fill in all the pixels in the higher row between the two pixels a certain color. I'm afraid I may not have made much sense, so here's a diagram:

A pair of pixels http://i63.tinypic.com/2jg583k.png

Sorry about the poor graphics, but assume each rectangle is a pixel. The program should take in the first value for each of the black pixels (each is stored as r,g,b,a, the program gets the location of the r in the array representing the canvas' image data), and stores the r value for the lower pixel as bottomPixel and the higher one as topPixel . In this case, bottomPixel = 124 and topPixel = 112 It should use this to fill all pixels between the two base pixels a certain color. For example, using the previous pixel locations, the red pixels in the following picture should be colored in, but the blue one should not.

Colored canvas http://i66.tinypic.com/21blzq8.png

Here is the code I have: (Assume that the canvas has an Id "Canvas" and is 6px wide by 10px tall)

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

I'd like to know why my code isn't doing what I previously described. If anything here needs clarification, please leave a comment. Thanks!

This is a method that works on the point coordinates and uses a the setPixel function to modify imageData. I'm using blue for start and black for end. You'll need to adjust for your exact condition but you can use setPixel to allow for direct x and y edits on the imageData.

update

I've included an alternate line method and your line method. There is also an animation that will help you find errors.

 function ptIndex(p, w) { return ((px|0) + ((py|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 (px > cnvs.width) { px = cnvs.width; p.sx = 0; p.sy = 1; } if (py > cnvs.height) { py = cnvs.height; p.sy = 0; p.sx = -1; } if (px < 0) { px = 0; p.sx = 0; p.sy = -1; } if (py < 0) { py = 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(px - p2.x) <= 1 && Math.abs(py - 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 */ } 
 <canvas id="Canvas" width="128" height="64" style="width:320px"></canvas> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM