In a previous post, I changed the color of a simple image (of a pair of eyes) by converting it to an SVG first, and then changing the SVG colors.
But what if you want to a take a complex image and change the color?
In Photoshop/Gimp this can be achieved by creating a new layer on top of the image and filling it with a solid color, and then setting its Mode to ‘Multiply’. But how can we reproduce this on the web?
There are various solutions using svg filters (feFlood and feBlend) but these are not very well supported in browsers. So I’ve come up with a solution that is very well supported in all modern browsers, including IE.
...
Replace the numbers 0.5 with the rgb values of the color that you want. For example, in react:
hexToRgb(hex) { var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : {r: 255, g: 255, b: 255}; } skinColorDef(colorAsString) { const hex = hexToRgb(colorAsString); /* <-- See next for an improvement*/ const r = hex.r/255; const g = hex.g/255; const b = hex.b/255; return ( ); }
We can now tint our image with a color like skinColorDef(“#e7b48f”).
But let’s make small improvement. It’s not obvious what the final color is going to be because the tint color is multiplied by the color in the image. So let’s make it more intuitive by first looking at the main color in the image (e.g. using the color picker in gimp/photoshop) and then dividing (i.e ‘un-multiplying’) the colorAsString by that color.
For example, the skin color in that girl image is #fff2f2 which is (255,242,228). So:
divideByImageSkinColor(rgb) { return {r: rgb.r * (255/255), g: rgb.g * (255/242), b: rgb.b * (255/242)} }
and modify the skinColorDef like:
skinColorDef(colorAsString) { const hex = divideByImageSkinColor(hexToRgb(colorAsString));
Now we can just chose the colors directly. For skin, the Fitzpatrick Scale is a nice place to start:
We can now use these RGB values directly in our skinColorDef function. Here’s an example html combobox to select the color: (The onChange function is left to you to implement)
Light Fair Medium Olive Brown Black
And that’s it!
Sidenote: Many years ago, I wrote the graphics drivers (when I worked at Imagination Technologies) to accelerate this sort of multiply operation using shaders. That driver is used in the iPhone, iPad, TomTom, and many other small devices.
Pingback: Photoshop/gimp layers to SVG | John Tapsell