76 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from io import BytesIO
 | |
| import base64
 | |
| from .png import Writer, from_array
 | |
| 
 | |
| try:
 | |
|     from PIL import Image
 | |
| 
 | |
|     pil_imported = True
 | |
| except ImportError:
 | |
|     pil_imported = False
 | |
| 
 | |
| 
 | |
| def image_array_to_data_uri(img, backend="pil", compression=4, ext="png"):
 | |
|     """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
 | |
|         compression level to be passed to the backend
 | |
|     ext: str, 'png' or 'jpg'
 | |
|         compression format used to generate b64 string
 | |
|     """
 | |
|     # PIL and pypng error messages are quite obscure so we catch invalid compression values
 | |
|     if compression < 0 or compression > 9:
 | |
|         raise ValueError("compression level must be between 0 and 9.")
 | |
|     alpha = False
 | |
|     if img.ndim == 2:
 | |
|         mode = "L"
 | |
|     elif img.ndim == 3 and img.shape[-1] == 3:
 | |
|         mode = "RGB"
 | |
|     elif img.ndim == 3 and img.shape[-1] == 4:
 | |
|         mode = "RGBA"
 | |
|         alpha = True
 | |
|     else:
 | |
|         raise ValueError("Invalid image shape")
 | |
|     if backend == "auto":
 | |
|         backend = "pil" if pil_imported else "pypng"
 | |
|     if ext != "png" and backend != "pil":
 | |
|         raise ValueError("jpg binary strings are only available with PIL backend")
 | |
| 
 | |
|     if backend == "pypng":
 | |
|         ndim = img.ndim
 | |
|         sh = img.shape
 | |
|         if ndim == 3:
 | |
|             img = img.reshape((sh[0], sh[1] * sh[2]))
 | |
|         w = Writer(
 | |
|             sh[1], sh[0], greyscale=(ndim == 2), alpha=alpha, compression=compression
 | |
|         )
 | |
|         img_png = from_array(img, mode=mode)
 | |
|         prefix = "data:image/png;base64,"
 | |
|         with BytesIO() as stream:
 | |
|             w.write(stream, img_png.rows)
 | |
|             base64_string = prefix + base64.b64encode(stream.getvalue()).decode("utf-8")
 | |
|     else:  # pil
 | |
|         if not pil_imported:
 | |
|             raise ImportError(
 | |
|                 "pillow needs to be installed to use `backend='pil'. Please"
 | |
|                 "install pillow or use `backend='pypng'."
 | |
|             )
 | |
|         pil_img = Image.fromarray(img)
 | |
|         if ext == "jpg" or ext == "jpeg":
 | |
|             prefix = "data:image/jpeg;base64,"
 | |
|             ext = "jpeg"
 | |
|         else:
 | |
|             prefix = "data:image/png;base64,"
 | |
|             ext = "png"
 | |
|         with BytesIO() as stream:
 | |
|             pil_img.save(stream, format=ext, compress_level=compression)
 | |
|             base64_string = prefix + base64.b64encode(stream.getvalue()).decode("utf-8")
 | |
|     return base64_string
 |