I am trying to achieve realtime color changes to a PNG image using HTML5 and Canvas for an app I've been working on. I have researched two ways of achieving this that do not require altering each pixel as that is too expensive of an operation to be done every frame, but both methods have undesired consequences.
Method 1: Draw the original image to a temporary canvas, set the context's globalCompositeOperation to "source-in", and then draw a filled rectangle of the desired color to the temporary canvas (on top of the image), then return the newly tinted canvas/image for use in the main project. Source code of this approach can be found in answer #2 of: stackoverflow.com/questions/16228048/replace-a-specific-color-by-another-in-an-image-sprite-in-a-html5-canvas.
The problem with Method 1 is that none of the grayscale or darker components of the source image will carry over, only the alpha components and the new color. So, if I draw the tinted image repeatedly in the same spot, it will eventually be a solid color even if the original had some textured components that should remain a darker shade at all times. It works great for images that need to only be a single color with no texture.
Method 2: Separate the original image into RGB and black/transparent components and store each as a separate image. Then, use the 'lighten' mode to draw each of the components on top of one another. This is explained in depth with code snippets at: www.playmycode.com/blog/2011/06/realtime-image-tinting-on-html5-canvas/.
The problem with Method 2 is that any semi-transparent pixels get darker instead of remaining light and transparent as they should. It seems the Method 2 approach is used in some engines like Cocos2dx HTML but when I try on my own it always makes the transparent pixels darker.
The example image I used for testing is: https://i.stack.imgur.com/vrjl7.png
Here is an illustration of the methods and my intended result. https://i.stack.imgur.com/MWP8h.png