Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose sharp stats? (specifically, dominant color) #377

Open
nick-vincent opened this issue Aug 30, 2022 · 7 comments
Open

Expose sharp stats? (specifically, dominant color) #377

nick-vincent opened this issue Aug 30, 2022 · 7 comments

Comments

@nick-vincent
Copy link
Contributor

Hi there!

Firstly, great lib! I just started using it with SvelteKit and the ability to process images at compile time is a game changer.

I noticed that sharp has a stats API and it would be awesome to use it to dynamically pull the dominant color from an image.

Would it be possible to expose this stats API and return the results via a directive, similar to the metadata directive?

@benmccann
Copy link
Collaborator

I'm curious, what's your use case for this feature?

@nick-vincent
Copy link
Contributor Author

nick-vincent commented Aug 31, 2022

@benmccann: I'm curious, what's your use case for this feature?

For example, it's fairly common to display a BG color while an image is loading that is the dominant color of that image:

CfJlAogoTIiaZka74hqW_pinterest_loading

While it's possible to use canvas to do this client side, that kind of defeats the purpose, since the image must already be fully loaded in the browser for it to work.

Personally, I'm working on an image gallery + lightbox and I would like to use this loading effect for the image loading states.

I'm happy to poke around in the codebase and see if I can submit a PR for this, but I wanted to check in here first of course to even see if this is desired and/or possible!

@JonasKruckenberg
Copy link
Owner

I think this would be a great addition if you want to submit a PR!
I could think of a couple ways the API could look, maybe we can have see which works best:

  1. Add stats directive. This would be the easiest but would conflict with the metadata one, not ideal :/
  2. Add the output object to the standard metadata output. This gives a lot of functionality, but really causes bloat as most people don't use the whitelist feature.
  3. have individual directives for dominantColor, entropy, isOpaque etc. that add their values to the image metadata. Kinda weird design-wise IMO

@benmccann
Copy link
Collaborator

We should figure out how this would interact with a low-quality placeholder (#86), the picture directive, etc.

@nick-vincent
Copy link
Contributor Author

Hi @JonasKruckenberg!

Just returning to this idea after getting more acquainted with the codebase.

Seems to me the easiest option you mentioned would be option 2 — here is a quick & dirty POC for that.

The added stats do seem to be filtered through the allowlist if used, but yeah it does bloat the metadata if you don't use it.

I could also see going with option 1 (adding a stats directive), but I'm not sure how to hook in a new directive like that...

I agree that option 3 would be a little unintuitive API-wise, with the way metadata is currently used.

Let me know if you have any additional thoughts?

@benmccann
Copy link
Collaborator

I think option 2 probably makes the most sense when combined with the metadata filter. Users are going to want to use the metadata filter as with any other metadata to keep the output from getting bloated. So something like &meta=dominantColor. I think we'd need to document which stats are available.

@eltigerchino
Copy link

eltigerchino commented Oct 18, 2023

Here's a custom transform that works now. However, it doesn't cache the results so performance is slow when reloading the page.

import { type TransformFactory } from 'imagetools-core';
import type { VitePluginOptions } from 'vite-imagetools/dist/types';
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';
import { imagetools } from 'vite-imagetools';

const dominantColorDirective = 'dominantColor';

const placeholderTransform: TransformFactory = (config) => {
	return async function (image) {
		if (!(dominantColorDirective in config)) return image;

		const stats = await image.stats();
		const { r, g, b } = stats.dominant;
        // we can set style="background-color: {dominantColor}" on the image element later on
		setMetadata(image, dominantColorDirective, `rgb(${r}, ${g}, ${b})`);

		return image;
	};
};

const imageToolsConfig: Partial<VitePluginOptions> = {
	extendTransforms: (builtins) => {
		return [placeholderTransform, ...builtins];
	}
};

export default defineConfig({
	plugins: [
		imagetools(imageToolsConfig),
		sveltekit()
	],
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants