예제 #1
0
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
예제 #2
0
    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
예제 #3
0
    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]
예제 #4
0
    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)
예제 #5
0
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