Source code for frame_msg.tx_image_sprite_block

import struct
from typing import List
import numpy as np
from .tx_sprite import TxSprite

[docs] class TxImageSpriteBlock: """ An image split into horizontal sprite strips. Attributes: image: Source sprite to split sprite_line_height: Height of each sprite strip. If the TxSprite is compressed, the strip has a packed size limit of 4kB and this value is ignored. progressive_render: Whether to render lines as they arrive updatable: Whether lines can be updated after initial render """ image: TxSprite sprite_line_height: int progressive_render: bool updatable: bool def __init__(self, image: TxSprite, sprite_line_height: int = 16, progressive_render: bool = True, updatable: bool = True): self.image = image self.progressive_render = progressive_render self.updatable = updatable if image.compress: # 4k uncompressed (binary packed) limit packed_bytes_per_row = int((image.width + (8 / image.bpp) - 1) // (8 / image.bpp)) self.sprite_line_height = int(4096 // packed_bytes_per_row) else: self.sprite_line_height = sprite_line_height self.sprite_lines: List[TxSprite] = [] self._split_into_lines() def _split_into_lines(self): """Split the source image into horizontal strips.""" pixels = np.frombuffer(self.image.pixel_data, dtype=np.uint8) pixels = pixels.reshape((self.image.height, self.image.width)) # Process full-height lines for i in range(0, self.image.height // self.sprite_line_height): start_y = i * self.sprite_line_height line_pixels = pixels[start_y:start_y + self.sprite_line_height] self.sprite_lines.append(TxSprite( width=self.image.width, height=self.sprite_line_height, num_colors=self.image.num_colors, palette_data=self.image.palette_data, pixel_data=line_pixels.tobytes(), compress=self.image.compress )) # Process final partial line if any remaining_height = self.image.height % self.sprite_line_height if remaining_height > 0: final_line = pixels[-remaining_height:] self.sprite_lines.append(TxSprite( width=self.image.width, height=remaining_height, num_colors=self.image.num_colors, palette_data=self.image.palette_data, pixel_data=final_line.tobytes(), compress=self.image.compress ))
[docs] def pack(self) -> bytes: """Pack the image block header.""" if not self.sprite_lines: raise Exception("No sprite lines to pack") return struct.pack('>BHHHBB', 0xFF, # Block marker self.image.width, self.image.height, self.sprite_line_height, 1 if self.progressive_render else 0, 1 if self.updatable else 0 )