node.jssvgcolorssharp

Colourise unfilled svgs with Sharp


I want to use Sharp to colorise SVG files without a fill attribute (these look black in my browser) and export the result as a png. Currently I'm using the following process:

sharp().modulate({ lightness: 50 }).tint({ r: 255, g: 0, b: 0 }).png();

This correctly colourises the SVG as red. However if I try the same approach with yellow:

sharp().modulate({ lightness: 50 }).tint({ r: 255, g: 255, b: 0 }).png();

I get a grubby brown colour, whereas the following (note the lightness change from 50 to 100) works as expected:

sharp().modulate({ lightness: 100 }).tint({ r: 255, g: 255, b: 0 }).png();

So it seems that lightness value needs to be varied depending on the colour.

Given an RGB target colour, how can I calculate what the lightness value should be, or is there a better approach?


Solution

  • After reading around the issue and seeing this discussion, I decided to use a different approach.

    Rather than working with modulate and tint, I generate a rectangle the size of my image and of the required overlay colour, and composite this with my source image with blend mode in:

    const writableStream = fs.createWriteStream('my_image.png')
    readableStream.pipe(sharp().resize(200, 200).composite([{
     input: {
      create: {
       width: 200,
       height: 200,
       channels: 4,
       background: { r: 255, g: 0, b: 0 }
      }
     }, blend: 'in'
    }])).pipe(writableStream);