Blurhash Python Library
The `blurhash` library is a pure-Python implementation of the BlurHash algorithm, allowing you to create compact, unique hashes for images that represent a blurred placeholder. This is useful for lazy-loading images on the web. The current version is 1.1.5, with releases occurring infrequently, primarily for distribution updates rather than core code changes.
Common errors
-
ValueError: Image data is not in the expected format (width * height * 4 required)
cause The `encode` function received a pixel data list whose length does not match `width * height * 4`. This often happens if the input image was RGB (3 channels) but the function expects RGBA (4 channels) implicitly, or if the width/height parameters are incorrect for the provided data.fixEnsure your `pixel_data` list contains `width * height * 4` elements, where 4 accounts for R, G, B, and A channels. If your source image is RGB, you might need to convert it to RGBA before flattening the pixel data (e.g., `img.convert('RGBA')` with Pillow). -
IndexError: tuple index out of range (when using img.putpixel or similar in reconstruction)
cause This error typically occurs when trying to reconstruct an image from decoded pixel data if the `width` and `height` provided to `decode` do not result in a pixel array that can be correctly mapped to an image of those dimensions. It can also happen if `decoded_pixels` length isn't a multiple of 4 (for RGBA).fixVerify that the `width` and `height` passed to `decode` are correct and that the resulting `decoded_pixels` list has a length of `width * height * 4`. When using `putdata` with Pillow, ensure the list of tuples is correctly formed, i.e., `list(zip(*[iter(decoded_pixels)]*4))` for RGBA. -
TypeError: encode() missing 2 required positional arguments: 'width' and 'height'
cause The `encode` function requires the `pixel_data` list, `width`, `height`, `x_components`, and `y_components` as arguments. This error means `width` and `height` were omitted.fixAlways provide the correct `width` and `height` of the original image whose pixel data you are passing to the `encode` function: `encode(pixel_data, image_width, image_height, x_components, y_components)`.
Warnings
- gotcha The `encode` function expects raw pixel data as a flat list of RGBA integers, not a Pillow `Image` object or a NumPy array directly. You must manually extract and flatten the pixel data.
- gotcha When calling `encode`, the `x_components` and `y_components` parameters determine the detail level of the blurhash. Using very low values (e.g., 1 or 2) can result in a highly pixelated or blocky hash that might not adequately represent the original image, while very high values increase the hash string's length without much visual gain.
- gotcha The `decode` function reconstructs pixel data for a specified output `width` and `height`. If these dimensions are significantly different from the *aspect ratio* of the original image that generated the blurhash, the decoded blurred image might appear stretched or distorted.
Install
-
pip install blurhash -
pip install Pillow
Imports
- encode
from blurhash import encode
- decode
from blurhash import decode
Quickstart
import os
from PIL import Image
from blurhash import encode, decode
# 1. Create a dummy image for demonstration
width, height = 32, 32
img = Image.new('RGBA', (width, height), color = 'red')
img.putpixel((0, 0), (0, 255, 0, 255)) # Green pixel at top-left
img.putpixel((width-1, height-1), (0, 0, 255, 255)) # Blue pixel at bottom-right
# Prepare image data for blurhash (flat list of RGBA values)
# The library expects pixel data as a flat list, not a Pillow Image object directly.
# If your image is RGB, you might need to convert it to RGBA first.
pixel_data = []
for y in range(height):
for x in range(width):
r, g, b, a = img.getpixel((x, y))
pixel_data.extend([r, g, b, a])
# 2. Encode the image
x_components = 4 # How many color components horizontally
y_components = 3 # How many color components vertically
blurhash_string = encode(pixel_data, width, height, x_components, y_components)
print(f"Generated BlurHash: {blurhash_string}")
# 3. Decode the blurhash string back into pixel data
output_width = 160
output_height = 90
decoded_pixels = decode(blurhash_string, output_width, output_height)
# 4. Reconstruct image from decoded pixels (using Pillow)
decoded_img = Image.new('RGBA', (output_width, output_height))
decoded_img.putdata(list(zip(*[iter(decoded_pixels)]*4)))
# 5. Save the original and decoded images
original_path = 'original_image.png'
decoded_path = 'decoded_blurhash.png'
img.save(original_path)
decoded_img.save(decoded_path)
print(f"Original image saved to {original_path}")
print(f"Decoded blurhash image saved to {decoded_path}")
# Clean up (optional)
# os.remove(original_path)
# os.remove(decoded_path)