It's past 2am so here's a brief answer.
Best option: Create a spritesheet with all your character variations and cut out desired sprites from your spritesheet like this:
drawImage(spritesheet, spriteX, spriteY, spriteWidth, spriteHeight, canvasX, canvasY, spriteWidth, spriteHeight)
Next best option: Create a spritesheet with your full character and then have multiple sets of replacement pants (just pants--not the full character), replacement shirts, replacement weapons, etc. First draw the full character and then draw the desired pants on top of the character -- overwriting the original pants with desired pants. This way you're effectively "dressing" the character in replaceable pants, shirts, weapons, etc.
If you need runtime recoloring, use compositing to dynamically recolor a cutout of just the pants:
- Create a full character on the main canvas
- On a second canvas, create just the pants.
- Set `secondContext.globalCompositeOperation='source-in'
- Set a desired fillStyle.
- Fill a rectangle on the entire second canvas:
About your #2: Expensive to manipulate pixels -- avoid if possible.
About your #3: If you're just replacing a single RGB color, you don't need to mess with saturation & lightness.