Pregunta

I'm working on some particle animations for my game engine, and I want to know if is possible to change the hue, gamma and other image properties of a ImageElement object of the canvas, keeping the shape of the image.

What I've tried so far is this:

_ctx.save();
_ctx.setStrokeColorHsl(240, 100, 50);
_ctx.fillRect(c.x, c.y, width, height);
_ctx.globalAlpha = nAlpha; //Modify the transparency
_ctx.drawImageScaled(p, c.x, c.y, width, height);
_ctx.restore();   

Which works but it is applying the tone to the entire piece of image, which means if the image is a PNG with transparent edges it'll paint even the transparent parts because it uses a "fillRect()" (which paints rectangles only) to apply the transformation and the image object.

The result is this: (the red particles are semi-transparent circles)

Attempt of a bonfire

Is there any other way to tint the an image shape only or to modify the object directly so the transformation only apply to the visible part of the image?

¿Fue útil?

Solución

You should use the globalCompositeOperation modes. Draw your image first maybe, then a fillRect with a globalAlpha and the globalCompositeOperation = 'source-atop'.

https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html

so you can play around those modes, using lighter to lighten and colorize the image, or destination-over to add a background.
But beware some modes don't work on all Browsers, i tested darker a few month ago, which didn't work by then.

Otros consejos

I am not aware of a built-in way to do this. One way you could do it, would be by drawing your image to a temporary canvas and modify the pixels of the image yourself. But you'll need functions to convert between RGB and HSL. You can use this method to do the same thing to saturation and lightness.

double hue = 0.8;

var data = _context.getImageData(0, 0, _canvas.width, _canvas.height);
var pixels = data.data;
List<double> hsl;
List<int> newPixel;

for(var i = 0, len = pixels.length; i < len; i += 4) {
  hsl = rgbToHsl(pixels[i + 0], pixels[i + 1], pixels[i + 2]);

  newPixel = hslToRgb(h, hsl[1], hsl[2]);
  // or newPixel = hslToRgb((hsl[0] + hue) % 1.0, hsl[1], hsl[2]);

  pixels[i + 0] = newPixel[0];
  pixels[i + 1] = newPixel[1];
  pixels[i + 2] = newPixel[2];
}
_context.putImageData(data, 0, 0);

Another way, using you method, could be to additionally use your base image as a mask for the canvas with the changed hue. You would have to loop through your pixels and change pixel[i + 3] to the alpha of the base image. But you wouldn't have to convert between HSL and RGB.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top