def unseep(seed_queue, filled, gc_filler, total_px, tiles_bbox, distances): """Seep inversion is basically a four-way 0-alpha fill with different conditions. It only backs off into the original fill and therefore does not require creation of new tiles or use of an input alpha tile. """ backup = {} while len(seed_queue) > 0: tile_coord, seeds, is_initial = seed_queue.pop(0) if tile_coord not in distances or tile_coord not in filled: continue if tile_coord not in backup: if filled[tile_coord] is _FULL_TILE: backup[tile_coord] = _FULL_TILE filled[tile_coord] = fc.new_full_tile(1 << 15) else: backup[tile_coord] = np.copy(filled[tile_coord]) result = gc_filler.unseep(distances[tile_coord], filled[tile_coord], seeds, is_initial) overflows = result[0:4] num_erased_pixels = result[4] total_px -= num_erased_pixels enqueue_overflows(seed_queue, tile_coord, overflows, tiles_bbox, (False, ) * 4) if total_px <= 0: # For small areas, when starting on a distance-marked pixel, # backing off may remove the entire fill, in which case we # roll back the tiles that were processed for tile_coord, tile in iteritems(backup): filled[tile_coord] = tile
def alpha_grid(self, tile_coord): """When needed, create and calculate alpha tiles for distance searching. For the tile of the given coordinate, ensure that a corresponding tile of alpha values (based on the tolerance function) exists in the full_alphas dict for both the tile and all of its neighbors :returns: Tuple with the grid and a boolean value indicating whether every tile in the grid is the constant full alpha tile """ all_full = True alpha_tiles = self._alpha_tiles grid = [] for ntc in fc.nine_grid(tile_coord): if ntc not in alpha_tiles: with self._src.tile_request(ntc[0], ntc[1], readonly=True) as src_tile: is_empty = src_tile is _EMPTY_RGBA alpha = self._filler.tile_uniformity(is_empty, src_tile) if alpha == _OPAQUE: alpha_tiles[ntc] = _FULL_TILE elif alpha == 0: alpha_tiles[ntc] = _EMPTY_TILE elif alpha: alpha_tiles[ntc] = fc.new_full_tile(alpha) else: alpha_tile = np.empty((N, N), 'uint16') self._filler.flood(src_tile, alpha_tile) alpha_tiles[ntc] = alpha_tile tile = alpha_tiles[ntc] grid.append(tile) all_full = all_full and tile is _FULL_TILE return grid, all_full
def uniform_tile(self, alpha): """ Return a reference to a uniform alpha tile If no uniform tile with the given alpha value exists, one is created """ if alpha not in self.uniform_tiles: self.uniform_tiles[alpha] = fc.new_full_tile(alpha) return self.uniform_tiles[alpha]
def find_gaps(self, *grid): """Search for and mark gaps, given a nine-grid of alpha tiles :param grid: nine-grid of alpha tiles :return: True if any gaps were found, otherwise false :rtype: bool """ if self._dist_data is None: self._dist_data = fc.new_full_tile(INF_DIST) return myplib.find_gaps(self._distbucket, self._dist_data, *grid)
import lib.modes import lib.morphology from lib.pycompat import iteritems logger = logging.getLogger(__name__) TILE_SIZE = N = myplib.TILE_SIZE INF_DIST = 2 * N * N # This should point to the array transparent_tile.rgba # defined in tiledsurface.py _EMPTY_RGBA = None # Distance data for tiles with no detected distances _GAPLESS_TILE = fc.new_full_tile(INF_DIST) _GAPLESS_TILE.flags.writeable = False EDGE = myplib.edges class GapClosingOptions: """Container of parameters for gap closing fill operations to avoid updates to the call chain in case the parameter set is altered. """ def __init__(self, max_gap_size, retract_seeps): self.max_gap_size = max_gap_size self.retract_seeps = retract_seeps