Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Here's an implementation that I've been working on. It can get really slow if the replacement color is too close to the original color. It's quite a bit faster in Chrome than Firefox (I haven't tested it in any other browsers).</p> <p>I also haven't done exhaustive testing yet, so there may be edge cases where it doesn't work.</p> <pre><code>function getPixel(pixelData, x, y) { if (x &lt; 0 || y &lt; 0 || x &gt;= pixelData.width || y &gt;= pixelData.height) { return NaN; } var pixels = pixelData.data; var i = (y * pixelData.width + x) * 4; return ((pixels[i + 0] &amp; 0xFF) &lt;&lt; 24) | ((pixels[i + 1] &amp; 0xFF) &lt;&lt; 16) | ((pixels[i + 2] &amp; 0xFF) &lt;&lt; 8) | ((pixels[i + 3] &amp; 0xFF) &lt;&lt; 0); } function setPixel(pixelData, x, y, color) { var i = (y * pixelData.width + x) * 4; var pixels = pixelData.data; pixels[i + 0] = (color &gt;&gt;&gt; 24) &amp; 0xFF; pixels[i + 1] = (color &gt;&gt;&gt; 16) &amp; 0xFF; pixels[i + 2] = (color &gt;&gt;&gt; 8) &amp; 0xFF; pixels[i + 3] = (color &gt;&gt;&gt; 0) &amp; 0xFF; } function diff(c1, c2) { if (isNaN(c1) || isNaN(c2)) { return Infinity; } var dr = ((c1 &gt;&gt;&gt; 24) &amp; 0xFF) - ((c2 &gt;&gt;&gt; 24) &amp; 0xFF); var dg = ((c1 &gt;&gt;&gt; 16) &amp; 0xFF) - ((c2 &gt;&gt;&gt; 16) &amp; 0xFF); var db = ((c1 &gt;&gt;&gt; 8) &amp; 0xFF) - ((c2 &gt;&gt;&gt; 8) &amp; 0xFF); var da = ((c1 &gt;&gt;&gt; 0) &amp; 0xFF) - ((c2 &gt;&gt;&gt; 0) &amp; 0xFF); return dr*dr + dg*dg + db*db + da*da; } function floodFill(canvas, x, y, replacementColor, delta) { var current, w, e, stack, color, cx, cy; var context = canvas.getContext("2d"); var pixelData = context.getImageData(0, 0, canvas.width, canvas.height); var done = []; for (var i = 0; i &lt; canvas.width; i++) { done[i] = []; } var targetColor = getPixel(pixelData, x, y); delta *= delta; stack = [ [x, y] ]; done[x][y] = true; while ((current = stack.pop())) { cx = current[0]; cy = current[1]; if (diff(getPixel(pixelData, cx, cy), targetColor) &lt;= delta) { setPixel(pixelData, cx, cy, replacementColor); w = e = cx; while (w &gt; 0 &amp;&amp; diff(getPixel(pixelData, w - 1, cy), targetColor) &lt;= delta) { --w; if (done[w][cy]) break; setPixel(pixelData, w, cy, replacementColor); } while (e &lt; pixelData.width - 1 &amp;&amp; diff(getPixel(pixelData, e + 1, cy), targetColor) &lt;= delta) { ++e; if (done[e][cy]) break; setPixel(pixelData, e, cy, replacementColor); } for (cx = w; cx &lt;= e; cx++) { if (cy &gt; 0) { color = getPixel(pixelData, cx, cy - 1); if (diff(color, targetColor) &lt;= delta) { if (!done[cx][cy - 1]) { stack.push([cx, cy - 1]); done[cx][cy - 1] = true; } } } if (cy &lt; canvas.height - 1) { color = getPixel(pixelData, cx, cy + 1); if (diff(color, targetColor) &lt;= delta) { if (!done[cx][cy + 1]) { stack.push([cx, cy + 1]); done[cx][cy + 1] = true; } } } } } } context.putImageData(pixelData, 0, 0, 0, 0, canvas.width, canvas.height); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload