def __init__(self, obj, mipmap_level=0): """Construct from a color or from a NumPy array :param obj: RGB triple (uint8), or a HxWx4 or HxWx3 numpy array which can be either uint8 or uint16. :param mipmap_level: mipmap level, used internally. Root is zero. """ if not isinstance(obj, numpy.ndarray): r, g, b = obj obj = numpy.zeros((N, N, 3), dtype='uint8') obj[:, :, :] = r, g, b height, width = obj.shape[0:2] if height % N or width % N: raise BackgroundError('unsupported background tile size: %dx%d' % (width, height)) super(Background, self).__init__(mipmap_level=0, looped=True, looped_size=(width, height)) self.load_from_numpy(obj, 0, 0) # Generate mipmap if mipmap_level <= MAX_MIPMAP_LEVEL: mipmap_obj = numpy.zeros((height, width, 4), dtype='uint16') for ty in range(height/N*2): for tx in range(width/N*2): with self.tile_request(tx, ty, readonly=True) as src: mypaintlib.tile_downscale_rgba16(src, mipmap_obj, tx*N/2, ty*N/2) self.mipmap = Background(mipmap_obj, mipmap_level+1) self.mipmap.parent = self self.mipmap_level = mipmap_level
def __init__(self, obj, mipmap_level=0): if not isinstance(obj, numpy.ndarray): r, g, b = obj obj = numpy.zeros((N, N, 3), dtype='uint8') obj[:,:,:] = r, g, b height, width = obj.shape[0:2] if height % N or width % N: raise BackgroundError, 'unsupported background tile size: %dx%d' % (width, height) Surface.__init__(self, mipmap_level=0, looped=True, looped_size=(width, height)) self.load_from_numpy(obj, 0, 0) # Generate mipmap if mipmap_level <= MAX_MIPMAP_LEVEL: mipmap_obj = numpy.zeros((height, width, 4), dtype='uint16') for ty in range(height/N*2): for tx in range(width/N*2): with self.tile_request(tx, ty, readonly=True) as src: mypaintlib.tile_downscale_rgba16(src, mipmap_obj, tx*N/2, ty*N/2) self.mipmap = Background(mipmap_obj, mipmap_level+1) self.mipmap.parent = self self.mipmap_level = mipmap_level
def get_tile_memory(self, tx, ty, readonly): # OPTIMIZE: do some profiling to check if this function is a bottleneck # yes it is # Note: we must return memory that stays valid for writing until the # last end_atomic(), because of the caching in tiledsurface.hpp. t = self.tiledict.get((tx, ty)) if t is None: if readonly: t = transparent_tile else: t = Tile() self.tiledict[(tx, ty)] = t if t is mipmap_dirty_tile: # regenerate mipmap t = Tile() self.tiledict[(tx, ty)] = t empty = True for x in xrange(2): for y in xrange(2): src = self.parent.get_tile_memory(tx*2 + x, ty*2 + y, True) mypaintlib.tile_downscale_rgba16(src, t.rgba, x*N/2, y*N/2) if src is not transparent_tile.rgba: empty = False if empty: # rare case, no need to speed it up del self.tiledict[(tx, ty)] t = transparent_tile if t.readonly and not readonly: # shared memory, get a private copy for writing t = t.copy() self.tiledict[(tx, ty)] = t if not readonly: assert self.mipmap_level == 0 self._mark_mipmap_dirty(tx, ty) return t.rgba
def __init__(self, obj, mipmap_level=0): """Construct from a color or from a NumPy array :param obj: RGB triple (uint8), or a HxWx4 or HxWx3 numpy array which can be either uint8 or uint16. :param mipmap_level: mipmap level, used internally. Root is zero. """ if not isinstance(obj, numpy.ndarray): r, g, b = obj obj = numpy.zeros((N, N, 3), dtype='uint8') obj[:, :, :] = r, g, b height, width = obj.shape[0:2] if height % N or width % N: raise BackgroundError('unsupported background tile size: %dx%d' % (width, height)) super(Background, self).__init__(mipmap_level=0, looped=True, looped_size=(width, height)) self.load_from_numpy(obj, 0, 0) # Generate mipmap if mipmap_level <= MAX_MIPMAP_LEVEL: mipmap_obj = numpy.zeros((height, width, 4), dtype='uint16') for ty in range(height / N * 2): for tx in range(width / N * 2): with self.tile_request(tx, ty, readonly=True) as src: mypaintlib.tile_downscale_rgba16( src, mipmap_obj, tx * N / 2, ty * N / 2) self.mipmap = Background(mipmap_obj, mipmap_level + 1) self.mipmap.parent = self self.mipmap_level = mipmap_level
def __init__(self, obj, mipmap_level=0): if isinstance(obj, gdk.Pixbuf): obj = helpers.gdkpixbuf2numpy(obj) elif not isinstance(obj, numpy.ndarray): r, g, b = obj obj = numpy.zeros((N, N, 3), dtype='uint8') obj[:,:,:] = r, g, b self.tw = obj.shape[1]/N self.th = obj.shape[0]/N #print obj if obj.shape[0:2] != (self.th*N, self.tw*N): raise BackgroundError, 'unsupported background tile size: %dx%d' % (obj.shape[0], obj.shape[1]) if obj.dtype == 'uint8': obj = (obj.astype('uint32') * (1<<15) / 255).astype('uint16') self.tiles = {} for ty in range(self.th): for tx in range(self.tw): # make sure we have linear memory (optimization) tile = numpy.empty((N, N, 4), dtype='uint16') # rgbu tile[:,:,:3] = obj[N*ty:N*(ty+1), N*tx:N*(tx+1), :3] self.tiles[tx, ty] = tile # generate mipmap self.mipmap_level = mipmap_level if mipmap_level < MAX_MIPMAP_LEVEL: mipmap_obj = numpy.zeros((self.th*N, self.tw*N, 4), dtype='uint16') for ty in range(self.th*2): for tx in range(self.tw*2): src = self.get_tile_memory(tx, ty) mypaintlib.tile_downscale_rgba16(src, mipmap_obj, tx*N/2, ty*N/2) self.mipmap = Background(mipmap_obj, mipmap_level+1)
def _regenerate_mipmap(self, t, tx, ty): t = _Tile() self.tiledict[(tx, ty)] = t empty = True for x in xrange(2): for y in xrange(2): src = self.parent.tiledict.get((tx*2 + x, ty*2 + y), transparent_tile) if src is mipmap_dirty_tile: src = self.parent._regenerate_mipmap(src, tx*2 + x, ty*2 + y) mypaintlib.tile_downscale_rgba16(src.rgba, t.rgba, x*N/2, y*N/2) if src.rgba is not transparent_tile.rgba: empty = False if empty: # rare case, no need to speed it up del self.tiledict[(tx, ty)] t = transparent_tile return t