回答
這裏是你如何在畫布
// get a reference to your canvas
var c=document.getElementById("canvas");
var ctx=c.getContext("2d");
// get the pixel data from the canvas
var imgData=ctx.getImageData(0,0,c.width,c.height);
// loop through each pixel and count non-transparent pixels
var count=0;
for (var i=0;i<imgData.data.length;i+=4)
{
// nontransparent = imgData.data[i+3]==0
if(imgData.data[i+3]==0){ count++; }
}
[編輯:獲得「如果填充」畫布上的封閉圖形的像素數]指望非透明像素
我通常使用此代碼在畫布中進行遮罩,但我已在此調整它以使您的像素數在您的封閉形狀內。
幾個caviats:
因爲「相鄰」算法被使用的,strokewidth必須至少2個像素寬爲未彎曲的形狀和至少3個像素寬爲含有曲線形狀。
由於Canvas使用抗鋸齒自動繪製筆劃,因此內部像素數將始終略大於預期值。這是因爲抗鋸齒「吃入」了中風,有效地導致了比預期更多的內部像素。順便說一句,有沒有辦法關閉畫布的抗鋸齒,如果您嘗試getImageData(),將所有形狀像素設置爲rbg(0,0,0),putImageData(),結果圖像也將消除鋸齒 - 更多的參差不齊!
下面是代碼:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
canvas{border:1px solid red;}
</style>
<script>
$(function(){
// The floodFill algorithm below is based on the good work by William Malone, Copyright 2010 William Malone (www.williammalone.com) -- Apache License: http://www.apache.org/licenses/LICENSE-2.0 -- Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
var canvas=document.getElementById("canvas");
var context = canvas.getContext("2d");
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var strokeColor = {r: 0, g: 0, b: 0};
var fillColor = {r: 101,g: 155,b: 65};
var fillData;
var strokeData;
function redraw() {
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.putImageData(fillData, 0, 0);
drawOutline(context);
}
function matchstrokeColor(r, g, b, a) {
// must check for near black because of anti-aliasing
return (r + g + b < 100 && a === 255);
}
function matchStartColor(pixelPos, startR, startG, startB) {
var r = strokeData.data[pixelPos],
g = strokeData.data[pixelPos + 1],
b = strokeData.data[pixelPos + 2],
a = strokeData.data[pixelPos + 3];
// If current pixel of the outline image is black-ish
if (matchstrokeColor(r, g, b, a)) {
return false;
}
r = fillData.data[pixelPos];
g = fillData.data[pixelPos + 1];
b = fillData.data[pixelPos + 2];
// If the current pixel matches the clicked color
if (r === startR && g === startG && b === startB) {
return true;
}
// If current pixel matches the new color
if (r === fillColor.r && g === fillColor.g && b === fillColor.b) {
return false;
}
return true;
}
function setPixel(pixelPos, r, g, b, a) {
fillData.data[pixelPos] = r;
fillData.data[pixelPos + 1] = g;
fillData.data[pixelPos + 2] = b;
fillData.data[pixelPos + 3] = a !== undefined ? a : 255;
}
function floodFill(startX, startY, startR, startG, startB) {
var newPos;
var x;
var y;
var pixelPos;
var neighborLeft;
var neighborRight;
var pixelStack = [[startX, startY]];
while (pixelStack.length) {
newPos = pixelStack.pop();
x = newPos[0];
y = newPos[1];
// Get current pixel position
pixelPos = (y * canvasWidth + x) * 4;
// Go up as long as the color matches and are inside the canvas
while (y >= 0 && matchStartColor(pixelPos, startR, startG, startB)) {
y -= 1;
pixelPos -= canvasWidth * 4;
}
pixelPos += canvasWidth * 4;
y += 1;
neighborLeft = false;
neighborRight = false;
// Go down as long as the color matches and in inside the canvas
while (y <= (canvasHeight-1) && matchStartColor(pixelPos, startR, startG, startB)) {
y += 1;
setPixel(pixelPos, fillColor.r, fillColor.g, fillColor.b);
if (x > 0) {
if (matchStartColor(pixelPos - 4, startR, startG, startB)) {
if (!neighborLeft) {
// Add pixel to stack
pixelStack.push([x - 1, y]);
neighborLeft = true;
}
} else if (neighborLeft) {
neighborLeft = false;
}
}
if (x < (canvasWidth-1)) {
if (matchStartColor(pixelPos + 4, startR, startG, startB)) {
if (!neighborRight) {
// Add pixel to stack
pixelStack.push([x + 1, y]);
neighborRight = true;
}
} else if (neighborRight) {
neighborRight = false;
}
}
pixelPos += canvasWidth * 4;
}
}
}
// Fill
function paintAt(startX, startY) {
var pixelPos = (startY * canvasWidth + startX) * 4,
r = fillData.data[pixelPos],
g = fillData.data[pixelPos + 1],
b = fillData.data[pixelPos + 2],
a = fillData.data[pixelPos + 3];
if (r === fillColor.r && g === fillColor.g && b === fillColor.b) {
// this one's already filled
return;
}
if (matchstrokeColor(r, g, b, a)) {
return;
}
floodFill(startX, startY, r, g, b);
redraw();
}
function init() {
var theShapes=document.getElementById("theShapes");
var theShapesContext=theShapes.getContext("2d");
drawOutline(theShapesContext);
drawOutline(context);
strokeData = context.getImageData(0, 0, canvasWidth, canvasHeight);
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
fillData = context.getImageData(0, 0, canvasWidth, canvasHeight);
$('#canvas').mousedown(function (e) {
// Mouse down location
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
paintAt(mouseX, mouseY);
});
redraw();
};
function drawOutline(theContext){
theContext.beginPath();
theContext.moveTo(55, 60);
theContext.bezierCurveTo(35, 70, 35, 95, 85, 95);
theContext.bezierCurveTo(95,110, 130,110, 140, 95);
theContext.bezierCurveTo(180, 95, 180, 80, 165, 70);
theContext.bezierCurveTo(185, 40, 155, 35, 140, 45);
theContext.bezierCurveTo(130, 25, 95, 30, 95, 45);
theContext.bezierCurveTo(70, 25, 45, 30, 55, 60);
theContext.closePath();
theContext.rect(200,30,100,70);
theContext.lineWidth = 3;
theContext.strokeStyle = 'rgb(0,0,0)';
theContext.stroke();
}
function getFilledPixelCount(theContext,theCanvas){
// get the pixel data from the fill canvas
var imgData=theContext.getImageData(0,0,theCanvas.width,theCanvas.height);
console.log(imgData.data.length);
var count=0;
for (var i=0;i<imgData.data.length;i+=4){
r = imgData.data[i],
g = imgData.data[i + 1],
b = imgData.data[i + 2],
a = imgData.data[i + 3];
if (r === fillColor.r && g === fillColor.g && b === fillColor.b) {
count++;
}
}
return(count);
}
$("#counter").click(function(){alert("There are "+getFilledPixelCount(context,canvas)+" filled pixels.");});
init();
}); // end $(function(){});
</script>
</head>
<body>
<p>The original stroked shapes</p>
<canvas id="theShapes" width=350 height=150></canvas><br/>
<p>The filled shapes used for pixel counting</p>
<p>Click inside a shape below</p>
<canvas id="canvas" width=350 height=150></canvas><br/>
<button id="counter">Filled Count</button>
</body>
</html>
當然這不是封閉的區域,只是所有不透明的像素... – 2013-03-25 07:54:13
@Rich Bradshaw--很高興認識你!那麼,如果填充形狀,它會計數填充,如果它沒有填充,它不會計數填充 - 只是中風:)但是,如果OP進一步請求包含「if-filled」的像素計數未填充的形狀 - 我也有一個解決方案。這有點複雜,但它基本上是邊緣檢測,包括識別筆劃外的所有像素,然後從畫布的總像素數中減去該數。 – markE 2013-03-25 15:21:26
這聽起來很有趣 - 看演示會很酷,我經常想知道如何做邊緣檢測,但大多數例子都非常複雜! – 2013-03-25 19:59:47
- 1. 繪製單個像素線HTML5畫布
- 2. 已移動html5畫布上已繪製的形狀
- 3. 在畫布上繪製透明形狀
- 4. 在HTML5畫布上繪製形狀...與視頻
- 5. 計算形狀的繪製圖像中的獨特像素
- 6. HTML5畫布繪製圖像
- 7. 繪製在HTML5畫布中的任意形狀
- 8. 在畫布上繪製像素橢圓
- 9. html5動畫畫布已繪製元素
- 10. 在控制檯上繪製HTML5畫布
- 11. HTML5畫布繪製
- 12. 如何在html5畫布上繪製圓形扇形?
- 13. 如何解決在HTML5畫布上繪製的形狀並更改其屬性?
- 14. 在網格基礎上的HTML畫布上繪製形狀
- 15. HTML5畫布繪製地形設置
- 16. 在html5的畫布上繪製扭曲的圖像
- 17. 畫布上的繪圖形狀
- 18. 在支持字體元素的HTML5畫布上繪製SVG
- 19. HTML5 - 超時後在畫布上繪製
- 20. 在HTML5畫布上繪製虛線?
- 21. 來自計算機的畫布上的繪畫圖像
- 22. 在HTML5畫布中傳播圖像內部形狀
- 23. HTML5畫布:像素
- 24. 在Html5上繪製圖像浮點座標處的畫布
- 25. HTML5 - 畫布形狀描邊
- 26. 從畫布上的像素數組中繪製圖像putImageData
- 27. 在觸摸位置在HTML5畫布上繪製圓形
- 28. 在相對大小的畫布上繪製形狀
- 29. 存儲在畫布上繪製的形狀
- 30. 繪製2個形狀不同的顏色在畫布上
不容易。你可以以某種方式將它分成小的梯形和近似它,但它根本不是內置的。 – 2013-03-24 20:19:19
是的,我很驚訝沒有完成這項工作的文件 - 不是用於sketch.js,而是用於畫布。哦,很好 - 謝謝。 – 2013-03-24 21:31:02
當你說「像素數量」時,你的意思是你想知道其邊界框的大小,或者你真的想知道不透明像素的數量? – markE 2013-03-24 21:59:45