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

Image Placeholders #52

Open
OliverSpeir opened this issue Apr 3, 2024 · 5 comments
Open

Image Placeholders #52

OliverSpeir opened this issue Apr 3, 2024 · 5 comments

Comments

@OliverSpeir
Copy link
Collaborator Author

https://discord.com/channels/830184174198718474/846469231176056853/1277731809467175014

---
import { getPixels } from "@unpic/pixels";
import type { UnresolvedImageTransform } from "astro";
import type { HTMLAttributes } from "astro/types";
import { getImage, type LocalImageProps } from "astro:assets";
import { readFile } from "node:fs/promises";
import sharp from "sharp";
import { rgbaToThumbHash, thumbHashToDataURL } from "thumbhash";

type Props = Omit<LocalImageProps, "src"> & {
  src: ImageMetadata;
};

const props = Astro.props;

if (typeof props.width === "string") {
  props.width = parseInt(props.width);
}

if (typeof props.height === "string") {
  props.height = parseInt(props.height);
}

const image = await getImage(props);

const opts: UnresolvedImageTransform = {
  src: Astro.props.src,
  format: "png",
};

const [w, h] = [image.attributes.width, image.attributes.height];

// if pic is 1:1 or wider than tall
if (w >= h) {
  opts.width = 100;
}

// if pic is 1:1 or taller than wide
if (h >= w) {
  opts.height = 100;
}
let buf = import.meta.env.PROD
  ? await sharp(await readFile(`./dist/${props.src.src}`))
    .resize({
      width: 100,
      height: 100,
      fit: "inside",
      withoutEnlargement: true,
    })
    .png()
    .modulate({ saturation: 1.2 })
    .toBuffer()
  : await getImage(opts)
    .then(_ => new URL(_.src, Astro.url));

const { height, width, data } = await getPixels(buf);
const hash = rgbaToThumbHash(width, height, data);
const src = thumbHashToDataURL(hash);

const additionalAttributes: HTMLAttributes<"img"> = {};
if (image.srcSet.values.length > 0) {
  additionalAttributes.srcset = image.srcSet.attribute;
}
---

<img
  src={src}
  data-src={image.src}
  data-srcset={additionalAttributes.srcset}
  {...additionalAttributes}
  {...image.attributes}
/>

<script>
import { lazyLoad } from "unlazy";

lazyLoad();
</script>

@OliverSpeir
Copy link
Collaborator Author

@sarah11918
Copy link
Member

haha.. just came here to post that same article!

@OliverSpeir
Copy link
Collaborator Author

https://www.robinosborne.co.uk/2018/01/05/image-placeholders-do-it-right-or-dont-do-it-at-all-please/

Not sure I agree with this honestly

The main point of the article I got was don't do blurry LQIP (low quality image placeholders) instead just do a lower quality (but still recognizable) version of the original image

@alexanderniebuhr
Copy link
Member

Thanks for all the information and context.. I need to block myself some time to go over this.

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

No branches or pull requests

3 participants