Converts a numpy array of uint8 into a base64 png or jpg string. Parameters ---------- img: ndarray of uint8 array image backend: str 'auto', 'pil' or 'pypng'. If 'auto', Pillow is used if installed, otherwise pypng. compression: int, between 0 and 9
(img, backend="pil", compression=4, ext="png")
| 11 | |
| 12 | |
| 13 | def image_array_to_data_uri(img, backend="pil", compression=4, ext="png"): |
| 14 | """Converts a numpy array of uint8 into a base64 png or jpg string. |
| 15 | |
| 16 | Parameters |
| 17 | ---------- |
| 18 | img: ndarray of uint8 |
| 19 | array image |
| 20 | backend: str |
| 21 | 'auto', 'pil' or 'pypng'. If 'auto', Pillow is used if installed, |
| 22 | otherwise pypng. |
| 23 | compression: int, between 0 and 9 |
| 24 | compression level to be passed to the backend |
| 25 | ext: str, 'png' or 'jpg' |
| 26 | compression format used to generate b64 string |
| 27 | """ |
| 28 | # PIL and pypng error messages are quite obscure so we catch invalid compression values |
| 29 | if compression < 0 or compression > 9: |
| 30 | raise ValueError("compression level must be between 0 and 9.") |
| 31 | alpha = False |
| 32 | if img.ndim == 2: |
| 33 | mode = "L" |
| 34 | elif img.ndim == 3 and img.shape[-1] == 3: |
| 35 | mode = "RGB" |
| 36 | elif img.ndim == 3 and img.shape[-1] == 4: |
| 37 | mode = "RGBA" |
| 38 | alpha = True |
| 39 | else: |
| 40 | raise ValueError("Invalid image shape") |
| 41 | if backend == "auto": |
| 42 | backend = "pil" if pil_imported else "pypng" |
| 43 | if ext != "png" and backend != "pil": |
| 44 | raise ValueError("jpg binary strings are only available with PIL backend") |
| 45 | |
| 46 | if backend == "pypng": |
| 47 | ndim = img.ndim |
| 48 | sh = img.shape |
| 49 | if ndim == 3: |
| 50 | img = img.reshape((sh[0], sh[1] * sh[2])) |
| 51 | w = Writer( |
| 52 | sh[1], sh[0], greyscale=(ndim == 2), alpha=alpha, compression=compression |
| 53 | ) |
| 54 | img_png = from_array(img, mode=mode) |
| 55 | prefix = "data:image/png;base64," |
| 56 | with BytesIO() as stream: |
| 57 | w.write(stream, img_png.rows) |
| 58 | base64_string = prefix + base64.b64encode(stream.getvalue()).decode("utf-8") |
| 59 | else: # pil |
| 60 | if not pil_imported: |
| 61 | raise ImportError( |
| 62 | "pillow needs to be installed to use `backend='pil'. Please" |
| 63 | "install pillow or use `backend='pypng'." |
| 64 | ) |
| 65 | pil_img = Image.fromarray(img) |
| 66 | if ext == "jpg" or ext == "jpeg": |
| 67 | prefix = "data:image/jpeg;base64," |
| 68 | ext = "jpeg" |
| 69 | else: |
| 70 | prefix = "data:image/png;base64," |