woltapp / blurhash

A very compact representation of a placeholder for an image.
https://blurha.sh
MIT License
15.85k stars 360 forks source link

Why decoded blurhash is so big? #154

Open rabinpoudyal opened 2 years ago

rabinpoudyal commented 2 years ago

I tried to create a blurhash from 50x50 image and tried decoding it into base64. I got very lengthly string as output (400-2000): /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAFA3PEY8MlBGQUZaVVBfeMiCeG5uePWvuZHI////////////////////////////////////////////////////2wBDAVVaWnhpeOuCguv/////////////////////////////////////////////////////////////////////////wAARCAAgACADAREAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAQMCBP/EABgQAQEBAQEAAAAAAAAAAAAAAAEAAhES/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFREBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhEDEQA/AM5YioxQtRntESzZiqjUC1GFoihiNHzAJBhzRHSFpSkE9EByg//Z

Is there any way to shorten this string? It seems airbnb also has similar blurhash implementation but they have only 179character long encoded base64 string for images. I am trying to decode in server since the page has lot of images and not feasible to decode in client side.

predaytor commented 2 years ago

Not sure why it takes such long string in your example, I'm using sharp with 16px sizes, blur 4px, and you should pick lossless for better compression (great quality, less artifacts).


export async function resolveBlurhashURI(hash: string, width = 16, height = 16, punch = 1) {
    if (!isBlurhashValid(hash)) throw Error('invalid hash');

    const pixels = decode(hash, width, height, punch);

    const resizedImageBuffer = await sharp(Buffer.from(pixels), {
        raw: {
            channels: 4,
            width,
            height,
        },
    })
        .webp({
            lossless: true,
            smartSubsample: true,
            quality: 100,
        })
                .blur(4)
        .toBuffer();

    return `data:image/webp;base64,${resizedImageBuffer.toString('base64')}`;
}
ahmadkhalaf1 commented 1 year ago

Not sure why it takes such long string in your example, I'm using sharp with 16px sizes, blur 4px, and you should pick lossless for better compression (great quality, less artifacts).

export async function resolveBlurhashURI(hash: string, width = 16, height = 16, punch = 1) {
  if (!isBlurhashValid(hash)) throw Error('invalid hash');

  const pixels = decode(hash, width, height, punch);

  const resizedImageBuffer = await sharp(Buffer.from(pixels), {
      raw: {
          channels: 4,
          width,
          height,
      },
  })
      .webp({
          lossless: true,
          smartSubsample: true,
          quality: 100,
      })
                .blur(4)
      .toBuffer();

  return `data:image/webp;base64,${resizedImageBuffer.toString('base64')}`;
}

Can i use this with nodejs ? can you please show an example how would this function work ? can i pass an image url and it will hash it for me + sharp optimization ? where does decode function comes from?

Thanks