def sky(width, height, canvas, gs): def rcolor(): return hsv2rgb(.55 + randneghalf2half() * .25, .6 + randneghalf2half() * .125, .25 + randneghalf2half() * .125) transform = agg.Transform() starpaint = agg.SolidPaint(*hsv2rgb(.165, .96, .99)) starshape = agg.Path() angles = np.linspace(0, 2 * np.pi, num=5, endpoint=False) pts = np.stack([np.cos(angles), np.sin(angles)]).T * 7 starshape.lines([pts[i] for i in (0, 2, 4, 1, 3)]) starshape.close() bgshape = agg.Path() bgshape.rect(0, 0, width, height) bgpaint = agg.LinearGradientPaint(0, 0, 0, height, randgradstops(2, rcolor), agg.GradientSpread.SpreadReflect, agg.GradientUnits.UserSpace) canvas.draw_shape(bgshape, transform, gs, fill=bgpaint) star_count = 40 xs = np.random.rand(star_count) * width ys = np.random.rand(star_count) * height for x, y in zip(xs, ys): transform.reset() transform.translate(x, y) canvas.draw_shape(starshape, transform, gs, fill=starpaint)
def spiral(size, hue, sat, val): canvas = agg.CanvasRGB24(np.zeros((size[1], size[0], 3), dtype=np.uint8)) gs = agg.GraphicsState(drawing_mode=agg.DrawingMode.DrawFill) transform = agg.Transform() circle = agg.Path() circle.ellipse(0, 0, CIRCLE_SIZE, CIRCLE_SIZE) divisions = np.linspace(0, 2*np.pi, CIRCLE_COUNT, endpoint=False) centers = np.stack((np.cos(divisions), np.sin(divisions)), axis=1) offsets = compute_offsets(np.sqrt(size[0]**2 + size[1]**2) / 2) color_count = len(offsets) hsv = np.ones((color_count, 1, 3)) hsv[:, 0, 0] = np.linspace(hue[0], hue[1], color_count, endpoint=False) hsv[:, 0, 1] = np.linspace(sat[0], sat[1], color_count, endpoint=False) hsv[:, 0, 2] = np.linspace(val[0], val[1], color_count, endpoint=False) spectrum = hsv2rgb(hsv).reshape(color_count, 3) for idx, offset in enumerate(offsets): paint = agg.SolidPaint(*spectrum[idx]) radius = np.pi * offset / CIRCLE_COUNT scale = radius / CIRCLE_SIZE for i in range(CIRCLE_COUNT): if ((idx + i) % 2) == 0: continue transform.reset() transform.translate(size[0]/2 + offset*centers[i, 0], size[1]/2 + offset*centers[i, 1]) transform.scale(scale, scale) canvas.draw_shape(circle, transform, gs, fill=paint) imsave('spiral.png', canvas.array)
def worm_frame_mask(width_tck, image_shape, num_spline_points=None, antialias=False, zoom=1): """Use a centerline and width spline to draw a worm mask image in the worm frame of reference. Parameters: width_tck: width splines defining worm outline image_shape: shape of the output mask num_spline_points: number of points to evaluate the worm outline along (more points = smoother mask). By default, ~1 point/pixel will be used, which is more than enough. antialias: if False, return a mask with only values 0 and 255. If True, edges will be smoothed for better appearance. This is slightly slower, and unnecessary when just using the mask to select pixels of interest. zoom: zoom-value to use (for matching output of to_worm_frame with zooming.) Returns: mask image with dtype=numpy.uint8 in range [0, 255]. To obtain a True/False-valued mask from a uint8 mask (regardless of antialiasing): bool_mask = uint8_mask > 255 """ worm_length = image_shape[0] if num_spline_points is None: num_spline_points = worm_length widths = interpolate.spline_interpolate(width_tck, num_points=num_spline_points) widths *= zoom x_vals = numpy.linspace(0, worm_length, num_spline_points) centerline_y = image_shape[1] / 2 top = numpy.transpose([x_vals, centerline_y - widths]) bottom = numpy.transpose([x_vals, centerline_y + widths])[::-1] path = celiagg.Path() path.lines(numpy.concatenate([top, bottom])) return draw.draw_mask(image_shape, path, antialias)
def test_bad_method_args(): canvas = agg.CanvasG8(np.zeros((1, 1), dtype=np.uint8)) pix_format = agg.PixelFormat.Gray8 gs = agg.GraphicsState() path = agg.Path() transform = agg.Transform() with pytest.raises(TypeError): canvas.draw_image(None, pix_format, transform, gs) with pytest.raises(TypeError): canvas.draw_image(canvas.array, None, transform, gs) with pytest.raises(TypeError): canvas.draw_image(canvas.array, pix_format, None, gs) with pytest.raises(TypeError): canvas.draw_image(canvas.array, pix_format, transform, None) # But this version should work canvas.draw_image(canvas.image, None, transform, gs) with pytest.raises(TypeError): canvas.draw_shape(None, transform, gs) with pytest.raises(TypeError): canvas.draw_shape(path, None, gs) with pytest.raises(TypeError): canvas.draw_shape(path, transform, None) text = "Hello!" font = agg.Font("Times New Roman", 12.0, agg.FontCacheType.RasterFontCache) with pytest.raises(TypeError): canvas.draw_text(text, None, transform, gs) with pytest.raises(TypeError): canvas.draw_text(text, font, None, gs) with pytest.raises(TypeError): canvas.draw_text(text, font, transform, None)
def lab_frame_mask(center_tck, width_tck, image_shape, num_spline_points=None, antialias=False): """Use a centerline and width spline to draw a worm mask image in the lab frame of reference. Parameters: center_tck, width_tck: centerline and width splines defining worm pose. image_shape: shape of the output mask num_spline_points: number of points to evaluate the worm outline along (more points = smoother mask). By default, ~1 point/pixel will be used, which is more than enough. antialias: if False, return a mask with only values 0 and 255. If True, edges will be smoothed for better appearance. This is slightly slower, and unnecessary when just using the mask to select pixels of interest. Returns: mask image with dtype=numpy.uint8 in range [0, 255]. To obtain a True/False-valued mask from a uint8 mask (regardless of antialiasing): bool_mask = uint8_mask > 255 """ path = celiagg.Path() path.lines( spline_geometry.outline(center_tck, width_tck, num_points=num_spline_points)[-1]) return draw.draw_mask(image_shape, path, antialias)
def fill_rects(self, rects): path = agg.Path() path.rects(rects) self.canvas_state.drawing_mode = agg.DrawingMode.DrawFill self.gc.draw_shape( path, self.transform, self.canvas_state, fill=self.fill_paint )
def draw_rect(self, rect, mode=constants.FILL_STROKE): """ Draw a rect. """ # XXX: kiva::graphics_context<>::_draw_rect_simple() does a VERY # specific optimization for drawing rectangles in certain circumstances # which results in chaco plot borders which are sharp. # This implements that same special case. - JW 2018/09/01 transform = self.transform if (not self.canvas_state.anti_aliased and self.canvas_state.line_width in (0.0, 1.0) and fabs(self.transform.shx) < 1e-3 and fabs(self.transform.shy) < 1e-3): scale_x = self.transform.sx scale_y = self.transform.sy tx = self.transform.tx ty = self.transform.ty x1 = int(rect[0] * scale_x + tx) y1 = int(rect[1] * scale_y + ty) x2 = int((rect[0] + rect[2]) * scale_x + tx) y2 = int((rect[1] + rect[3]) * scale_y + ty) rect = (x1, y1, abs(x2 - x1), abs(y2 - y1)) # XXX: The base transform is a half-pixel translate transform = agg.Transform(tx=0.5, ty=0.5) path = agg.Path() path.rect(*rect) self.canvas_state.drawing_mode = draw_modes[mode] self.gc.draw_shape(path, transform, self.canvas_state, stroke=self.stroke_paint, fill=self.fill_paint)
def fill_rect(self, rect): shape = agg.Path() shape.rect(*rect) self.canvas_state.drawing_mode = agg.DrawingMode.DrawFill self.gc.draw_shape( shape, self.transform, self.canvas_state, fill=self.fill_paint )
def clear_rect(self, rect): shape = agg.Path() shape.rect(*rect) paint = agg.SolidPaint(0.0, 0.0, 0.0, 0.0) self.canvas_state.drawing_mode = agg.DrawingMode.DrawFill self.gc.draw_shape( shape, self.transform, self.canvas_state, fill=paint )
def test_stencil_size_mismatch(): canvas = agg.CanvasRGB24(np.zeros((4, 5, 3), dtype=np.uint8)) stencil_canvas = agg.CanvasG8(np.zeros((1, 2), dtype=np.uint8)) gs = agg.GraphicsState(stencil=stencil_canvas.image) path = agg.Path() transform = agg.Transform() with pytest.raises(agg.AggError): canvas.draw_shape(path, transform, gs)
def stroke_rect_with_width(self, rect, width): shape = agg.Path() shape.rect(*rect) self.canvas_state.line_width = width self.canvas_state.drawing_mode = agg.DrawingMode.DrawStroke self.gc.draw_shape( shape, self.transform, self.canvas_state, stroke=self.stroke_paint )
def test_ellipse(canvas, paint, state, transform): path = agg.Path() path.ellipse(2.5, 2.5, 2, 2) expected = [ [0, 1, 1, 1, 0], [1, 1, 0, 1, 1], [1, 0, 0, 0, 1], [1, 1, 0, 1, 1], [0, 1, 1, 1, 0], ] canvas.draw_shape(path, transform, state, stroke=paint) assert_equal(expected, canvas.array)
def draw_rect(self, rect, mode=constants.FILL_STROKE): """ Draw a rect. """ path = agg.Path() path.rect(*rect) self.canvas_state.drawing_mode = draw_modes[mode] self.gc.draw_shape(path, self.transform, self.canvas_state, stroke=self.stroke_paint, fill=self.fill_paint)
def vignette_mask(optocoupler, shape, cx=0.5, cy=0.5): """Return a boolean mask of the un-vignetted area of an image. Parameters: optocoupler: magnification of optocoupler (as a float), which determines the vignette size. Should be 1 or 0.7. shape: shape of desired mask. cx, cy: center of the vignetted region, as a fraction of image width or height, respectively. Returns: boolean mask """ r = VIGNETTE_RADIUS_1X * optocoupler cx, cy, r = int(cx * shape[0]), int(cy * shape[1]), int(r * shape[0]) path = celiagg.Path() path.ellipse(cx, cy, r, r) return draw.draw_mask(shape, path, antialias=False) > 0
def test_lines(canvas, paint, state, transform): path = agg.Path() path.move_to(0, .5) path.line_to(5, .5) expected = [ [1, 1, 1, 1, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ] canvas.draw_shape(path, transform, state, stroke=paint) assert_equal(expected, canvas.array) canvas.clear(0, 0, 0) path.reset() path.move_to(.5, 0) path.line_to(.5, 5) expected = [ [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], ] canvas.draw_shape(path, transform, state, stroke=paint) assert_equal(expected, canvas.array) canvas.clear(0, 0, 0) path.reset() path.move_to(0, 0) path.line_to(5, 5) path.move_to(0, 5) path.line_to(5, 0) state.line_width = 0.5 expected = [ [1, 0, 0, 0, 1], [0, 1, 0, 1, 0], [0, 0, 1, 0, 0], [0, 1, 0, 1, 0], [1, 0, 0, 0, 1], ] canvas.draw_shape(path, transform, state, stroke=paint) assert_equal(expected, canvas.array)
def make_mask(metadata, mask_file): spine_tck = metadata['spine_tck'] width_tck = metadata['width_tck'] outline = spline_geometry.outline(spine_tck, width_tck, num_points=400)[-1] image = numpy.zeros( (1040, 1388), dtype=numpy.uint8) # Celiagg convention: image.shape = (H, W) canvas = celiagg.CanvasG8(image) path = celiagg.Path() path.lines(outline) path.close() canvas.draw_shape(path, AGG_TRANSFORM, AGG_STATE, fill=AGG_PAINT, stroke=AGG_TRANSPARENT) freeimage.write( image.T, mask_file ) # freeimage convention: image.shape = (W, H). So take transpose.
def draw_horizon(xs, ys, canvas, gs): def rcolor(): return hsv2rgb(.125 + randneghalf2half() * .25, .6 + randneghalf2half() * .4, .6 + randneghalf2half() * .4) width = xs[-1] path = agg.Path() path.move_to(0, 0) path.line_to(xs[0], ys[0]) for x, y in zip(xs[1:], ys[1:]): path.line_to(x, y) path.line_to(width, 0) path.close() transform = agg.Transform() fill = agg.LinearGradientPaint(0, 0, width, 0, randgradstops(2, rcolor), agg.GradientSpread.SpreadReflect, agg.GradientUnits.UserSpace) canvas.draw_shape(path, transform, gs, fill=fill)
def test_rect(canvas, paint, state, transform): path = agg.Path() path.rect(0, 0, 5, 5) expected = [ [1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1], ] canvas.draw_shape(path, transform, state, stroke=paint) assert_equal(expected, canvas.array) expected = [ [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], ] canvas.draw_shape(path, transform, state, fill=paint, stroke=paint) assert_equal(expected, canvas.array)
def __init__(self): self.path = agg.Path()
def clip_to_rects(self, rects): """ Clip context to a collection of rectangles """ path = agg.Path() path.rects(rects) self._clip_impl(path, agg.DrawingMode.DrawFill)
def circle_mask(cx, cy, r, shape): cx, cy, r = int(cx * shape[0]), int(cy * shape[1]), int(r * shape[0]) path = celiagg.Path() path.ellipse(cx, cy, r, r) return worm_spline._celiagg_draw_mask(shape, path, antialias=False)
import numpy as np from skimage.io import imsave import celiagg as agg SIZE = 1000 order = (2, 4, 1, 3, 0) angles = np.linspace(0, 2 * np.pi, num=5, endpoint=False) pts = np.stack([np.cos(angles), np.sin(angles)]).T * SIZE / 2 + SIZE / 2 star_shape = agg.Path() star_shape.lines([pts[i] for i in (0, 2, 4, 1, 3)]) star_shape.close() star_transform = agg.Transform() star_transform.translate(SIZE / 2, SIZE / 2) star_transform.rotate(-np.pi / 2) star_transform.translate(-SIZE / 2, -SIZE / 2) big_box = agg.Path() big_box.rect(0, 0, SIZE, SIZE) small_box = agg.Path() small_box.rect(0, 0, SIZE / 2, SIZE / 2) stencil_canvas = agg.CanvasG8(np.zeros((SIZE, SIZE), dtype=np.uint8)) canvas = agg.CanvasRGB24(np.zeros((SIZE, SIZE, 3), dtype=np.uint8)) gs = agg.GraphicsState(drawing_mode=agg.DrawingMode.DrawFill, line_width=6.0) transform = agg.Transform() blue_paint = agg.SolidPaint(0.1, 0.1, 1.0) white_paint = agg.SolidPaint(1.0, 1.0, 1.0) stops = ((0.0, 0.0, 0.0, 0.0, 1.0), (1.0, 0.3, 0.3, 0.75, 1.0)) bw_grad = agg.LinearGradientPaint(0, 0, 2, 5, stops,
import celiagg as agg import numpy as np from skimage.io import imsave canvas = agg.CanvasRGB24(np.ones((400, 400, 3), dtype=np.uint8)) state = agg.GraphicsState(drawing_mode=agg.DrawingMode.DrawStroke, line_width=10.0) transform = agg.Transform() red_paint = agg.SolidPaint(1.0, 0.0, 0.0) black_paint = agg.SolidPaint(0.0, 0.0, 0.0) font = agg.Font("/Library/Fonts/Verdana.ttf", 96.0, agg.FontCacheType.RasterFontCache) path = agg.Path() path.ellipse(200, 200, 190, 190) canvas.clear(1.0, 1.0, 1.0) canvas.draw_shape(path, transform, state, stroke=red_paint) transform.translate(30.0, 220.0) canvas.draw_text("celiagg", font, transform, state, stroke=black_paint) imsave("example.png", canvas.array)
def parse_path(elem, context): def extractnum(it, offset): return float(next(it).group('num')) + offset regex = re.compile( '(?P<command>[MmZzLlHhVvCcSsQqTtAa])|' '(?P<num>-?(([0-9]*[.][0-9]*)|[0-9]+)([eE][+-]?[0-9]*)?)') path = agg.Path() dataiter = regex.finditer(elem.get('d', '')) currentpt = (0.0, 0.0) lastctrl = None for chunk in dataiter: command = chunk.group('command') if command in 'mM': offx = currentpt[0] if command.islower() else 0.0 offy = currentpt[1] if command.islower() else 0.0 x, y = (extractnum(dataiter, offx), extractnum(dataiter, offy)) path.move_to(x, y) currentpt = (x, y) lastctrl = None elif command in 'lL': offx = currentpt[0] if command.islower() else 0.0 offy = currentpt[1] if command.islower() else 0.0 x, y = (extractnum(dataiter, offx), extractnum(dataiter, offy)) path.line_to(x, y) currentpt = (x, y) lastctrl = None elif command in 'hH': offx = currentpt[0] if command.islower() else 0.0 x, y = (extractnum(dataiter, offx), currentpt[1]) path.line_to(x, y) currentpt = (x, y) lastctrl = None elif command in 'vV': offy = currentpt[1] if command.islower() else 0.0 x, y = (currentpt[0], extractnum(dataiter, offy)) path.line_to(x, y) currentpt = (x, y) lastctrl = None elif command in 'cC': offx = currentpt[0] if command.islower() else 0.0 offy = currentpt[1] if command.islower() else 0.0 x1, y1 = extractnum(dataiter, offx), extractnum(dataiter, offy) x2, y2 = extractnum(dataiter, offx), extractnum(dataiter, offy) x, y = extractnum(dataiter, offx), extractnum(dataiter, offy) path.cubic_to(x1, y1, x2, y2, x, y) currentpt = (x, y) lastctrl = (x2, y2) elif command in 'sS': offx = currentpt[0] if command.islower() else 0.0 offy = currentpt[1] if command.islower() else 0.0 x1, y1 = currentpt if lastctrl is None else lastctrl x2, y2 = extractnum(dataiter, offx), extractnum(dataiter, offy) x, y = extractnum(dataiter, offx), extractnum(dataiter, offy) path.cubic_to(x1, y1, x2, y2, x, y) currentpt = (x, y) lastctrl = (x2, y2) elif command in 'qQ': offx = currentpt[0] if command.islower() else 0.0 offy = currentpt[1] if command.islower() else 0.0 x1, y1 = extractnum(dataiter, offx), extractnum(dataiter, offy) x, y = extractnum(dataiter, offx), extractnum(dataiter, offy) path.quadric_to(x1, y1, x, y) currentpt = (x, y) lastctrl = (x1, y1) elif command in 'tT': offx = currentpt[0] if command.islower() else 0.0 offy = currentpt[1] if command.islower() else 0.0 x1, y1 = currentpt if lastctrl is None else lastctrl x, y = extractnum(dataiter, offx), extractnum(dataiter, offy) path.quadric_to(x1, y1, x, y) currentpt = (x, y) lastctrl = (x1, y1) elif command in 'aA': # Elliptical arc. ``agg.Path`` does not directly support this. next(dataiter) next(dataiter) next(dataiter) next(dataiter) next(dataiter) next(dataiter) next(dataiter) elif command in 'zZ': path.close() return { 'style': parse_style(elem.get('style', '')), 'transform': parse_transform(elem.get('transform', '')), 'data': path }