async def render_image_from_file(self, icon: str, label: str): """ Render the image from file into an image with optional label. this funckwargstion code is based on the render helper function from the python-elgato-streamdeck example code. Missing icons are not rendered. """ image = PILHelper.create_image(self.controller.deck) if icon: icon_path = self.asset_path / "icons" / icon if icon_path.is_file(): LOGGER.info(f"Rendering icon {icon}") icon_image = Image.open(str(icon_path)).convert("RGBA") icon_image.thumbnail((image.width, image.height - 20), Image.LANCZOS) icon_pos = ((image.width - icon_image.width) // 2, 0) image.paste(icon_image, icon_pos, icon_image) else: LOGGER.warning(f"Icon {icon} cannot be found") if label: LOGGER.debug("Getting font and rendering label") draw = ImageDraw.Draw(image) font = await self.get_font(self.label_font, 14) label_w, _ = draw.textsize(label, font=font) label_pos = ((image.width - label_w) // 2, image.height - 20) draw.text(label_pos, text=label, font=font, fill="white") return PILHelper.to_native_format(self.controller.deck, image)
def create_animation_frames(deck, image_filename): icon_frames = list() # Open the source image asset icon = Image.open(os.path.join(os.path.dirname(__file__), "Assets", image_filename)) # Create a blank key image in the host image format, which we can # duplicate quickly for each animation frame to save time blank_image = PILHelper.create_image(deck) try: # Extract out each animation frame, resizing and converting to the # native device image format while True: image = blank_image.copy() # Resize the animation frame and paste it into the new image buffer icon_frame = icon.convert("RGBA") icon_frame.thumbnail(image.size, Image.LANCZOS) icon_frame_pos = ((image.width - icon_frame.width) // 2, (image.height - icon_frame.height) // 2) image.paste(icon_frame, icon_frame_pos, icon_frame) # Store the rendered animation frame in the device's native image # format for later use, so we don't need to keep converting it icon_frames.append(PILHelper.to_native_format(deck, image)) # Move to next animation frame in the source image icon.seek(icon.tell() + 1) except EOFError: # End of file, all image frames have been extracted pass # Return an infinite cycle generator that returns the next animation frame # each time it is called return itertools.cycle(icon_frames)
def crop_key_image_from_deck_sized_image(deck, image, key_spacing, key): key_rows, key_cols = deck.key_layout() key_width, key_height = deck.key_image_format()['size'] spacing_x, spacing_y = key_spacing # Determine which row and column the requested key is located on. row = key // key_cols col = key % key_cols # Compute the starting X and Y offsets into the full size image that the # requested key should display. start_x = col * (key_width + spacing_x) start_y = row * (key_height + spacing_y) # Compute the region of the larger deck image that is occupied by the given # key, and crop out that segment of the full image. region = (start_x, start_y, start_x + key_width, start_y + key_height) segment = image.crop(region) # Create a new key-sized image, and paste in the cropped section of the # larger image. key_image = PILHelper.create_image(deck) key_image.paste(segment) return PILHelper.to_native_format(deck, key_image)
def create_animation_frames(deck, image_filename): icon_frames = list() # Open the source image asset. icon = Image.open(os.path.join(ASSETS_PATH, image_filename)) # Iterate through each animation frame of the source image for frame in ImageSequence.Iterator(icon): # We need source frames in RGBA format, convert now before we resize it. icon_frame = frame.convert("RGBA") # Create new key image of the correct dimensions, black background. image = PILHelper.create_image(deck) # Resize the animation frame to best-fit the dimensions of a single key, # and paste it onto our blank frame centered as closely as possible. icon_frame.thumbnail(image.size, Image.LANCZOS) icon_frame_pos = ((image.width - icon_frame.width) // 2, (image.height - icon_frame.height) // 2) image.paste(icon_frame, icon_frame_pos, icon_frame) # Store the rendered animation frame in the device's native image # format for later use, so we don't need to keep converting it. icon_frames.append(PILHelper.to_native_format(deck, image)) # Return an infinite cycle generator that returns the next animation frame # each time it is called. return itertools.cycle(icon_frames)
def _render_key_image(deck, icon: str = "", text: str = "", font: str = DEFAULT_FONT, **kwargs): """Renders an individual key image""" image = PILHelper.create_image(deck) draw = ImageDraw.Draw(image) if icon: rgba_icon = Image.open(icon).convert("RGBA") else: rgba_icon = Image.new("RGBA", (300, 300)) icon_width, icon_height = image.width, image.height if text: icon_height -= 20 rgba_icon.thumbnail((icon_width, icon_height), Image.LANCZOS) icon_pos = ((image.width - rgba_icon.width) // 2, 0) image.paste(rgba_icon, icon_pos, rgba_icon) if text: true_font = ImageFont.truetype(os.path.join(FONTS_PATH, font), 14) label_w, label_h = draw.textsize(text, font=true_font) if icon: label_pos = ((image.width - label_w) // 2, image.height - 20) else: label_pos = ((image.width - label_w) // 2, (image.height // 2) - 7) draw.text(label_pos, text=text, font=true_font, fill="white") return PILHelper.to_native_format(deck, image)
def render_key_image(deck, icon_filename): image = PILHelper.create_image(deck) icon = Image.open(ASSETS_PATH + "/" + icon_filename).convert("RGBA") icon.thumbnail((image.width, image.height - 20), Image.LANCZOS) icon_pos = ((image.width - icon.width) // 2, 0) image.paste(icon, icon_pos, icon) return image
def render_key_image(deck, icon_filename): # Create new key image of the correct dimensions, black background image = PILHelper.create_image(deck) draw = ImageDraw.Draw(image) # Add image overlay, rescaling the image asset if it is too large to fit # the requested dimensions via a high quality Lanczos scaling algorithm icon = Image.open(icon_filename).convert("RGBA") icon.thumbnail((image.width, image.height), Image.LANCZOS) image.paste(icon) return PILHelper.to_native_format(deck, image)
def ActualizarImagen(deck, teclas, tecla, limpiar=False): global folder image = PILHelper.create_image(deck) if not limpiar: nombre = "{}".format(teclas[tecla]['Nombre']) if 'Regresar' in teclas[tecla]: if 'ico' in teclas[tecla]: NombreIcon = "{}".format(teclas[tecla]['ico']) elif 'ico_Regresar' in data: NombreIcon = data['ico_Regresar'] else: NombreIcon = "imagen.png" elif 'Estado' in teclas[tecla]: # print("Hay estado {}".format(teclas[tecla]['Estado'])) if teclas[tecla]['Estado'] and 'icon_true' in teclas[tecla]: NombreIcon = teclas[tecla]['icon_true'] elif not teclas[tecla]['Estado'] and 'icon_false' in teclas[tecla]: NombreIcon = teclas[tecla]['icon_false'] elif 'ico_defecto' in data: NombreIcon = data['ico_defecto'] else: NombreIcon = "imagen.png" elif 'ico' in teclas[tecla]: NombreIcon = "{}".format(teclas[tecla]['ico']) else: if 'ico_defecto' in data: NombreIcon = data['ico_defecto'] else: NombreIcon = "imagen.png" icon = Image.open(NombreIcon).convert("RGBA") icon.thumbnail((image.width, image.height - 20), Image.LANCZOS) icon_posicion = ((image.width - icon.width) // 2, 0) image.paste(icon, icon_posicion, icon) titulo = '' if 'Titulo' in teclas[tecla]: titulo = "{}".format(teclas[tecla]['Titulo']) if not titulo == '': dibujo = ImageDraw.Draw(image) font = ImageFont.truetype(fuente, 14) label_w, label_h = dibujo.textsize(titulo, font=font) label_pos = ((image.width - label_w) // 2, image.height - 20) dibujo.text(label_pos, text=titulo, font=font, fill="white") deck.set_key_image(tecla, PILHelper.to_native_format(deck, image))
def test_key_pattern(deck): test_key_image = PILHelper.create_image(deck) draw = ImageDraw.Draw(test_key_image) draw.rectangle((0, 0) + test_key_image.size, fill=(0x11, 0x22, 0x33), outline=(0x44, 0x55, 0x66)) test_key_image = PILHelper.to_native_format(deck, test_key_image) with deck: deck.open() deck.set_key_image(0, test_key_image) deck.close()
def render_key_image(deck, btn): # Create new key image of the correct dimensions, black background image = PILHelper.create_image(deck) draw = ImageDraw.Draw(image) if btn.selected: draw.rectangle((0, 0, image.width - 1, image.height - 1), fill=btn.selected_color) label_w, label_h = draw.textsize(btn.label) label_pos = ((image.width - label_w) // 2, (image.height - label_h) // 2) draw.text(label_pos, text=btn.label, fill="white") return PILHelper.to_native_format(deck, image)
def getAsset(deck, assetFilename): """ Load an image asset from the given filename. Returned in the native format of `deck` """ image = PILHelper.create_image(deck) # Resize the source image asset to best-fit the dimensions of a single key, # and paste it onto our blank frame centered as closely as possible. icon = Image.open(os.path.join(ASSETS_PATH, assetFilename)).convert("RGBA") icon.thumbnail((image.width, image.height - 20), Image.LANCZOS) icon_pos = ((image.width - icon.width) // 2, 0) image.paste(icon, icon_pos, icon) return PILHelper.to_native_format(deck, image)
def run(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('127.0.0.1', 5555)) s.listen(1) conn, addr = s.accept() with conn: while True: image = PILHelper.create_image(deck) frame = conn.recv(11664) if not frame: break video = Image.frombytes('RGB', (72, 54), frame, 'raw') image.paste(video, (0, 0)) deck.set_key_image(14, PILHelper.to_native_format(deck, image))
async def render_clock_number(self, number: int) -> Image.Image: LOGGER.info(f"Rendering number {number}") image = PILHelper.create_image(self.controller.deck) text = f"{number:02d}" font = await self.get_font(self.label_font, 50) draw = ImageDraw.Draw(image) w, _h = draw.textsize(text, font=font) h_pos = image.height // 8 pos = ((image.width - w) // 2, h_pos) draw.text(pos, text=text, font=font, fill="white") return PILHelper.to_native_format(self.controller.deck, image)
def getCharacterAsset(deck, character, background='black', color='white'): if character in characterAssets: return characterAssets[character] image = PILHelper.create_image(deck, background=background) # Load a custom TrueType font and use it to overlay the key index, draw key # label onto the image. draw = ImageDraw.Draw(image) font = ImageFont.truetype(os.path.join(ASSETS_PATH, FONT_NAME), 96) label_w, label_h = draw.textsize(character, font=font) label_pos = (0, 0) #((image.width - label_w) // 2, image.height - 20) draw.text(label_pos, text=character, font=font, fill=color) nativeImage = PILHelper.to_native_format(deck, image) characterAssets[character] = nativeImage return nativeImage
def _render_key_image(deck, icon: str = "", text: str = "", font: str = DEFAULT_FONT, **kwargs): """Renders an individual key image and returns it as a PIL image""" image = PILHelper.create_image(deck) draw = ImageDraw.Draw(image) if icon: try: kind = filetype.guess(icon) if kind is None: svg_code = open(icon).read() png = cairosvg.svg2png(svg_code, output_height=72, output_width=72) image_file = BytesIO(png) rgba_icon = Image.open(image_file) else: rgba_icon = Image.open(icon).convert("RGBA") except (OSError, IOError) as icon_error: print(f"Unable to load icon {icon} with error {icon_error}") rgba_icon = Image.new("RGBA", (300, 300)) else: rgba_icon = Image.new("RGBA", (300, 300)) icon_width, icon_height = image.width, image.height if text: icon_height -= 20 rgba_icon.thumbnail((icon_width, icon_height), Image.LANCZOS) icon_pos = ((image.width - rgba_icon.width) // 2, 0) image.paste(rgba_icon, icon_pos, rgba_icon) if text: true_font = ImageFont.truetype(os.path.join(FONTS_PATH, font), 14) label_w, label_h = draw.textsize(text, font=true_font) if icon: label_pos = ((image.width - label_w) // 2, image.height - 20) else: label_pos = ((image.width - label_w) // 2, (image.height // 2) - 7) draw.text(label_pos, text=text, font=true_font, fill="white") return image
def getInitializedDeck(initBrightness=30, deviceNum=0, background='black'): """ Initialize and return the first stream deck device or None. """ streamdecks = DeviceManager().enumerate() if streamdecks and len(streamdecks) >= deviceNum + 1: deck = streamdecks[deviceNum] deck.open() deck.reset() deck.set_brightness(initBrightness) # Blank background of provided color keyImage = PILHelper.to_native_format( deck, PILHelper.create_image(deck, background)) for keyNum in range(deck.key_count()): deck.set_key_image(keyNum, keyImage) return deck print("Unable to open any stream deck devices.") return None
def __getitem__(self, key): if self._pixels is None: image = PILHelper.create_image(self._deck, background=self._color) l_x, l_y, l_w, l_h = self._draw_label(image) v_x, v_y, v_w, v_h = self._draw_value(image) o_x = 0 o_y = (l_y or 0) + (l_h or 0) o_w = image.width o_h = (v_y or image.height) - o_y overlay_pos = (int(o_x), int(o_y)) overlay_size = (int(o_w), int(o_h)) self._draw_overlay(image, overlay_pos, overlay_size) self._pixels = PILHelper.to_native_format(self._deck, image) return self._pixels[key]
def render_key_image(deck, icon_filename, font_filename, label_text, fill): # Create new key image of the correct dimensions, black background. image = PILHelper.create_image(deck) # Resize the source image asset to best-fit the dimensions of a single key, # and paste it onto our blank frame centered as closely as possible. icon = Image.open(icon_filename).convert("RGBA") icon.thumbnail((image.width, image.height), Image.LANCZOS) icon_pos = ((image.width - icon.width) // 2, (image.height - icon.height) // 2) image.paste(icon, icon_pos, icon) # Load a custom TrueType font and use it to overlay the key index, draw key # label onto the image. draw = ImageDraw.Draw(image) font = ImageFont.truetype(font_filename, 14) label_w, label_h = draw.textsize(label_text, font=font) label_pos = ((image.width - label_w) // 2, image.height - 20) draw.text(label_pos, text=label_text, font=font, fill=fill) return PILHelper.to_native_format(deck, image)
def crop_key_image_from_deck_sized_image(deck, image, key): key_width, key_height = deck.key_image_format()['size'] key_rows, key_cols = deck.key_layout() # Determine which row and column the requested key is located on. row = key // key_cols col = key % key_cols # Compute the region of the larger deck image that is occupied by the given # key. region = (col * key_width, row * key_height, (col + 1) * key_width, (row + 1) * key_height) segment = image.crop(region) # Create a new key-sized image, and paste in the cropped section of the # larger image. key_image = PILHelper.create_image(deck) key_image.paste(segment) return PILHelper.to_native_format(deck, key_image)
def render_key_image(deck, icon_filename, font_filename, label_text): # Create new key image of the correct dimensions, black background image = PILHelper.create_image(deck) draw = ImageDraw.Draw(image) # Add image overlay, rescaling the image asset if it is too large to fit # the requested dimensions via a high quality Lanczos scaling algorithm icon = Image.open(icon_filename).convert("RGBA") icon.thumbnail((image.width, image.height - 20), Image.LANCZOS) icon_pos = ((image.width - icon.width) // 2, 0) image.paste(icon, icon_pos, icon) # Load a custom TrueType font and use it to overlay the key index, draw key # label onto the image font = ImageFont.truetype(font_filename, 14) label_w, label_h = draw.textsize(label_text, font=font) label_pos = ((image.width - label_w) // 2, image.height - 20) draw.text(label_pos, text=label_text, font=font, fill="white") return PILHelper.to_native_format(deck, image)
def render_key(config, deck, icon_filename, font_filename, label): image = PILHelper.create_image(deck) has_label = label is not None and label != "" # Render the image in case it exists. if os.path.exists(icon_filename): icon = Image.open(icon_filename).convert("RGBA") image_height = image.height - 20 if has_label else image.height - 5 image_width = image.width if has_label else image.width - 2 icon.thumbnail((image_width, image_height), Image.LANCZOS) icon_pos = ((image.width - icon.width) // 2, 0) image.paste(icon, icon_pos, icon) # Render the label. if has_label: draw = ImageDraw.Draw(image) font = ImageFont.truetype(font_filename, config.font_size) label_w, label_h = draw.textsize(label, font=font) label_pos = ((image.width - label_w) // 2, image.height - 20) draw.text(label_pos, text=label, font=font, fill="white") return PILHelper.to_native_format(deck, image)
def ActualizarIcono(Deck, indice, accion): global FuenteIcono global ImagenBase global ListaImagenes ColorFondo = "black" imagenFondo = None if "imagen_opciones" in accion: opciones = accion["imagen_opciones"] if "fondo" in opciones: ColorFondo = opciones["fondo"] if "imagen" in opciones: imagenFondo = opciones["imagen"] ImagenBoton = PILHelper.create_image(Deck, background=ColorFondo) if imagenFondo is not None: PonerImagen(ImagenBoton, imagenFondo, accion, Deck.Folder, True) DirecionImagen = BuscarDirecionImagen(accion) if DirecionImagen is not None: if DirecionImagen.endswith(".gif"): # TODO: Meter proceso gif adentro return None PonerImagen(ImagenBoton, DirecionImagen, accion, Deck.Folder) if "cargar_titulo" in accion: TextoCargar = accion["cargar_titulo"] if "archivo" in TextoCargar and "atributo" in TextoCargar: accion["titulo"] = ObtenerValor(TextoCargar["archivo"], TextoCargar["atributo"]) if "titulo" in accion: PonerTexto(ImagenBoton, accion, DirecionImagen) Deck.set_key_image(indice, PILHelper.to_native_format(Deck, ImagenBoton))
def render_key_image(deck, icon_filename, title, value): # Create new key image of the correct dimensions, black background image = PILHelper.create_image(deck) draw = ImageDraw.Draw(image) # Add image overlay, rescaling the image asset if it is too large to fit # the requested dimensions via a high quality Lanczos scaling algorithm if icon_filename: icon = Image.open(icon_filename).convert("RGBA") icon.thumbnail((image.width, image.height), Image.LANCZOS) image.paste(icon) if value: font = ImageFont.truetype('arial', 22) draw.text((image.width - 5, image.height / 2), text=str(int(value)), font=font, anchor="rs", fill="white") if title: font = ImageFont.truetype('arial', 12) draw.text((image.width / 2, image.height - 5), text=title, font=font, anchor="ms", fill="white") return PILHelper.to_native_format(deck, image)
def test_basic_apis(deck): with deck: deck.open() connected = deck.connected() # noqa: F841 deck_id = deck.id() # noqa: F841 key_count = deck.key_count() # noqa: F841 deck_type = deck.deck_type() # noqa: F841 key_layout = deck.key_layout() # noqa: F841 image_format = deck.key_image_format() # noqa: F841 key_states = deck.key_states() # noqa: F841 deck.set_key_callback(None) deck.reset() deck.set_brightness(30) test_key_image = PILHelper.create_image(deck) test_key_image = PILHelper.to_native_format(deck, test_key_image) deck.set_key_image(0, None) deck.set_key_image(0, test_key_image) deck.close()
if __name__ == "__main__": logging.basicConfig(level=logging.INFO) manager = DeviceManager(transport="dummy") streamdecks = manager.enumerate() print("Got {} Dummy Stream Deck(s).\n".format(len(streamdecks)), flush=True) for index, deck in enumerate(streamdecks): deck.open() connected = deck.connected() deck_id = deck.id() key_count = deck.key_count() deck_type = deck.deck_type() key_layout = deck.key_layout() image_format = deck.key_image_format() key_states = deck.key_states() test_key_image = PILHelper.create_image(deck) test_key_image = PILHelper.to_native_format(deck, test_key_image) deck.set_key_callback(None) deck.reset() deck.set_brightness(30) deck.set_key_image(0, test_key_image) deck.close()
def test_pil_helpers(deck): test_scaled_image = PILHelper.create_scaled_image( deck, Image.new("RGB", (1, 1))) # noqa: F841 test_key_image = PILHelper.create_image(deck) test_key_image = PILHelper.to_native_format(deck, test_key_image)
def LimpiarIcono(Deck, indice): ImagenBoton = PILHelper.create_image(Deck) Deck.set_key_image(indice, PILHelper.to_native_format(Deck, ImagenBoton))
def _render_key_image( deck, selectedFont: str = "Open_Sans", textAlign: str = "Cetner", fontSize: int = 14, fontColor: str = "white", icon: str = "", text: str = "", font: str = DEFAULT_FONT, **kwargs, ): """Renders an individual key image""" image = PILHelper.create_image(deck) draw = ImageDraw.Draw(image) if icon: try: rgba_icon = Image.open(icon).convert("RGBA") except (OSError, IOError) as icon_error: print(f"Unable to load icon {icon} with error {icon_error}") rgba_icon = Image.new("RGBA", (300, 300)) else: rgba_icon = Image.new("RGBA", (300, 300)) icon_width, icon_height = image.width, image.height if text: icon_height -= 20 rgba_icon.thumbnail((icon_width, icon_height), Image.LANCZOS) icon_pos = ((image.width - rgba_icon.width) // 2, 0) image.paste(rgba_icon, icon_pos, rgba_icon) if text: text = text.replace("\\n", "\n") if selectedFont == "Goblin_One": true_font = ImageFont.truetype( os.path.join(FONTS_PATH, os.path.join("Goblin_One", "GoblinOne-Regular.ttf")), fontSize, ) elif selectedFont == "Open_Sans": true_font = ImageFont.truetype( os.path.join(FONTS_PATH, os.path.join("Open_Sans", "OpenSans-Regular.ttf")), fontSize, ) elif selectedFont == "Roboto": true_font = ImageFont.truetype( os.path.join(FONTS_PATH, os.path.join("roboto", "Roboto-Regular.ttf")), fontSize ) elif selectedFont == "Lobster": true_font = ImageFont.truetype( os.path.join(FONTS_PATH, os.path.join("Lobster", "Lobster-Regular.ttf")), fontSize ) elif selectedFont == "Anton": true_font = ImageFont.truetype( os.path.join(FONTS_PATH, os.path.join("Anton", "Anton-Regular.ttf")), fontSize ) elif selectedFont == "Pacifico": true_font = ImageFont.truetype( os.path.join(FONTS_PATH, os.path.join("Pacifico", "Pacifico-Regular.ttf")), fontSize ) label_w, label_h = draw.textsize(text, font=true_font) if icon: label_pos = ((image.width - label_w) // 2, image.height - 20) else: label_pos = ((image.width - label_w) // 2, (image.height // 2) - 7) draw.text(label_pos, align=textAlign, text=text, font=true_font, fill=fontColor) return PILHelper.to_native_format(deck, image)