Having trawled Stack Overflow and Google it seems to me that there is no way to disable antialiasing when drawing lines on an HTML5 canvas.
This makes for nice looking lines, but causes me a problem when it comes time to applying a paint bucket / flood fill algorithm.
Part of my application requires that users draw on a canvas, freestyle drawing with basic tools like line size, color... and a paint bucket.
Because lines are rendered with antialiasing they are not a consistent color... with that in mind consider the following:
My flood fill algorithm fills the bulk of the line with red, but the edges that were antialiased are detected as being outside the area that should be filled... hence remain (greys / blues(?) left over from the black line).
The flood fill algorithm does not incorporate something akin to 'tolerance' like Photoshop does... I have considered something like that but am unsure it would help as I don't think the anti-aliasing does something simple like render grey next to a black line, I think it's more advanced than that and the anti-aliasing takes into consideration the surrounding colors and blends.
Does anyone have any suggestions as to how I can end up with a better paint bucket / flood fill that COMPLETELY flood fills / replaces an existing line or section of a drawing?
If you simply want to change a color of a line: don't use bucket paint fill at all.
Store all your lines and shapes as objects/arrays and redraw them when needed.
This not only allow you to change canvas size without losing everything on it, but to change a color is simply a matter of changing a color property on your object/array and redraw, as well as scaling everything based on vectors instead of raster.
This will be faster than a bucket fill as redrawing is handled in most part internally and not by pixel-by-pixel in JavaScript as is needed with a bucket fill.
That being said: you cannot, unfortunately, disable anti-alias for shapes and lines, only for images (using the imageSmoothingEnabled
property).
An object could look like this:
function myLine(x1, y1, x2, y2, color) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
return this;
}
And then allocate it by:
var newLine = new myLine(x1, y1, x2, y2, color);
Then store this to an array:
/// globally:
var myLineStack = [];
/// after x1/x2/y1/y2 and color is achieved in the draw function:
myLineStack.push(new myLine(x1, y1, x2, y2, color));
Then it is just a matter of iterating through the objects when an update is needed:
/// some index to a line you want to change color for:
myLineStack[index].color = newColor;
/// Redraw all (room for optimizations here...)
context.clearRect( ... );
for(var i = 0, currentLine; currentLine = myLineStack[i]; i++) {
/// new path
context.beginPath();
/// set the color for this line
context.strokeStyle = currentLine.color;
/// draw the actual line
context.moveTo(currentLine.x1, currentLine.y1);
context.lineTo(currentLine.x2, currentLine.y2);
context.stroke();
}
(For optimizations you can for example clear only the area that needs redraw and draw a single index. You can also group lines/shapes with the same colors and draw then with a single setting of strokeStyle
etc.)