def blurhashUpload(): try: if "image" not in request.files: return { "message": 'No image sent in payload' }, 400 image_file = request.files['image'] if not allowed_file(image_file.filename): return { "message": "A invalid file was supplied as an image. Only .png, .jpg, .jpeg, and .gif are allowed" }, 403 xComp = 3 yComp = 3 try: xComp = int(request.form['x'], 10) yComp = int(request.form['y'], 10) except: defaultValues = True finally: if (xComp > 9 or yComp > 9): xComp = xComp if xComp < 9 else 9 yComp = yComp if yComp < 9 else 9 hash = blurhash.encode( image_file, x_components=xComp, y_components=yComp) return { "message": f"Hash Successfully Generated for {image_file.filename} with coordinates X{xComp} Y{yComp}", "warning": "Coordinate value over 9 was given, it was reduced to 9", "blurhash": hash }, 200 else: hash = blurhash.encode( image_file, x_components=xComp, y_components=yComp) if defaultValues: return { "message": f"Hash Successfully Generated for '{image_file.filename}' with coordinates X{xComp} Y{yComp}", "warning": "Default values of 3 were used for X and/or Y, as values were not provided", "blurhash": hash }, 200 else: return { "message": f"Hash Successfully Generated for '{image_file.filename}' with coordinates X{xComp} Y{yComp}", "blurhash": hash }, 200 except Exception as err: return { "message": "A server error occurred", "error": str(err) }, 500
def get_file(): file: FileStorage = request.files["file"] filename = secure_filename(file.filename) if len(filename) < 4: return "Invalid filename", 400 if filename.split(".")[-1] not in ["jpg", "png", "jpeg"]: return "Filetype not allowed", 400 if not isdir("files"): mkdir("files") files = listdir("files/") if len(files) != 0: remove(f"files/{files[0]}") if isfile("blurhash_str.txt"): remove("blurhash_str.txt") file.save(f"files/{filename}") del file blurhash_str = blurhash.encode(f"files/{filename}", x_components=4, y_components=3) with open("blurhash_str.txt", "w") as f: f.write(blurhash_str) return "File was successfully submitted."
def test_components(): image = PIL.Image.open(os.path.join(base_path, "cool_cat.jpg")) blur_hash = blurhash.encode(np.array(image.convert("RGB")), components_x=8, components_y=3) size_x, size_y = blurhash.components(blur_hash) assert size_x == 8 assert size_y == 3
def generate_hash(): url = str(request.args.get('url')) x_components = int(request.args.get('x_comp')) y_components = int(request.args.get('y_comp')) image = requests.get(url, stream=True) return blurhash.encode(image.raw, x_components=x_components, y_components=y_components)
def test_asymmetric(): image = PIL.Image.open(os.path.join(base_path, "cool_cat.jpg")) blur_hash = blurhash.encode(np.array(image.convert("RGB")), components_x=2, components_y=8) assert blur_hash == "%BMOZfK1BBNG2skqs9n4?HvgJ.Nav}J-$%sm" decoded_image = blurhash.decode(blur_hash, 32, 32) assert np.sum(np.var(decoded_image, axis=0)) > np.sum( np.var(decoded_image, axis=1)) blur_hash = blurhash.encode(np.array(image.convert("RGB")), components_x=8, components_y=2) decoded_image = blurhash.decode(blur_hash, 32, 32) assert np.sum(np.var(decoded_image, axis=0)) < np.sum( np.var(decoded_image, axis=1))
def test_blurhashes_values(self): try: data = parse.DATA except AttributeError: self.skipTest("Json data not found") for item in data['restaurants']: img = requests.get(item['image'], stream=True) hash = blurhash.encode(img.raw, x_components=4, y_components=4) self.assertEqual(item['blurhash'], hash)
def test_linear_dc_only(): image = PIL.Image.open(os.path.join(base_path, "cool_cat.jpg")) linearish_image = np.array(image.convert("RGB")) / 255.0 blur_hash = blurhash.encode(linearish_image, components_x=1, components_y=1, linear=True) avg_color = blurhash.decode(blur_hash, 1, 1, linear=True) reference_avg_color = np.mean( linearish_image.reshape( linearish_image.shape[0] * linearish_image.shape[1], -1), 0) assert np.sum(np.abs(avg_color - reference_avg_color)) < 0.01
def processImage(): file = request.files['file'] width = int(request.form.get('width', 128)) height = int(request.form.get('height', 128)) image = np.array(PIL.Image.open(file).convert("RGB")) blur_hash = blurhash.encode(np.array(image)) img = PIL.Image.fromarray( np.array(blurhash.decode(blur_hash, width, height)).astype('uint8')) fp = tempfile.NamedTemporaryFile(delete=False) img.save(fp, format='PNG') fp.close() return send_file(fp.name, mimetype='image/png')
def get_blurhash(self, resp_raw): """Extracts image's blurhash from HTTP request Parameters: resp_raw (Response): raw response of the request Returns: int: blurhash of the image """ try: blurhash_code = blurhash.encode(resp_raw, comp_x=4, comp_y=5) except Exception as error: logging.error("Cannot get blurhash: ", error) return None return blurhash_code
def set_blur_hash(doc): # TODO create doctype settings for components if doc.file_url: if doc.file_url.startswith("/files"): try: image, filename, extn = get_local_image(doc.file_url) image.thumbnail(MAX_RESIZE) except IOError: return else: try: image, filename, extn = get_web_image(doc.file_url) image.thumbnail(MAX_RESIZE) except (requests.exceptions.HTTPError, requests.exceptions.SSLError, IOError, TypeError): return doc.db_set('blurhash', blurhash.encode(np.array(image.convert("RGB")))) return doc
def test_invalid_parameters(): image = np.array( PIL.Image.open(os.path.join(base_path, "cool_cat.jpg")).convert("RGB")) with pytest.raises(ValueError): blurhash.decode("UBMO", 32, 32) with pytest.raises(ValueError): blurhash.decode("UBMOZfK1GG%LBBNG", 32, 32) with pytest.raises(ValueError): blurhash.encode(image, components_x=0, components_y=1) with pytest.raises(ValueError): blurhash.encode(image, components_x=1, components_y=0) with pytest.raises(ValueError): blurhash.encode(image, components_x=1, components_y=10) with pytest.raises(ValueError): blurhash.encode(image, components_x=10, components_y=1)
def getBlurCodeFromImage(imageUrl): image = getImageBytes(imageUrl) return blurhash.encode(image, x_components=4, y_components=6)
def test_encode_black_and_white_picture(): result = encode('tests/pic2_bw.png', 4, 3) assert result == 'LjIY5?00?bIUofWBWBM{WBofWBj['
def test_invalid_image(): with pytest.raises(IOError): encode('README.md', 4, 3)
def test_file_does_not_exist(): with pytest.raises(IOError): encode('pic404.png', 4, 3)
def test_invalid_x_components(): with pytest.raises(ValueError): encode('tests/pic2.png', 10, 3) with pytest.raises(ValueError): encode('tests/pic2.png', 0, 3)
import blurhash hash = blurhash.encode('bin/image.jpg', x_components=4, y_components=3) print(hash)
def test_invalid_y_components(): with pytest.raises(ValueError): encode('tests/pic2.png', 4, 10) with pytest.raises(ValueError): encode('tests/pic2.png', 4, 0)
def test_encode_file(): with open('tests/pic2.png', 'rb') as image_file: result = encode(image_file, 4, 3) assert result == 'LlMF%n00%#MwS|WCWEM{R*bbWBbH'
min( target_components, round(image_linear_thumb.shape[1] / (work_size / target_components))))) components_y = int( max( min_components, min( target_components, round(image_linear_thumb.shape[0] / (work_size / target_components))))) print("Using component counts: {} x {}".format(components_x, components_y)) # Create blurhash blur_hash = blurhash.encode(image_linear_thumb, components_x, components_y, linear=True) print("Blur hash of image: " + blur_hash) """ Part 2: Decode """ # Figure out what size to decode to decode_components_x, decode_components_y = blurhash.components(blur_hash) decode_size_x = decode_components_x * (work_size // target_components) decode_size_y = decode_components_y * (work_size // target_components) print("Decoder working at size {} x {}".format(decode_size_x, decode_size_y)) # Decode decoded_image = np.array( blurhash.decode(blur_hash, decode_size_x, decode_size_y, linear=True))
def test_encode(): image = PIL.Image.open(os.path.join(base_path, "cool_cat.jpg")) blur_hash = blurhash.encode(np.array(image.convert("RGB"))) assert blur_hash == "UBMOZfK1GG%LBBNG,;Rj2skq=eE1s9n4S5Na"
def test_encode_with_filename(): result = encode('tests/pic2.png', 4, 3) assert result == 'LlMF%n00%#MwS|WCWEM{R*bbWBbH'
import json image_dir = './public/images' files = [] hashes = [] with open('./public/private/hashes.json', 'r') as f: hashes = json.load(f) for file in os.listdir(image_dir): if '/images/' + file in [file["image"] for file in hashes]: continue path = image_dir + '/' + file files.append({"file": file, "path": path}) files.sort(key=lambda f: f['file']) for idx, file in enumerate(files): with open(file['path'], 'rb') as f: hash = blurhash.encode(f, 4, 3) print(f'{file["file"]} - {hash}') hashes.append({"image": '/images/' + file["file"], "hash": hash}) with open('./public/private/hashes.json', 'w') as f: json.dump(hashes, f)
def processImage(): image = PIL.Image.open(input_image).convert("RGB") image_size = (image.width, image.height) print("Read image " + input_image + "({} x {})".format(image_size[0], image_size[1])) # Convert to linear and thumbnail image_linear = np.vectorize(blurhash.srgb_to_linear)(np.array(image)) image_linear_thumb = [] for i in range(3): channel_linear = PIL.Image.fromarray(image_linear[:, :, i].astype("float32"), mode='F') channel_linear.thumbnail((work_size, work_size)) image_linear_thumb.append(np.array(channel_linear)) image_linear_thumb = np.transpose(np.array(image_linear_thumb), (1, 2, 0)) print("Encoder working at size: {} x {}".format( image_linear_thumb.shape[1], image_linear_thumb.shape[0])) # Figure out a good component count components_x = int( max( min_components, min( target_components, round(image_linear_thumb.shape[1] / (work_size / target_components))))) components_y = int( max( min_components, min( target_components, round(image_linear_thumb.shape[0] / (work_size / target_components))))) print("Using component counts: {} x {}".format(components_x, components_y)) # Create blurhash blur_hash = blurhash.encode(image_linear_thumb, components_x, components_y, linear=True) print("Blur hash of image: " + blur_hash) """ Part 2: Decode """ # Figure out what size to decode to decode_components_x, decode_components_y = blurhash.components(blur_hash) decode_size_x = decode_components_x * (work_size // target_components) decode_size_y = decode_components_y * (work_size // target_components) print("Decoder working at size {} x {}".format(decode_size_x, decode_size_y)) # Decode decoded_image = np.array( blurhash.decode(blur_hash, decode_size_x, decode_size_y, linear=True)) # Scale so that we have the right size to fill out_size without letter/pillarboxing # while matching original images aspect ratio. fill_x_size_y = out_size[0] * (image_size[0] / image_size[1]) fill_y_size_x = out_size[1] * (image_size[1] / image_size[0]) scale_target_size = list(out_size) if fill_x_size_y / out_size[1] < fill_y_size_x / out_size[0]: scale_target_size[0] = max(scale_target_size[0], int(fill_y_size_x)) else: scale_target_size[1] = max(scale_target_size[1], int(fill_x_size_y)) # Scale (ideally, your UI layer should take care of this in some kind of efficient way) print("Scaling to target size: {} x {}".format(scale_target_size[0], scale_target_size[1])) decoded_image_large = [] for i in range(3): channel_linear = PIL.Image.fromarray( decoded_image[:, :, i].astype("float32"), mode='F') decoded_image_large.append( np.array( channel_linear.resize(scale_target_size, PIL.Image.BILINEAR))) decoded_image_large = np.transpose(np.array(decoded_image_large), (1, 2, 0)) # Convert to srgb PIL image decoded_image_out = np.vectorize(blurhash.linear_to_srgb)( np.array(decoded_image_large)) decoded_image_out = PIL.Image.fromarray( np.array(decoded_image_out).astype('uint8')) # Crop to final size and write decoded_image_out = decoded_image_out.crop(( (decoded_image_out.width - out_size[0]) / 2, (decoded_image_out.height - out_size[1]) / 2, (decoded_image_out.width + out_size[0]) / 2, (decoded_image_out.height + out_size[1]) / 2, )) decoded_image_out.save(output_image) print("Wrote final result to " + str(output_image))