Now Reading
Immediate color fill with HTML Canvas – SOS

Immediate color fill with HTML Canvas – SOS

2023-05-23 14:18:10

TLDR: Demo is at https://shaneosullivan.github.io/example-canvas-fill/ , code is at https://github.com/shaneosullivan/example-canvas-fill .

The Downside

When constructing a web site or app utilizing HTML Canvas, it’s usually a requirement to help a flood fill. That’s, when the consumer chooses a color and clicks on a pixel, fill all the encompassing pixels that match the color of the clicked pixel with the consumer’s chosen color.

To take action you’ll be able to write a reasonably easy algorithm to step via the pixels one after the other, examine them to the clicked pixel and both change their color or not. For those who redraw the canvas whereas doing this, in order to offer the consumer with visible suggestions, it may well appear to be this.

This works however is sluggish and ugly. It’s potential to enormously pace this up, in order that it’s primarily prompt, and appears like this

To realize this we pre-process the supply picture and use the output to immediately apply a colored masks to the HTML Canvas.

Why did I work on this?

I’ve constructed an online based mostly app referred to as Kidz Fun Art for my two younger daughters, optimised to be used on a pill. The concept was to construct one thing enjoyable that by no means exhibits adverts to them or methods them into sneaky purchases by “accident”. I noticed them get irritated by the sluggish fill algorithm I first wrote, so my private pleasure compelled me to go resolve this drawback! Right here’s what the ultimate implementation of the answer to this drawback appears like on the app.

The Resolution

Begin with a picture that has a lot of enclosed areas, every with a uniform color inside these areas. On this instance, we’ll use a picture with 4 enclosed areas, numbered 1 via 4.

Now create an online employee, which is JavaScript that runs on a separate thread to the browser thread, so it doesn’t lock up the consumer interface when processing a variety of information.

let employee = new Employee("./src/employee.js");

The employee.js file comprises the code to execute the fill algorithm. Within the browser UI code, ship the picture pixels to the employee by drawing the picture to a Canvas ingredient and calling the getImageData operate. Be aware that you just ship an ImageBuffer object to the employee, not the ImageData itself


const canvas = doc.getElementById('mycanvas');const context = canvas.getContext('second');

const dimensions = { top: canvas.top, width: canvas.width };

const img = new Picture();
img.onload = () => {
  context.drawImage(img, 0, 0);
  
  const imageData = 
    canvas.getImageData(0, 0, dimensions.width, dimensions.top);

  employee.postMessage({
      motion: "course of",
      dimensions,
      buffer: imageData.information.buffer,
    }, 
    [imageData.data.buffer]
  );
};

The employee script then asynchronously inspects each pixel within the picture. It begins by setting the alpha (transparency) worth of every pixel to zero, which marks the pixel as unprocessed. When it finds a pixel with a zero alpha worth, it executes a FILL operation from that pixel, the place each surrounding pixel is given an incremental alpha worth. That’s, the primary time a fill is executed, all surrounding pixels are given an alpha model of 1, the second time an alpha worth of two is assigned, and so forth.

Every time a FILL completes, the employee shops an standalone picture of simply the realm utilized by the FILL (saved as an array of numbers). When it has inspected all pixels within the supply picture, it should ship again to the UI thread all the person picture ‘masks’ it has calculated, in addition to a single picture with all the alpha values set numbers between 1 and 255. Which means that utilizing this system, we will help a most of 255 distinct areas to instant-fill, which needs to be wonderful, as we will fall again to a sluggish fill if a given pixel has not been pre-processed.

You see within the totally processed picture above that every one pixels within the supply picture are assigned an alpha worth. The numeric worth corresponds to one of many masks, as proven under.

For this picture, it will generate 4 masks as within the picture above. The purple areas are the pixels with non-zero alpha values, and the white are the pixels with alpha values of zero.

When the consumer clicks on a pixel of the HTML Canvas node, the UI code checks the alpha worth within the picture returned from the employee. If the worth is 2, it selects the second merchandise within the array of masks it acquired.

Now it’s time to use some HTML Canvas magic, by means of the globalCompositeOperation property. This property allows all kinds of enjoyable and attention-grabbing operations to be carried out with Canvas, however for our functions we have an interest within the source-in worth. This makes it in order that calling fillRect() on the Canvas context will solely fill the non-transparent pixels, and go away the others unchanged.

const pixelMaskContext = pixelMaskCanvasNode.getContext('second');
const pixelMaskImageData = new ImageData(
  pixelMaskInfo.width,
  pixelMaskInfo.top
);

pixelMaskImageData.information.set(
  new Uint8ClampedArray(pixelMaskInfo.pixels)
);

pixelMaskContext.putImageData(pixelMaskImageData, 0, 0);

// Here is the canvas magic that makes it simply draw the non
// clear pixels onto our foremost canvas
pixelMaskContext.globalCompositeOperation = "source-in";
pixelMaskContext.fillStyle = color;

pixelMaskContext.fillRect(
  0, 0, pixelMaskInfo.width, pixelMaskInfo.top
);

Now you’ve crammed the masks with a color, on this instance purple, you then simply have to attract that onto the canvas seen to the consumer on the prime left location of the masks, and also you’re achieved!

context.drawImage(
  pixelMaskCanvasNode,
  pixelMaskInfo.x,
  pixelMaskInfo.y
);

It ought to appear to be the picture under when achieved

All of the code for that is accessible on Github at https://github.com/shaneosullivan/example-canvas-fill

You may see the demo operating at https://shaneosullivan.github.io/example-canvas-fill/

One caveat is that for those who do this code in your native laptop by simply opening the index.html file, it is not going to work as browser safety is not going to let the Employee be registered. You want run a localhost server and run it from there.

P.S.

Because of the Excalidraw group for making it really easy to create these diagrams, what a implausible app!

Revealed

Source Link

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top