def _create_background_box(self, lines: int, y_offset: int) -> TileGrid: """Private Class function to create a background_box :param lines: int number of lines :param y_offset: int y pixel bottom coordinate for the background_box""" left = self._bounding_box[0] if self._background_tight: # draw a tight bounding box box_width = self._bounding_box[2] box_height = self._bounding_box[3] x_box_offset = 0 y_box_offset = self._bounding_box[1] else: # draw a "loose" bounding box to include any ascenders/descenders. ascent, descent = self._ascent, self._descent if self._label_direction in ("UPR", "DWR", "TTB"): box_height = (self._bounding_box[3] + self._padding_top + self._padding_bottom) x_box_offset = -self._padding_bottom box_width = ((ascent + descent) + int( (lines - 1) * self._width * self._line_spacing) + self._padding_left + self._padding_right) else: box_width = (self._bounding_box[2] + self._padding_left + self._padding_right) x_box_offset = -self._padding_left box_height = ((ascent + descent) + int( (lines - 1) * self._height * self._line_spacing) + self._padding_top + self._padding_bottom) if self._base_alignment: y_box_offset = -ascent - self._padding_top else: y_box_offset = -ascent + y_offset - self._padding_top box_width = max(0, box_width) # remove any negative values box_height = max(0, box_height) # remove any negative values if self._label_direction == "UPR": movx = left + x_box_offset movy = -box_height - x_box_offset elif self._label_direction == "DWR": movx = left + x_box_offset movy = x_box_offset elif self._label_direction == "TTB": movx = left + x_box_offset movy = x_box_offset else: movx = left + x_box_offset movy = y_box_offset background_bitmap = Bitmap(box_width, box_height, 1) tile_grid = TileGrid( background_bitmap, pixel_shader=self._background_palette, x=movx, y=movy, ) return tile_grid
def register_click(self, click_pt): click_cmp = self.pix_to_cmp(click_pt) rng_r = (self.cmp_bounds[0][1] - self.cmp_bounds[0][0]) / 2 rng_c = (self.cmp_bounds[1][1] - self.cmp_bounds[1][0]) / 2 max_x = (self.pix_sz[0] - 1) // 2 max_y = (self.pix_sz[1] - 1) // 2 new_start_cmp = Complex(click_cmp.r - rng_r / 2, click_cmp.c - rng_c / 2) new_start_pix = self.cmp_to_pix(new_start_cmp) new_start_pix = (max(0, min(int(new_start_pix[0]), max_x)), max(0, min(int(new_start_pix[1]), max_y))) new_start_cmp = self.pix_to_cmp(new_start_pix) self.cmp_bounds = ((new_start_cmp.r, new_start_cmp.r + rng_r), (new_start_cmp.c, new_start_cmp.c + rng_c)) self.current_col = 0 new_bitmap = Bitmap(self.pix_sz[0], self.pix_sz[1], self.color_mapper.num_colors) for x in range(self.pix_sz[0]): for y in range(self.pix_sz[1]): new_bitmap[x, y] = self.bitmap[x // 2 + new_start_pix[0], y // 2 + new_start_pix[1]] self.bitmap = new_bitmap self.first_render = False
def _generate_bitmap(self, start_range, end_range): char_width, char_height = self.get_bounding_box() self._bitmap = Bitmap(char_width * (end_range - start_range + 1), char_height, 2) for character in range(start_range, end_range + 1): ascii_char = chr(character) ascii_mask = self._font.getmask(ascii_char, mode="1") for y in range(char_height): for x in range(char_width): color = ascii_mask.getpixel((x, y)) character_position = character - start_range self._bitmap[character_position * char_width + x, y] = (1 if color else 0)
def init_class(cls, display=None, max_scale=1.5, max_icon_size=(80, 80), max_color_depth=256): """ Initializes the IconAnimated Class variables, including preallocating memory buffers for the icon zoom bitmap and icon zoom palette. .. Note:: The `init_class` class function must be called before instancing any IconAnimated widgets. Usage example: ``IconAnimated.init_class(display=board.DISPLAY, max_scale=1.5, max_icon_size=(80,80), max_color_depth=256)`` :param displayio.Display display: The display where the icons will be displayed. :param float max_scale: The maximum zoom of the any of the icons, should be >= 1.0, (default: 1.5) :param max_icon_size: The maximum (x,y) pixel dimensions of any `IconAnimated` bitmap size that will be created (default: (80,80)). Note: This is the original pixel size, before scaling :type max_icon_size: Tuple[int,int] :param int max_color_depth: The maximum color depth of any `IconAnimated` bitmap that will be created (default: 256) """ if display is None: raise ValueError( "IconAninmated.init_class: Must provide display parameter for IconAnimated." ) if (isinstance(max_icon_size, tuple) and len(max_icon_size) == 2 # validate max_icon_size input and isinstance(max_icon_size[0], int) and isinstance(max_icon_size[1], int)): pass else: raise ValueError( "IconAninmated.init_class: max_icon_size must be an (x,y) " "tuple of integer pixel sizes.") cls.display = display if max_scale < 1.0: print("Warning: IconAnimated.init_class - max_scale value was " "constrained to minimum of 1.0") cls.max_scale = max(1.0, max_scale) cls.bitmap_buffer = Bitmap( round(cls.max_scale * max_icon_size[0]), round(cls.max_scale * max_icon_size[1]), max_color_depth + 1, ) cls.palette_buffer = Palette(max_color_depth + 1)
def __init__(self, color_mapper, max_iter, fractal=mandelbrot_fractal, pix_sz=(320, 240), cmp_bounds=None): self.color_mapper = color_mapper self.fractal_fn = fractal.fractal_fn if pix_sz[0] % 2 == 0: pix_sz = (pix_sz[0] - 1, pix_sz[1]) if pix_sz[1] % 2 == 0: pix_sz = (pix_sz[0], pix_sz[1] - 1) self.pix_sz = pix_sz self.first_render = True raw_cmp_bounds = cmp_bounds if cmp_bounds is not None else fractal.starting_cmp_bounds self.cmp_bounds = match_cmp_bounds_with_aspect_ratio( raw_cmp_bounds, self.pix_sz) self.max_iter = max_iter self.current_col = 0 self.bitmap = Bitmap(self.pix_sz[0], self.pix_sz[1], color_mapper.num_colors)
storage.mount(vfs, "/sd") WHITE = 0xFFFFFF BLACK = 0x000000 RED = 0xFF0000 ORANGE = 0xFFA500 YELLOW = 0xFFFF00 GREEN = 0x00FF00 BLUE = 0x0000FF PURPLE = 0x800080 PINK = 0xFFC0CB colors = (BLACK, RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE, WHITE) print("Building sample bitmap and palette") bitmap = Bitmap(16, 16, 9) palette = Palette(len(colors)) for i, c in enumerate(colors): palette[i] = c for x in range(16): for y in range(16): if x == 0 or y == 0 or x == 15 or y == 15: bitmap[x, y] = 1 elif x == y: bitmap[x, y] = 4 elif x == 15 - y: bitmap[x, y] = 5 else: bitmap[x, y] = 0
width = display.width height = display.height # cam.test_pattern = OV7670_TEST_PATTERN_COLOR_BAR bitmap = None # Select the biggest size for which we can allocate a bitmap successfully, and # which is not bigger than the display for size in range(OV7670_SIZE_DIV1, OV7670_SIZE_DIV16 + 1): cam.size = size if cam.width > width: continue if cam.height > height: continue try: bitmap = Bitmap(cam.width, cam.height, 65535) break except MemoryError: continue print(width, height, cam.width, cam.height) if bitmap is None: raise SystemExit("Could not allocate a bitmap") g = Group(scale=1, x=(width - cam.width) // 2, y=(height - cam.height) // 2) tg = TileGrid( bitmap, pixel_shader=ColorConverter(input_colorspace=Colorspace.RGB565_SWAPPED)) g.append(tg) display.show(g)
def _blit( self, bitmap: displayio.Bitmap, # target bitmap x: int, # target x upper left corner y: int, # target y upper left corner source_bitmap: displayio.Bitmap, # source bitmap x_1: int = 0, # source x start y_1: int = 0, # source y start x_2: int = None, # source x end y_2: int = None, # source y end skip_index: int = None, # palette index that will not be copied # (for example: the background color of a glyph) ) -> None: # pylint: disable=no-self-use, too-many-arguments if hasattr(bitmap, "blit"): # if bitmap has a built-in blit function, call it # this function should perform its own input checks bitmap.blit( x, y, source_bitmap, x1=x_1, y1=y_1, x2=x_2, y2=y_2, skip_index=skip_index, ) else: # perform pixel by pixel copy of the bitmap # Perform input checks if x_2 is None: x_2 = source_bitmap.width if y_2 is None: y_2 = source_bitmap.height # Rearrange so that x_1 < x_2 and y1 < y2 if x_1 > x_2: x_1, x_2 = x_2, x_1 if y_1 > y_2: y_1, y_2 = y_2, y_1 # Ensure that x2 and y2 are within source bitmap size x_2 = min(x_2, source_bitmap.width) y_2 = min(y_2, source_bitmap.height) for y_count in range(y_2 - y_1): for x_count in range(x_2 - x_1): x_placement = x + x_count y_placement = y + y_count if (bitmap.width > x_placement >= 0) and ( bitmap.height > y_placement >= 0): # ensure placement is within target bitmap # get the palette index from the source bitmap this_pixel_color = source_bitmap[y_1 + ( y_count * source_bitmap.width ) # Direct index into a bitmap array is speedier than [x,y] tuple + x_1 + x_count] if (skip_index is None) or (this_pixel_color != skip_index): bitmap[ # Direct index into a bitmap array is speedier than [x,y] tuple y_placement * bitmap.width + x_placement] = this_pixel_color elif y_placement > bitmap.height: break