def _marshall_av_media(coordinates, proto, data, mimetype): """ Fill audio or video proto based on contents of data. Given a string, check if it's a url; if so, send it out without modification. Otherwise assume strings are filenames and let any OS errors raise. Load data either from file or through bytes-processing methods into a MediaFile object. Pack proto with generated Tornado-based URL. """ # Audio and Video methods have already checked if this is a URL by this point. if isinstance(data, str): # Assume it's a filename or blank. Allow OS-based file errors. with open(data, "rb") as fh: this_file = media_file_manager.add(fh.read(), mimetype, coordinates) proto.url = this_file.url return if data is None: # Allow empty values so media players can be shown without media. return # Assume bytes; try methods until we run out. if isinstance(data, bytes): pass elif isinstance(data, io.BytesIO): data.seek(0) data = data.getvalue() elif isinstance(data, io.RawIOBase) or isinstance(data, io.BufferedReader): data.seek(0) data = data.read() elif type_util.is_type(data, "numpy.ndarray"): data = data.tobytes() else: raise RuntimeError("Invalid binary data format: %s" % type(data)) this_file = media_file_manager.add(data, mimetype, coordinates) proto.url = this_file.url
def marshall_images( image, caption, width, proto_imgs, clamp, channels="RGB", format="JPEG" ): channels = channels.upper() # Turn single image and caption into one element list. if type(image) is list: images = image else: if type(image) == np.ndarray and len(image.shape) == 4: images = _4d_to_list_3d(image) else: images = [image] if type(caption) is list: captions = caption else: if isinstance(caption, str): captions = [caption] # You can pass in a 1-D Numpy array as captions. elif type(caption) == np.ndarray and len(caption.shape) == 1: captions = caption.tolist() # If there are no captions then make the captions list the same size # as the images list. elif caption is None: captions = [None] * len(images) else: captions = [str(caption)] assert type(captions) == list, "If image is a list then caption should be as well" assert len(captions) == len(images), "Cannot pair %d captions with %d images." % ( len(captions), len(images), ) proto_imgs.width = width for image, caption in zip(images, captions): proto_img = proto_imgs.imgs.add() if caption is not None: proto_img.caption = str(caption) # PIL Images if isinstance(image, ImageFile.ImageFile) or isinstance(image, Image.Image): data = _PIL_to_bytes(image, format) # BytesIO elif type(image) is io.BytesIO: data = _BytesIO_to_bytes(image) # Numpy Arrays (ie opencv) elif type(image) is np.ndarray: data = _verify_np_shape(image) data = _clip_image(data, clamp) if channels == "BGR": if len(data.shape) == 3: data = data[:, :, [2, 1, 0]] else: raise StreamlitAPIException( 'When using `channels="BGR"`, the input image should ' "have exactly 3 color channels" ) data = _np_array_to_bytes(data, format=format) # Strings elif isinstance(image, str): # If it's a url, then set the protobuf and continue try: p = urlparse(image) if p.scheme: proto_img.url = image continue except UnicodeDecodeError: pass # If not, see if it's a file. Allow OS filesystem errors to raise. with open(image, "rb") as f: data = f.read() # Assume input in bytes. else: data = image (data, mimetype) = _normalize_to_bytes(data, width, format) this_file = media_file_manager.add(data, mimetype=mimetype) proto_img.url = this_file.url
def image_to_url(image, width, clamp, channels, format, image_id, allow_emoji=False): # PIL Images if isinstance(image, ImageFile.ImageFile) or isinstance( image, Image.Image): data = _PIL_to_bytes(image, format) # BytesIO elif type(image) is io.BytesIO: data = _BytesIO_to_bytes(image) # Numpy Arrays (ie opencv) elif type(image) is np.ndarray: data = _verify_np_shape(image) data = _clip_image(data, clamp) if channels == "BGR": if len(data.shape) == 3: data = data[:, :, [2, 1, 0]] else: raise StreamlitAPIException( 'When using `channels="BGR"`, the input image should ' "have exactly 3 color channels") data = _np_array_to_bytes(data, format=format) # Strings elif isinstance(image, str): # If it's a url, then set the protobuf and continue try: p = urlparse(image) if p.scheme: return image except UnicodeDecodeError: pass # If not, see if it's a file. try: with open(image, "rb") as f: data = f.read() except: if allow_emoji: # This might be an emoji string, so just pass it to the frontend return image else: # Allow OS filesystem errors to raise raise # Assume input in bytes. else: data = image (data, mimetype) = _normalize_to_bytes(data, width, format) this_file = media_file_manager.add(data, mimetype, image_id) return this_file.url