[HN Gopher] Blurhash: A compact representation of a placeholder ...
       ___________________________________________________________________
        
       Blurhash: A compact representation of a placeholder for an image
        
       Author : notmysql_
       Score  : 190 points
       Date   : 2022-11-04 01:40 UTC (21 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | modeless wrote:
       | I really dislike these and similar super blurry image
       | replacements. They look ugly to me. Just use one color until the
       | image loads, that's way simpler and doesn't look worse than
       | these.
        
       | aloer wrote:
       | I was hoping this would include the unblur animation that wolt
       | uses in their app.
       | 
       | It's a joy to use when it resolves those placeholders piece by
       | piece into the original
        
       | mfsch wrote:
       | I wish something like this was used for the Signal message
       | history, similar to what WhatsApp does. As it is now, you either
       | have an ever growing message database full of pictures you don't
       | need to keep around, or you start deleting them and end up with
       | weird gaps in your message history. Keeping a few bytes of data
       | as a placeholder for deleted images would be optimal in my
       | opinion.
        
         | b4je7d7wb wrote:
         | Seems like signal already uses it for non downloaded images, so
         | your suggestion should be simple enough for them to implement.
        
       | learndeeply wrote:
       | Previous discussion:
       | https://news.ycombinator.com/item?id=22374825
       | 
       | Wonder if anyone's turned Instagram's version of Blurhash into a
       | library?
        
       | cpeterso wrote:
       | Do websites still use progressive JPEGs? The blurhash is much
       | smaller than the data needed to render a progressive JPEG's first
       | pass, but would the progressive rendering on top of the blurhash
       | still be worthwhile on today's fast networks?
        
       | nikeee wrote:
       | These blurry images look like they are composed of a couple of
       | gradients.
       | 
       | Wouldn't it be possible to generate a tiny SVG or some CSS that
       | reproduces these gradients?
       | 
       | In that case, basically no decoding step is needed and
       | integration is as easy as setting a CSS style on a div or
       | including an SVG. If the image dimensions are set from the start,
       | the browser can even continue layouting the page before actually
       | drawing the gradients. Letting the browser decode the gradients
       | should also be much faster.
       | 
       | Is there a library that does that?
        
         | jesuscript wrote:
         | Someone can correct me, but gradients and large box shadows are
         | some of the most intensive things your browser can render.
         | There was noticeable slowdown when you do too much of that.
        
         | wongarsu wrote:
         | At that point, why not just create a 6x3px thumbnail in a
         | format of your choice and let interpolation take care of the
         | gradients.
        
         | wiredearp wrote:
         | Supposedly some library called SQIP might handle that as
         | explained over on https://medium.com/free-code-camp/using-svg-
         | as-placeholders-...
        
         | notpushkin wrote:
         | There certainly is an SVG thing but I don't remember the name.
         | 
         | I think Blurhash is the way it is because Wolt is an app and
         | not a website, so the decoder is already loaded when you open
         | it. For browser use, SVG would be more straightforward.
        
           | mark-r wrote:
           | SVG would be much larger for the same image, it's XML based.
        
             | SergeAx wrote:
             | It would be nice if there was a way to translate/transcode
             | Blurhash directly to SVG with a small piece if TS code.
        
         | fold_left wrote:
         | I had a go at doing this in Rust some time ago
         | https://github.com/JamieMason/blurhash-to-css and there is also
         | https://plaiceholder.co/.
        
           | warpech wrote:
           | Nice!
           | 
           | A CSS Houdini worklet would be another way to represent this
           | in CSS.
           | 
           | https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Houdini
           | 
           | https://houdini.how/
        
             | michaelmior wrote:
             | Interesting idea using Houdini, although I think browser
             | support isn't really good enough yet to justify this.
        
       | jylam wrote:
       | Something related somehow, from 13 years ago, to fit an image in
       | the (then) 140 characters on Twitter:
       | https://www.flickr.com/photos/quasimondo/3518306770
        
       | darekkay wrote:
       | I am using blurhash on my photography website and it works and
       | looks great. But given all the examples and libraries out there,
       | more DIY work than expected was required to implement the main
       | use case for blurhash end-to-end in vanilla JS.
        
       | Dwedit wrote:
       | I've seen something similar before, where a specific JPEG header
       | and specific quantization matrices was added to user-provided
       | binary data to make the very low-res images. That method uses the
       | native JPEG decoder, so it's fast.
        
         | Scaevolus wrote:
         | Instagram does this, sending media previews as ~350B base64
         | strings with constant (well, almost-- they change the width and
         | height) 607B JPEG headers.
        
       | codedokode wrote:
       | What are memory and CPU costs of using this in web pages? For
       | example, when a page with 100 images loads, won't decompressing
       | hashes into 100 canvases take lot of resources and block the page
       | or entire system for several seconds?
       | 
       | The placeholders are blurred and I assume that creating blurred
       | images is pretty expensive and takes O(N^2*M) where N is size of
       | the image and M is number of points.
       | 
       | Wouldn't it be cheaper to use blocky placeholders that take only
       | O(N^2) time to paint?
        
         | ajconway wrote:
         | The amount of work it takes to decode an image is incredibly
         | tiny by today's standards:
         | https://github.com/woltapp/blurhash/blob/master/C/decode.c
        
         | onion2k wrote:
         | _What are memory and CPU costs of using this in web pages? For
         | example, when a page with 100 images loads, won 't
         | decompressing hashes into 100 canvases take lot of resources
         | and block the page or entire system for several seconds?_
         | 
         | If you're sensible and use small input images, and therefore
         | small hashes, it should be fine. It's not actually doing all
         | that much 'work'. Besides, browsers are much faster than people
         | think they are, especially for things like canvas drawing
         | because that happens on the GPU (even in a 2d context.)
         | 
         |  _I assume that creating blurred images is pretty expensive._
         | 
         | The input image is converted to a hash. When the placeholder is
         | needed the hash is converted to a gradient. Essentially it's
         | like picking a few points in an image and then using a gradient
         | function to fill in the spaces between the points. That's
         | something that's easy for a computer for do quickly.
         | 
         | Also, as it happens, blurring an image is fast too. You can
         | implement a Gaussian blur in a convolution filter, and that's
         | just a simple matrix.
        
           | kens wrote:
           | > browsers are much faster than people think they are
           | 
           | Serious question: my 2017 MacBook Air grinds to a halt on
           | many web pages, especially ones with video animation, to the
           | point where I can't type because it drops multiple
           | characters. I have to use an ad blocker to make pages
           | workable. Is this normal or is there something wrong with my
           | machine?
        
             | tokamak-teapot wrote:
             | Occasionally I will accidentally not have an ad blocker,
             | and yes, the amount of CPU required by them can be
             | enormous.
             | 
             | People seem to just be used to them and claim that their
             | computers are 'getting slower', but really they don't use
             | their computer for anything but web browsing and it's only
             | slower because ads are getting worse and worse.
        
           | RunSet wrote:
           | > browsers are much faster than people think they are
           | 
           | Does "people" include you?
           | 
           | Also web pages are more bloated than people think they are.
        
             | onion2k wrote:
             | _Does "people" include you?_
             | 
             | Without wishing to create a paradox, it absolutely does,
             | yes. I've been a web dev since 1997 and I _frequently_ have
             | to remind myself that I don 't always need to optimize
             | things, memoize things, or throw features out based on
             | browser performance any more. I constantly underestimate
             | what browsers are capable of. There's a 'pandemic' of over-
             | optimization that heaps complexity (aka bloat) into web
             | apps unnecessarily based on the mostly wrong belief that
             | browsers are slow.
             | 
             | Devs need to be careful, and they need to measure things.
             | They shouldn't start with the assumption that something
             | will be slow.
             | 
             | What's really interesting about this whole question is that
             | HN's least favorite frontend library, React, suffers this
             | problem. The virtual DOM implementation _was_ necessary a
             | decade ago when React started, but DOM manipulation has
             | been optimized in browsers so now the vdom is actually a
             | bit of a hinderance (React has advantages other than speed,
             | so it 's still a fine choice.) Libraries that HN likes,
             | such as Svelte and Solid, rely on the browser to be fast,
             | _because the browser is fast_.
        
               | RunSet wrote:
               | > Devs need to be careful, and they need to measure
               | things. They shouldn't start with the assumption that
               | something will be slow.
               | 
               | I disagree. The specs of developers' machines typically
               | so far surpass those of users as to make that assumption
               | valid more often than not.
               | 
               | Further, the fail case for incorrectly assuming that a
               | web page will be fast ranges from it being slow to it
               | being unusable, while the fail case for incorrectly
               | assuming that a web page will be slow is that it is
               | slightly more responsive than expected.
        
               | bmacho wrote:
               | > The specs of developers' machines typically so far
               | surpass those of users as to make that assumption valid
               | more often than not.
               | 
               | Billions of people are using computers that are 100 times
               | slower than your machine in different metrics. 100 times
               | less space on hard drive, 100 times slower hard drive,
               | 100 times slower processor, 8-16 times less memory, etc.
               | 
               | But then they probably won't pay you anyway, also if you
               | target them, you have to make compromises that will
               | affect the overall quality.
        
               | jokethrowaway wrote:
               | I don't know in which world you live in but most websites
               | are incredibly unoptimised and over-engineered. They use
               | a huge amount of resources on expensive machines and
               | bring consumer machines to a grind.
               | 
               | I wish we lived in a pandemic of over-optimization.
        
               | joshuacc wrote:
               | It's entirely possible for both things to be true at the
               | same time. Tons of developers prematurely optimizing
               | things that don't matter because they make assumptions
               | about performance. Those assumptions can also mean an
               | epidemic of not optimizing things that *do matter*.
        
           | mark-r wrote:
           | The blurring in this case is just a natural consequence of
           | throwing away all the high-frequency DCT components. And
           | since DCT is used to create JPEGs there are highly optimized
           | versions available.
        
       | z33k wrote:
       | Not sure why I would want to use this instead of progressive
       | image decoding with a (CSS?) blur filter. Instead of a blurred
       | image suddenly flashing to a fully loaded image, the user would
       | see the image quality gradually improve as it loads over the
       | network.
       | 
       | Then again, progressive JPEG or FLIF is not supported that well
       | anywhere, so I guess this could be the best thing right now
       | because it seems to just require HTML5 canvas.
        
         | rbut wrote:
         | A blurhash is much easier to send along with the JSON data used
         | to display the initial page. To see a blurred version of a
         | progressive JPEG the browser must have first started to
         | download that JPEG. When there are many JPEG's to download, it
         | may not even have started downloading yet.
        
         | divan wrote:
         | I typically store it in the DB along with the image ID (or
         | URL). It's being displayed even before network request to the
         | actual image has started. Works like a charm on slow networks.
        
           | zulu-inuoe wrote:
           | Store what? The BlurHash ?
        
             | divan wrote:
             | Correct. It's just 20-30 bytes of data.
        
         | sirn wrote:
         | Mastodon, for example, use it to defer loading of images tagged
         | with Content Warning until the user clicked reveal. It provides
         | a useful context for user to decide whether to view the image,
         | while not require browsers/clients to load the image
         | beforehand.
        
       | [deleted]
        
       | trinovantes wrote:
       | Is the space savings of using a custom base83 encoding really
       | worth it when modern browsers can natively support base64 image
       | encodings?
        
         | PostOnce wrote:
         | base85 is already fairly widely supported also in libraries for
         | many languages, its in python's standard lib
         | 
         | https://en.wikipedia.org/wiki/Ascii85
        
         | mark-r wrote:
         | In this case it looks like a key consideration is the way each
         | data point fits into exactly 2 characters, no tricky bit
         | manipulation going on. I'd say it's pretty clever.
        
         | jerjerjer wrote:
         | It's base83 hash, not base83 image so using base64 won't help
         | any.
        
           | trinovantes wrote:
           | It seems more like a modified version of jpg compression
           | which also uses DCT.
           | 
           | Why not just downsample the original image to 10x10 jpg and
           | encode it as base64 so it can be directly used in an <img>
           | without blocking your main JS thread to decode the image?
           | Apply css blur if you like the soft gradient effect.
        
             | nicoburns wrote:
             | Because a raster format is going to be very inefficient for
             | storing a gradient
        
               | trinovantes wrote:
               | Both formats are trying to encode the parameters of
               | cosine functions except jpg is implemented natively in
               | web browsers, likely with SIMD instructions. Is the ~200
               | bytes in savings per image really worth the extra
               | computation cost you're passing onto your users?
        
               | mark-r wrote:
               | I wonder if you could use Javascript to convert the hash
               | into a full JPEG and get the best of both?
        
       | akrymski wrote:
       | DCT based algo, nice! But what's wrong with using just 4 pixels
       | to represent an image and then blurring that in CSS?
        
       ___________________________________________________________________
       (page generated 2022-11-04 23:03 UTC)