sharp icon indicating copy to clipboard operation
sharp copied to clipboard

Enhancement: calculate stats dominant colour using a linear colourspace, plus apply ICC profiles first

Open chuckdries opened this issue 2 years ago • 1 comments

Question about an existing feature

What are you trying to achieve?

I'm building a photo gallery where the photos are sorted by the HSL hue of the dominant color. For roughly half of the images, however, the dominant color is a shade of grey. Some of these images are very colorful, so this is surprising. Is there anything I can do to coerce it into spitting out something more colorful?

When you searched for similar issues, what did you find that might be related?

https://github.com/lovell/sharp/issues/640 https://github.com/lovell/sharp/issues/2708

Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this question

const sharp = require("sharp");

async function getDominantHue(path) {
  const {
    dominant: { r, g, b },
  } = await sharp(path).stats();
  console.log(`rgb(${r}, ${g}, ${b})`);
}

getDominantHue("./images/_DSC5896.jpg");
getDominantHue("./images/DSC02610.jpg");

https://github.com/chuckdries/sharp-question is the above script packaged with sample images. If you clone, install, and run it, you'll see that for both images (one of which is extremely yellow, the other is extremely blue), it spits out a very very dark gray (rgb(8,8,8))

Please provide sample image(s) that help explain this question

  • https://raw.githubusercontent.com/chuckdries/sharp-question/main/images/_DSC5896.jpg
  • https://raw.githubusercontent.com/chuckdries/sharp-question/main/images/DSC02610.jpg

chuckdries avatar Jun 21 '22 19:06 chuckdries

The dominant colour logic is a relatively simple histogram-based approach in the non-linear sRGB space, which very much favours speed over accuracy.

https://github.com/lovell/sharp/blob/c1b13adac373102dfdd1753d8aa29a1df82c8245/src/stats.cc#L91-L102

The RGB value (8,8,8) represents the darkest bin, and it's likely that darker images are more likely to fill this when generating the histogram. I also note these images have ICC profiles, which are currently ignored during the stats() call, and this could exacerbate the darkest-bin-wins problem.

This is probably something that will need some experimentation, with the first things to consider being (a) the use of an alternative colourspace such as LAB and (b) transforming with embedded ICC profiles, if any.

lovell avatar Jun 22 '22 13:06 lovell