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 if obj.shape[-1] == 4: raise BackgroundError, 'background tile with alpha channel is not allowed' if obj.shape != (self.th*N, self.tw*N, 3): 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.zeros((N, N, 3), dtype='uint16') tile[:,:,:] = obj[N*ty:N*(ty+1), N*tx:N*(tx+1), :] 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, 3), 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_rgb16(src, mipmap_obj, tx*N/2, ty*N/2) self.mipmap = Background(mipmap_obj, mipmap_level+1)
def load_layer_from_pixbuf(self, pixbuf, x=0, y=0): arr = helpers.gdkpixbuf2numpy(pixbuf) s = tiledsurface.Surface() bbox = s.load_from_numpy(arr, x, y) #added x, y pointer position here #cur_x, cur_y = self.tdw.get_cursor_in_model_coordinates() self.do(command.LoadLayer(self, s)) return bbox
def __init__(self, x, y, w, h, alpha=False, data=None): assert w > 0 and h > 0 # We create and use a pixbuf enlarged to the tile boundaries internally. # Variables ex, ey, ew, eh and epixbuf store the enlarged version. self.x, self.y, self.w, self.h = x, y, w, h #print x, y, w, h tx = self.tx = x / N ty = self.ty = y / N self.ex = tx * N self.ey = ty * N tw = (x + w - 1) / N - tx + 1 th = (y + h - 1) / N - ty + 1 self.ew = tw * N self.eh = th * N #print 'b:', self.ex, self.ey, self.ew, self.eh # OPTIMIZE: remove assertions here? assert self.ew >= w and self.eh >= h assert self.ex <= x and self.ey <= y self.epixbuf = gdk.Pixbuf(gdk.COLORSPACE_RGB, alpha, 8, self.ew, self.eh) dx = x - self.ex dy = y - self.ey self.pixbuf = self.epixbuf.subpixbuf(dx, dy, w, h) assert self.ew <= w + 2 * N - 2 assert self.eh <= h + 2 * N - 2 if not alpha: #self.epixbuf.fill(0xff44ff44) # to detect uninitialized memory pass # speeds up scrolling slightly else: self.epixbuf.fill(0x00000000) # keep undefined regions transparent arr = helpers.gdkpixbuf2numpy(self.epixbuf) discard_transparent = False if data is not None: dst = arr[dy:dy + h, dx:dx + w, :] if data.shape[2] == 3: # no alpha dst[:, :, 0:3] = data dst[:, :, 3] = 255 else: dst[:, :, :] = data # this surface will be used read-only discard_transparent = True self.tile_memory_dict = {} for ty in range(th): for tx in range(tw): buf = arr[ty * N:(ty + 1) * N, tx * N:(tx + 1) * N, :] if discard_transparent and not buf[:, :, 3].any(): continue self.tile_memory_dict[(self.tx + tx, self.ty + ty)] = buf
def __init__(self, x, y, w, h, data=None): assert w>0 and h>0 # We create and use a pixbuf enlarged to the tile boundaries internally. # Variables ex, ey, ew, eh and epixbuf store the enlarged version. self.x, self.y, self.w, self.h = x, y, w, h #print x, y, w, h tx = self.tx = x/N ty = self.ty = y/N self.ex = tx*N self.ey = ty*N tw = (x+w-1)/N - tx + 1 th = (y+h-1)/N - ty + 1 self.ew = tw*N self.eh = th*N #print 'b:', self.ex, self.ey, self.ew, self.eh # OPTIMIZE: remove assertions here? assert self.ew >= w and self.eh >= h assert self.ex <= x and self.ey <= y self.epixbuf = pygtkcompat.gdk.pixbuf.new(gdk.COLORSPACE_RGB, True, 8, self.ew, self.eh) dx = x-self.ex dy = y-self.ey if pygtkcompat.USE_GTK3: self.pixbuf = self.epixbuf.new_subpixbuf(dx, dy, w, h) else: self.pixbuf = self.epixbuf.subpixbuf(dx, dy, w, h) assert self.ew <= w + 2*N-2 assert self.eh <= h + 2*N-2 self.epixbuf.fill(0x00000000) # keep undefined regions transparent arr = helpers.gdkpixbuf2numpy(self.epixbuf) assert len(arr) > 0 discard_transparent = False if data is not None: dst = arr[dy:dy+h,dx:dx+w,:] if data.shape[2] == 4: dst[:,:,:] = data discard_transparent = True else: assert data.shape[2] == 3 # no alpha channel dst[:,:,:3] = data dst[:,:,3] = 255 self.tile_memory_dict = {} for ty in range(th): for tx in range(tw): buf = arr[ty*N:(ty+1)*N,tx*N:(tx+1)*N,:] if discard_transparent and not buf[:,:,3].any(): continue self.tile_memory_dict[(self.tx+tx, self.ty+ty)] = buf
def __init__(self, x, y, w, h, alpha=False, data=None): assert w>0 and h>0 # We create and use a pixbuf enlarged to the tile boundaries internally. # Variables ex, ey, ew, eh and epixbuf store the enlarged version. self.x, self.y, self.w, self.h = x, y, w, h #print x, y, w, h tx = self.tx = x/N ty = self.ty = y/N self.ex = tx*N self.ey = ty*N tw = (x+w-1)/N - tx + 1 th = (y+h-1)/N - ty + 1 self.ew = tw*N self.eh = th*N #print 'b:', self.ex, self.ey, self.ew, self.eh # OPTIMIZE: remove assertions here? assert self.ew >= w and self.eh >= h assert self.ex <= x and self.ey <= y self.epixbuf = gdk.Pixbuf(gdk.COLORSPACE_RGB, alpha, 8, self.ew, self.eh) dx = x-self.ex dy = y-self.ey self.pixbuf = self.epixbuf.subpixbuf(dx, dy, w, h) assert self.ew <= w + 2*N-2 assert self.eh <= h + 2*N-2 if not alpha: #self.epixbuf.fill(0xff44ff44) # to detect uninitialized memory pass # speeds up scrolling slightly else: self.epixbuf.fill(0x00000000) # keep undefined regions transparent arr = helpers.gdkpixbuf2numpy(self.epixbuf) discard_transparent = False if data is not None: dst = arr[dy:dy+h,dx:dx+w,:] if data.shape[2] == 3: # no alpha dst[:,:,0:3] = data dst[:,:,3] = 255 else: dst[:,:,:] = data # this surface will be used read-only discard_transparent = True self.tile_memory_dict = {} for ty in range(th): for tx in range(tw): buf = arr[ty*N:(ty+1)*N,tx*N:(tx+1)*N,:] if discard_transparent and not buf[:,:,3].any(): continue self.tile_memory_dict[(self.tx+tx, self.ty+ty)] = buf
def scale_layer_from_pixbuf(self, pixbuf, direction, x, y): pixbuf = helpers.scale_incrementally(pixbuf, direction) #print 'scale' arr = helpers.gdkpixbuf2numpy(pixbuf) s = tiledsurface.Surface() bbox = s.load_from_numpy(arr, x, y) self.do(command.LoadLayer(self, s)) return bbox
def __init__(self, x, y, w, h, data=None): object.__init__(self) assert w > 0 and h > 0 # We create and use a pixbuf enlarged to the tile boundaries internally. # Variables ex, ey, ew, eh and epixbuf store the enlarged version. self.x, self.y, self.w, self.h = x, y, w, h #print x, y, w, h tx = self.tx = x / N ty = self.ty = y / N self.ex = tx * N self.ey = ty * N tw = (x + w - 1) / N - tx + 1 th = (y + h - 1) / N - ty + 1 self.ew = tw * N self.eh = th * N #print 'b:', self.ex, self.ey, self.ew, self.eh # OPTIMIZE: remove assertions here? assert self.ew >= w and self.eh >= h assert self.ex <= x and self.ey <= y self.epixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, self.ew, self.eh) dx = x - self.ex dy = y - self.ey self.pixbuf = self.epixbuf.new_subpixbuf(dx, dy, w, h) assert self.ew <= w + 2 * N - 2 assert self.eh <= h + 2 * N - 2 self.epixbuf.fill(0x00000000) # keep undefined regions transparent arr = helpers.gdkpixbuf2numpy(self.epixbuf) assert len(arr) > 0 discard_transparent = False if data is not None: dst = arr[dy:dy + h, dx:dx + w, :] if data.shape[2] == 4: dst[:, :, :] = data discard_transparent = True else: assert data.shape[2] == 3 # no alpha channel dst[:, :, :3] = data dst[:, :, 3] = 255 self.tile_memory_dict = {} for ty in range(th): for tx in range(tw): buf = arr[ty * N:(ty + 1) * N, tx * N:(tx + 1) * N, :] if discard_transparent and not buf[:, :, 3].any(): continue self.tile_memory_dict[(self.tx + tx, self.ty + ty)] = buf
def set_background(self, obj, make_default=False): # This is not an undoable action. One reason is that dragging # on the color chooser would get tons of undo steps. if not isinstance(obj, tiledsurface.Background): if isinstance(obj, GdkPixbuf.Pixbuf): obj = helpers.gdkpixbuf2numpy(obj) obj = tiledsurface.Background(obj) self.background = obj if make_default: self.default_background = obj self.invalidate_all()
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 if obj.shape[-1] == 4: raise BackgroundError, 'background tile with alpha channel is not allowed' if obj.shape != (self.th * N, self.tw * N, 3): 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.zeros((N, N, 3), dtype='uint16') tile[:, :, :] = obj[N * ty:N * (ty + 1), N * tx:N * (tx + 1), :] 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, 3), 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_rgb16(src, mipmap_obj, tx * N / 2, ty * N / 2) self.mipmap = Background(mipmap_obj, mipmap_level + 1)
def __init__(self, x, y, w, h, data=None): super(Surface, self).__init__() assert w > 0 and h > 0 # We create and use a pixbuf enlarged to the tile boundaries internally. # Variables ex, ey, ew, eh and epixbuf store the enlarged version. self.x, self.y, self.w, self.h = x, y, w, h #print x, y, w, h tx = self.tx = x/N ty = self.ty = y/N self.ex = tx*N self.ey = ty*N tw = (x+w-1)/N - tx + 1 th = (y+h-1)/N - ty + 1 self.ew = tw*N self.eh = th*N #print 'b:', self.ex, self.ey, self.ew, self.eh # OPTIMIZE: remove assertions here? assert self.ew >= w and self.eh >= h assert self.ex <= x and self.ey <= y # Tile-aligned pixbuf: also accessible by tile try: self.epixbuf = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, True, 8, self.ew, self.eh ) except Exception as te: logger.exception("GdkPixbuf.Pixbuf.new() failed") raise AllocationError(_POSSIBLE_OOM_USERTEXT) if self.epixbuf is None: logger.error("GdkPixbuf.Pixbuf.new() returned NULL") raise AllocationError(_POSSIBLE_OOM_USERTEXT) # External subpixbuf, also accessible by tile. dx = x-self.ex dy = y-self.ey try: self.pixbuf = self.epixbuf.new_subpixbuf(dx, dy, w, h) except Exception as te: logger.exception("GdkPixbuf.Pixbuf.new_subpixbuf() failed") raise AllocationError(_POSSIBLE_OOM_USERTEXT) if self.pixbuf is None: logger.error("GdkPixbuf.Pixbuf.new_subpixbuf() returned NULL") raise AllocationError(_POSSIBLE_OOM_USERTEXT) assert self.ew <= w + 2*N-2 assert self.eh <= h + 2*N-2 self.epixbuf.fill(0x00000000) # keep undefined regions transparent # Make it accessible by tile arr = helpers.gdkpixbuf2numpy(self.epixbuf) assert len(arr) > 0 discard_transparent = False if data is not None: dst = arr[dy:dy+h, dx:dx+w, :] if data.shape[2] == 4: dst[:, :, :] = data discard_transparent = True else: assert data.shape[2] == 3 # no alpha channel dst[:, :, :3] = data dst[:, :, 3] = 255 # Build (tx,ty)-indexed access struct self.tile_memory_dict = {} for ty in range(th): for tx in range(tw): buf = arr[ty*N:(ty+1)*N, tx*N:(tx+1)*N, :] if discard_transparent and not buf[:, :, 3].any(): continue self.tile_memory_dict[(self.tx+tx, self.ty+ty)] = buf
def load_layer_from_pixbuf(self, pixbuf, x=0, y=0): arr = helpers.gdkpixbuf2numpy(pixbuf) s = tiledsurface.Surface() bbox = s.load_from_numpy(arr, x, y) self.do(command.LoadLayer(self, s)) return bbox
def load_layer_from_pixbuf(self, pixbuf, x=0, y=0): arr = helpers.gdkpixbuf2numpy(pixbuf) self.do(command.LoadLayer(self, arr, x, y))
if len(self.layers) == 1: raise ValueError, 'Could not load any layer.' if no_background: # recognize solid or tiled background layers, at least those that mypaint <= 0.7.1 saves t1 = time.time() p = last_pixbuf if not p.get_has_alpha() and p.get_width() % N == 0 and p.get_height() % N == 0: tiles = self.layers[0].surface.tiledict.values() if len(tiles) > 1: all_equal = True for tile in tiles[1:]: if (tile.rgba != tiles[0].rgba).any(): all_equal = False break if all_equal: arr = helpers.gdkpixbuf2numpy(p) tile = arr[0:N,0:N,:] self.set_background(tile.copy()) self.select_layer(0) self.remove_layer() print ' %.3fs recognizing tiled background' % (time.time() - t1) if len(self.layers) > 1: # remove the still present initial empty top layer self.select_layer(len(self.layers)-1) self.remove_layer() # this leaves the topmost layer selected print '%.3fs load_ora total' % (time.time() - t0)
# no assertion (allow empty documents) print 'Warning: Could not load any layer, document is empty.' if no_background: # recognize solid or tiled background layers, at least those that mypaint <= 0.7.1 saves t1 = time.time() p = last_pixbuf if not p.get_has_alpha() and p.get_width() % N == 0 and p.get_height() % N == 0: tiles = self.layers[0]._surface.tiledict.values() if len(tiles) > 1: all_equal = True for tile in tiles[1:]: if (tile.rgba != tiles[0].rgba).any(): all_equal = False break if all_equal: arr = helpers.gdkpixbuf2numpy(p) tile = arr[0:N,0:N,:] self.set_background(tile.copy()) self.select_layer(0) self.remove_layer() print ' %.3fs recognizing tiled background' % (time.time() - t1) if len(self.layers) > 1: # remove the still present initial empty top layer self.select_layer(len(self.layers)-1) self.remove_layer() # this leaves the topmost layer selected print '%.3fs load_ora total' % (time.time() - t0)