{"id":13392692,"url":"https://github.com/woltapp/blurhash","last_synced_at":"2025-05-12T05:24:28.526Z","repository":{"id":37746739,"uuid":"193885464","full_name":"woltapp/blurhash","owner":"woltapp","description":"A very compact representation of a placeholder for an image.","archived":false,"fork":false,"pushed_at":"2024-07-08T22:23:42.000Z","size":12283,"stargazers_count":16319,"open_issues_count":47,"forks_count":370,"subscribers_count":72,"default_branch":"master","last_synced_at":"2025-05-12T02:41:10.133Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://blurha.sh","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/woltapp.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"License.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-06-26T10:45:33.000Z","updated_at":"2025-05-11T22:40:40.000Z","dependencies_parsed_at":"2024-01-15T14:56:37.956Z","dependency_job_id":"699fc77e-4975-4e66-89a3-0376141336fd","html_url":"https://github.com/woltapp/blurhash","commit_stats":{"total_commits":258,"total_committers":63,"mean_commits":4.095238095238095,"dds":0.8178294573643411,"last_synced_commit":"f1edb10ba0e0b78c95698488c7665fcb75d69aa2"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/woltapp%2Fblurhash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/woltapp%2Fblurhash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/woltapp%2Fblurhash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/woltapp%2Fblurhash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/woltapp","download_url":"https://codeload.github.com/woltapp/blurhash/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253672698,"owners_count":21945480,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T17:00:35.069Z","updated_at":"2025-05-12T05:24:28.502Z","avatar_url":"https://github.com/woltapp.png","language":"C","readme":"# [BlurHash](http://blurha.sh)\n\nBlurHash is a compact representation of a placeholder for an image.\n\n## Why would you want this?\n\nDoes your designer cry every time you load their beautifully designed screen, and it is full of empty boxes because all the\nimages have not loaded yet? Does your database engineer cry when you want to solve this by trying to cram little thumbnail\nimages into your data to show as placeholders?\n\nBlurHash will solve your problems! How? Like this:\n\n\u003cimg src=\"Media/WhyBlurHash.png\" width=\"600\"\u003e\n\nYou can also see nice examples and try it out yourself at [blurha.sh](http://blurha.sh/)!\n\n## How does it work?\n\nIn short, BlurHash takes an image, and gives you a short string (only 20-30 characters!) that represents the placeholder for this\nimage. You do this on the backend of your service, and store the string along with the image. When you send data to your\nclient, you send both the URL to the image, and the BlurHash string. Your client then takes the string, and decodes it into an\nimage that it shows while the real image is loading over the network. The string is short enough that it comfortably fits into\nwhatever data format you use. For instance, it can easily be added as a field in a JSON object.\n\nIn summary:\n\n\u003cimg src=\"Media/HowItWorks1.jpg\" width=\"250\"\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cimg src=\"Media/HowItWorks2.jpg\" width=\"250\"\u003e\n\nWant to know all the gory technical details? Read the [algorithm description](Algorithm.md).\n\nImplementing the algorithm is actually quite easy! Implementations are short and easily ported to your favourite language or\nplatform.\n\n## Implementations\n\nSo far, we have created these implementations:\n\n* [C](C) - An encoder implementation in portable C code.\n* [Swift](Swift) - Encoder and decoder implementations, and a larger library offering advanced features.\n  There is also an example app to play around with the algorithm.\n* [Kotlin](Kotlin) - A decoder implementation for Android.\n* [TypeScript](TypeScript) - Encoder and decoder implementations, and an example page to test.\n* [Python](https://github.com/woltapp/blurhash-python) - Integration of the C encoder code into Python.\n\nThese cover our use cases, but could probably use polishing, extending and improving. There are also these third party implementations that we know of:\n\n* [Pure Python](https://github.com/halcy/blurhash-python) - Implementation of both the encoder and decoder in pure Python.\n* [One version in Go](https://github.com/bbrks/go-blurhash), and [another version in Go](https://github.com/buckket/go-blurhash).\n* [PHP](https://github.com/kornrunner/php-blurhash) - Encoder and decoder implementations in pure PHP.\n* [Java](https://github.com/hsch/blurhash-java) - Encoder implementation in Java.\n* [Clojure](https://github.com/siili-core/blurhash) - Encoder and decoder implementations in Clojure.\n* [Nim](https://github.com/SolitudeSF/blurhash) - Encoder and decoder implementation in pure Nim.\n* [Rust and WebAssembly](https://github.com/fpapado/blurhash-rust-wasm) - Encoder and decoder implementations in Rust. Distributed as both native Rust and WebAssembly packages.\n* [Ruby](https://github.com/Gargron/blurhash) - Encoder implementation in Ruby.\n* [Crystal](https://github.com/Sija/blurhash.cr) - Encoder implementation in pure Crystal.\n* [Elm](https://github.com/WhileTruu/elm-blurhash) - Encoder and decoder in Elm.\n* [Dart](https://github.com/folksable/blurhash_ffi) - Encoder and decoder implementation in C into Dart using dart-ffi.\n* [Pure Dart](https://github.com/justacid/blurhash-dart) - Encoder and decoder implementation in pure Dart.\n* [.NET](https://github.com/MarkusPalcer/blurhash.net) - Encoder and decoder in C#.\n* [JavaScript](https://github.com/Dens49/blurhash-js) - Encoder and decoder implementation in pure JavaScript.\n* [.NET](https://github.com/Bond-009/BlurHashSharp) - Encoder implementation in C#.\n* [Haskell](https://github.com/SamProtas/JuicyPixels-blurhash) - Encoder and decoder in pure Haskell.\n* [Scala](https://github.com/markussammallahti/blurhash-scala) - Encoder and decoder in Scala.\n* [Elixir](https://github.com/perzanko/blurhash-elixir) - Encoder implementation in pure Elixir.\n* [ReScript](https://github.com/armedi/rescript-blurhash) - Encoder and decoder implementation in ReScript (BuckleScript).\n* [JavaScript](https://github.com/mad-gooze/fast-blurhash) - Tiny optimized decoder implementation JS.\n* [Xojo](https://github.com/piradoiv/xojo-blurhash/) - Encoder and decoder implementation in pure Xojo.\n* [React Native](https://github.com/mrousavy/react-native-blurhash) - UI Component for React Native. (Decoder in Swift and Kotlin)\n* [Zig](https://github.com/mhoward540/blurhash-zig) - Encoder implementation in Zig.\n* [Titanium SDK](https://github.com/m1ga/ti.blurhash) - Decoder for Titanium SDK (Android)\n* [BQN](https://github.com/dancek/blurhash-bqn) - Encoder, decoder and terminal viewer in pure BQN.\n* [Jetpack Compose](https://github.com/wajahat-iqbal/BlurHashPainter) - Decoder Jetpack Compose implementation\n* [C++](https://github.com/Nheko-Reborn/blurhash) - Encoder and decoder in C++.\n* [Kotlin Multiplatform](https://github.com/vanniktech/blurhash) - Encoding \u0026 decoding for Android, iOS \u0026 JVM\n* [OCaml](https://github.com/ushitora-anqou/ocaml-blurhash) - Encoder implementation in OCaml.\n\nCan't find the language you're looking for? Try your luck with the GitHub search. For example, here are the search results for [repos which have \"blurhash\" in their name](https://github.com/search?q=blurhash+in%3Aname\u0026type=repositories).\n\nPerhaps you'd like to help extend this list? Which brings us to...\n\n## Contributing\n\nWe'd love contributions! The algorithm is [very simple](Algorithm.md) - less than two hundred lines of code - and can easily be\nported to your platform of choice. And having support for more platforms would be wonderful! So, Java decoder? Golang encoder?\nHaskell? Rust? We want them all!\n\nWe will also try to tag any issues on our [issue tracker](https://github.com/woltapp/blurhash/issues) that we'd love help with, so\nif you just want to dip in, go have a look.\n\nYou can file a pull request with us, or you can start your own repo and project if you want to run everything yourself, we don't mind.\n\nIf you do want to contribute to this project, we have a [code of conduct](CodeOfConduct.md).\n\n## Users\n\nWho uses BlurHash? Here are some projects we know about:\n\n* [Wolt](http://wolt.com/) - We are of course using it ourselves. BlurHashes are used in the mobile clients on iOS and Android, as well as on the web, as placeholders during image loading.\n* [Mastodon](https://github.com/tootsuite/mastodon) - The Mastodon decentralised social media network uses BlurHashes both as loading placeholders, as well as for hiding media marked as sensitive.\n* [Signal](https://signal.org/) - Signal Private Messenger uses Blurhashes as placeholders before photo \u0026 video messages are downloaded in chat conversations.\n* [Jellyfin](https://jellyfin.org/) - Jellyfin the free software media system uses Blurhashes as placeholders for images of movies and TV shows when they are being downloaded.\n\n## Good Questions\n\n### How fast is encoding? Decoding?\n\nThese implementations are not very optimised. Running them on very large images can be a bit slow. The performance of\nthe encoder and decoder are about the same for the same input or output size, so decoding very large placeholders, especially\non your UI thread, can also be a bit slow.\n\nHowever! The trick to using the algorithm efficiently is to not run it on full-sized data. The fine detail of an image is all thrown away,\nso you should scale your images down before running BlurHash on them. If you are creating thumbnails, run BlurHash on those\ninstead of the full images.\n\nSimilarly, when displaying the placeholders, very small images work very well when scaled up. We usually decode placeholders\nthat are 32 or even 20 pixels wide, and then let the UI layer scale them up, which is indistinguishable from decoding them at full size.\n\n### How do I pick the number of X and Y components?\n\nIt depends a bit on taste. The more components you pick, the more information is retained in the placeholder, but the longer\nthe BlurHash string will be. Also, it doesn't always look good with too many components. We usually go with 4 by 3, which\nseems to strike a nice balance.\n\nHowever, you should adjust the number of components depending on the aspect ratio of your images. For instance, very wide\nimages should have more X components and fewer Y components.\n\nThe Swift example project contains a test app where you can play around with the parameters and see the results.\n\n### What is the `punch` parameter in some of these implementations?\n\nIt is a parameter that adjusts the contrast on the decoded image. 1 means normal, smaller values will make the effect more subtle,\nand larger values will make it stronger. This is basically a design parameter, which lets you adjust the look.\n\nTechnically, what it does is scale the AC components up or down.\n\n### Is this only useful as an image loading placeholder?\n\nWell, that is what it was designed for originally, but it turns out to be useful for a few other things:\n\n* Masking images without having to use expensive blurs - [Mastodon](http://github.com/tootsuite/mastodon) uses it for this.\n* The data representation makes it quite easy to extract colour averages of the image for different areas. You can easily find approximations of things like the average colour of the top edge of the image, or of a corner. There is some code in the Swift BlurHashKit implementation to experiment with this. Also, the average colour of the entire image is just the DC component and can be decoded even without implementing any of the more complicated DCT stuff.\n* We have been meaning to try to implement tinted drop shadows for UI elements by using the BlurHash and extending the borders. Haven't actually had time to implement this yet though.\n\n### Why base 83?\n\nFirst, 83 seems to be about how many low-ASCII characters you can find that are safe for use in all of JSON, HTML and shells.\n\nSecondly, 83 * 83 is very close to, and a little more than, 19 * 19 * 19, making it ideal for encoding three AC components in two\ncharacters.\n\n### What about using the full Unicode character set to get a more efficient encoding?\n\nWe haven't looked into how much overhead UTF-8 encoding would introduce versus base 83 in single-byte characters, but\nthe encoding and decoding would probably be a lot more complicated, so in the spirit of minimalism BlurHash uses the simpler\noption. It might also be awkward to copy-paste, depending on OS capabilities.\n\nIf you think it can be done and is worth it, though, do make your own version and show us! We'd love to see it in action.\n\n### What about other basis representations than DCT?\n\nThis is something we'd *love* to try. The DCT looks quite ugly when you increase the number of components, probably because\nthe shape of the basis functions becomes too visible. Using a different basis with more aesthetically pleasing shape might be\na big win.\n\nHowever, we have not managed come up with one. Some experimenting with a [Fourier-Bessel base](https://en.wikipedia.org/wiki/Fourier–Bessel_series),\ntargeted at images that are going to be cropped into circles has been done, but without much success. Here again we'd love\nto see what you can come up with!\n\n## Authors\n\n* [Dag Ågren](https://github.com/DagAgren) - Original algorithm design, Swift and C implementations\n* [Mykhailo Shchurov](https://github.com/shchurov) - Kotlin decoder implementation\n* [Hang Duy Khiem](https://github.com/hangduykhiem) - Android demo app\n* [Olli Mahlamäki](https://github.com/omahlama) - TypeScript decoder and encoder implementations\n* [Atte Lautanala](https://github.com/lautat) - Python integration\n* [Lorenz Diener](https://github.com/halcy) - Pure Python implementation\n* [Boris Momčilović](https://github.com/kornrunner) - Pure PHP implementation\n* [Hendrik Schnepel](https://github.com/hsch) - Java encoder implementation\n* [Tuomo Virolainen](https://github.com/tvirolai) - Clojure implementation\n* [Fotis Papadogeorgopoulos](https://github.com/fpapado) - Rust and WebAssembly implementation\n* [Sam Protas](https://github.com/SamProtas) - Pure Haskell implementation\n* [Markus Sammallahti](https://github.com/markussammallahti) - Scala implementation\n* [Kacper Perzankowski](https://github.com/perzanko) - Elixir encoder implementation\n* [Belvi Nosakhare](https://github.com/KingsMentor/BlurHashExt) - Kotlin extensions of Blurhash for ImageView, Glide, and Piccasso optimized for Android.\n* [Armedi](https://github.com/armedi) - ReScript (BuckleScript) implementation.\n* [Ricardo Cruz](https://github.com/piradoiv) - Xojo implementation.\n* [Marc Rousavy](https://github.com/mrousavy) - React Native UI Component\n* [Matt Howard](https://github.com/mhoward540) - Zig implementation\n* [Hannu Hartikainen](https://github.com/dancek) - BQN implementation\n* [Wajahat Iqbal](https://github.com/wajahat-iqbal) - Jetpack compose-based implementation optimized for using any component as a painter.\n\n\n* _Your name here?_\n","funding_links":[],"categories":["C","Graphics","GIT 仓库","others","\u003ca name=\"for-projects\"\u003e\u003c/a\u003e For Projects"],"sub_categories":["图像、图片处理","\u003ca name=\"for-projects-example-projects\"\u003e\u003c/a\u003e Example Projects"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwoltapp%2Fblurhash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwoltapp%2Fblurhash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwoltapp%2Fblurhash/lists"}