def draw_image_line(self, width, line, totlines, buff): ''' Reads in the buffer from the EyeLink camera image line by line and writes it into a buffer of size (width * totlines). Once the last line of the image has been read into the buffer, the image buffer is placed in a PIL.Image with the palette set by set_image_palette, converted to RGBA, resized, and then rendered to the middle of the screen. After rendering, the image buffer is cleared. ''' if len(self.imagebuffer) > (width * totlines): self.imagebuffer = [] self.imagebuffer += buff if int(line) == int(totlines): # Render complete camera image and resize to self.size img = Image.new("P", (width, totlines), 0) img.putpalette(self.palette) img.putdata(self.imagebuffer) self.img = img.convert('RGBA').resize(self.size, Image.BILINEAR) # Set up aggdraw to draw crosshair/bounds/etc. on image surface self.drawer = Draw(self.img) self.drawer.setantialias(True) self.draw_cross_hair() self.drawer.flush() # Draw complete image to screen fill() blit(asarray(self.img), 5, P.screen_c) if self.title: loc_x = (P.screen_c[0]) loc_y = (P.screen_c[1] + self.size[1] / 2 + 20) blit(self.title, 8, (loc_x, loc_y)) flip() # Clear image buffer self.imagebuffer = []
def initialize_renderers(self): ''' We will initialize the draw objects for each individual/solution as to save computations. Instead of reinitializing them each iteration we will wipe the images by drawing a opaque rectangle in white or black. Then render the shapes on top. This method creates those draw objects and stores them in a list. ''' self.draws = [] self.bg_brush = Brush((0, 0, 0) if self.bg_color == 'black' else (255, 255, 255), 255) self.bg_coords = (0, 0, *self.img_size) if self.shape_type in {'circle', 'square'}: self.render_method = self.render_uni_verts else: self.render_method = self.render_multi_verts if self.shape_type == 'circle': self.draw_method = 'ellipse' elif self.shape_type == 'square': self.draw_method = 'rectangle' else: self.draw_method = self.shape_type for _ in self.pop_range: draw = Draw('RGBA', self.img_size, self.bg_color) draw.setantialias(False) self.draws.append([draw, getattr(draw, self.draw_method)])
def __init__( self, img=None, imageType=None, # determines file type fileName=None, # if set determines output file name size=None, ): if img is None: try: import Image except ImportError: from PIL import Image if size is None: raise ValueError('please provide either an image or a size') img = Image.new('RGBA', size, "white") self.image = img self.draw = Draw(img) self.draw.setantialias(True) if size is None: self.size = self.draw.size else: self.size = size if imageType and imageType not in ('png', 'jpg'): raise ValueError('unsupported image type for agg canvas') self.drawType = imageType self.fileName = fileName
def get_image(self, im_width, im_length): im = Image.new("RGBA", (im_width, im_length), (0, 0, 0, MAX_COLOR)) # Black image draw = Draw(im) for shape in self.shapes_list: shape.draw(draw) draw.flush() return im
def create_pixel_img( self, scale, text, color, ): '''Creats a new canvas and draws text onto it if overridin''' font = Font(self.new_txt_color(color), self.font, self.font_size) bg_color = self.new_bg_color(color) img = Draw('RGB', scale, bg_color) img.text((0, 7), text, font) return img
def create_pixel_img(self, scale, text, color): '''Creats a new canvas and draws text onto it if overridin''' #define the font and the blank canvas font = Font(self.new_txt_color(color), self.font, self.font_size) #defines the background color of the canvas bg_color = self.new_bg_color(color) img = Draw('RGB', scale, bg_color) #draw text on to the canvas by default only one line of text is drawn #this method can be overriden to draw as much text as you want #Note that the if the scale is not large enough not all the text will be displayed img.text((0, 0), text, font) return img
def render_img_oaat_exis_mode(self, i: int): ''' One At A Time Renders the last image that was initialized ''' img = self.bgs[i] draw = Draw(img) draw.setantialias(False) draw_method = getattr(draw, self.draw_method) self.render_method(draw_method, self.mapped_population_b10[i, self.b10_idx[-1]]) return np.frombuffer(draw.tobytes(), dtype='uint8').reshape(-1, 4, order='C')[:, :3]
def getProgressItems(self, curStepIndex, steps): total = len(steps) marginTop = 4 dia = 9 space = 12 image = Image.new("RGB", (self.width, dia + int(marginTop * 1.5))) draw = Draw(image) w = ((dia + space) * total) - space marginLeft = (self.width - w) / 2 for s in range(total): left = marginLeft + ((dia + space) * s) draw.ellipse((left, marginTop, left + dia, marginTop + dia), Pen(self.colors[steps[s]]), Brush(self.colors[steps[s]])) if curStepIndex < s: draw.ellipse( (left + (dia * 0.25), marginTop + (dia * 0.25), left + (dia * 0.75), marginTop + (dia * 0.75)), Pen("#000"), Brush("#000")) draw.flush() return image
def _init_surface(self): self._update_dimensions() self.rendered = None # Clear any existing rendered texture if self.fill_color: if self.stroke_color and self.fill_color[3] == 255: col = self.stroke_color else: col = self.fill_color elif self.stroke_color: col = self.stroke_color else: col = (0, 0, 0) self.canvas = Image.new("RGBA", self.dimensions, (col[0], col[1], col[2], 0)) self.surface = Draw(self.canvas) self.surface.setantialias(True)
def test_graphics3(): """See issue #22.""" from aggdraw import Draw, Pen from PIL import Image main = Image.new('RGB', (480, 1024), 'white') d = Draw(main) p = Pen((90,) * 3, 0.5)
def __init__( self, img=None, imageType=None, # determines file type fileName=None, # if set determines output file name size=None, ): if img is None: try: import Image except ImportError: from PIL import Image if size is None: raise ValueError, "please provide either an image or a size" img = Image.new("RGBA", size, "white") self.image = img self.draw = Draw(img) self.draw.setantialias(True) if size is None: self.size = self.draw.size else: self.size = size if imageType and imageType not in ("png", "jpg"): raise ValueError, "unsupported image type for agg canvas" self.drawType = imageType self.fileName = fileName
def create_pixel_img( self, scale, text, color, ): '''Creats a new canvas and draws text onto it if overridin''' font = Font(self.new_txt_color(color), self.font, self.font_size) bg_color = self.new_bg_color(color) img = Draw('RGB', scale, bg_color) img.text((8, 0), text[:5], font) img.text((8, 10), text[5:10], font) img.text((8, 20), text[10:15], font) img.text((8, 30), text[15:20], font) img.text((8, 40), text[20:], font) return img
def make_marker(radius, fill_color, stroke_color, stroke_width, opacity=1.0): """ Creates a map marker and returns a PIL image. radius In pixels fill_color Any PIL-acceptable color representation, but standard hex string is best stroke_color See fill_color stroke_width In pixels opacity Float between 0.0 and 1.0 """ # Double all dimensions for drawing. We'll resize back to the original # radius for final output -- it makes for a higher-quality image, especially # around the edges radius, stroke_width = radius * 2, stroke_width * 2 diameter = radius * 2 im = Image.new('RGBA', (diameter, diameter)) draw = Draw(im) # Move in from edges half the stroke width, so that the stroke is not # clipped. half_stroke_w = (stroke_width / 2 * 1.0) + 1 min_x, min_y = half_stroke_w, half_stroke_w max_x = diameter - half_stroke_w max_y = max_x bbox = (min_x, min_y, max_x, max_y) # Translate opacity into aggdraw's reference (0-255) opacity = int(opacity * 255) draw.ellipse(bbox, Pen(stroke_color, stroke_width, opacity), Brush(fill_color, opacity)) draw.flush() # The key here is to resize using the ANTIALIAS filter, which is very # high-quality im = im.resize((diameter / 2, diameter / 2), Image.ANTIALIAS) return im
def test_draw(): from aggdraw import Draw from PIL import Image with pytest.raises(AttributeError) as excinfo: Draw("RGB") assert "'str' object has no attribute 'mode'" in str(excinfo.value) draw = Draw("RGB", (800, 600)) assert draw.mode == 'RGB' assert draw.size == (800, 600) draw = Draw("RGB", (800, 600), "white") assert draw.mode == 'RGB' assert draw.size == (800, 600) im = Image.new("RGB", (600, 800)) draw = Draw(im) assert draw.mode == 'RGB' assert draw.size == (600, 800)
async def loading(self): image = Image.new("RGB", (self.width, self.height)) draw = Draw(image) colors = list(self.colors.values()) draw.ellipse((50, 59, 60, 69), Pen(colors[0]), Brush(colors[0])) draw.ellipse((75, 59, 85, 69), Pen(colors[1]), Brush(colors[1])) draw.ellipse((100, 59, 110, 69), Pen(colors[2]), Brush(colors[2])) draw.flush() self.display(image)
def cursor(color=None): dc = Draw("RGBA", [32, 32], (0, 0, 0, 0)) if color is not None: cursor_color = color[0:3] else: cursor_color = [] for c in P.default_fill_color: cursor_color.append(abs(c - 255)) cursor_color = cursor_color[0:3] # coordinate tuples are easier to read/modify but aggdraw needs a stupid x,y,x,y,x,y list cursor_coords = [(6, 0), (6, 27), (12, 21), (18, 32), (20, 30), (15, 20), (23, 20), (6, 0)] cursor_xy_list = [] for point in cursor_coords: cursor_xy_list.append(point[0]) cursor_xy_list.append(point[1]) brush = Brush(tuple(cursor_color), 255) pen = Pen((255, 255, 255), 1, 255) dc.polygon(cursor_xy_list, pen, brush) cursor_surface = aggdraw_to_array(dc) return cursor_surface
def draw(self): rotation = self.rotation center = self.surface_width / 2.0 r = self.radius + 1 for i in range(0, len(self.colors)): brush = Brush(rgb_to_rgba(self.colors[i])) vertices = [center, center] for i in range(0, 4): r_shift = -0.25 if i < 2 else 1.25 r_shift -= rotation func = cos if i % 2 else sin vertices.append(r + r * func(radians(r_shift + 180))) self.surface.polygon(vertices, brush) rotation += 360.0 / len(self.colors) self.surface.flush() # Create annulus mask and apply it to colour disc mask = Image.new('L', (self.surface_width, self.surface_height), 0) d = Draw(mask) xy_1 = center - (self.radius - self.thickness / 2.0) xy_2 = center + (self.radius - self.thickness / 2.0) path_pen = Pen(255, self.thickness) d.ellipse([xy_1, xy_1, xy_2, xy_2], path_pen, self.transparent_brush) d.flush() self.canvas.putalpha(mask) return self.canvas
def _fill_annotations(a: Annotation, label: str, color=0xFF, out=None): if out is None: out = Image.new(mode='L', size=a.image.size) brush = Brush(color) d = Draw(out) d.setantialias(False) for o in a.iter_objects(label): xy = a.points(o) d.polygon(xy.flatten(), brush) return d.flush()
def draw_text(frame, x, y, text, size=16, color='white'): im = Image.fromarray(frame) draw = Draw(im) _, fh = draw.size font = Font(color, os.path.join(os.path.dirname(__file__), './Reith.ttf'), DRAW_SCALE_FACTOR) text_w, text_h = draw.textsize(text, font) y -= text_h draw.text((x + 2, y + 4), text, font) draw.flush() return np.array(im)
def test_graphics2(): """See issue #14.""" from aggdraw import Draw, Symbol, Pen from PIL import Image import numpy as np symbol = Symbol("M400 200 L400 400") pen = Pen("red") image = Image.fromarray(np.zeros((800, 600, 3)), mode="RGB") canvas = Draw(image) canvas.symbol((0, 0), symbol, pen) canvas.flush() assert np.asarray(image).sum() == 50800
def test_path(): from aggdraw import Draw, Path Path() Path([0, 0]) Path([0, 0, 0, 0]) p = Path() p.moveto(0, 0) p.lineto(1, 1) assert p.coords() == [0.0, 0.0, 1.0, 1.0] p.curveto(0, 0, 0, 0, 0, 0) p.close() p.coords() assert p.coords() == [0.0, 0.0, 1.0, 1.0, 0.125, 0.125, 0.0, 0.0] draw = Draw("RGB", (800, 600)) draw.line(p) draw.polygon(p) draw.symbol((0, 0), p)
def circleProgressLeft(self, percent, color): dia = 44 image = Image.new("RGB", (dia + 6, dia + 6)) draw = Draw(image) pen = Pen(self.colors[color], 6) radian = percent * 360 draw.arc((3, 3, dia + 3, dia + 3), 450 - radian, 90, pen) draw.flush() return image
def _stroke_annotations(a: Annotation, label: str, color=0xFF, width=5, out=None): if out is None: out = Image.new(mode='L', size=a.image.size) pen = Pen(color, width) d = Draw(out) d.setantialias(False) # Should not antialias masks for o in a.iter_objects(label): xy = a.points(o) d.polygon(xy.flatten(), pen) return d.flush()
def test_path(): from aggdraw import Draw, Path Path() Path([0, 0]) Path([0, 0, 0, 0]) p = Path() p.moveto(0, 0) p.lineto(1, 1) assert p.coords() == [0.0, 0.0, 1.0, 1.0] p.curveto(2, 1, 2, 1, 2, 0) p.close() p.coords() # Changed test w.r.t. aggdraw for agg 2.4 # Correctness of this may be seen in the file test-path-proof.ps assert p.coords() == [0.0, 0.0, 1.0, 1.0, 1.625, 1.0, 2.0, 0.625, 2.0, 0.0] draw = Draw("RGB", (800, 600)) draw.line(p) draw.polygon(p) draw.symbol((0, 0), p)
def __init__(self, img=None, imageType=None, # determines file type fileName=None, # if set determines output file name size=None, ): if img is None: import Image if size is None: raise ValueError,'please provide either an image or a size' img = Image.new('RGBA',size,"white") self.image = img self.draw = Draw(img) self.draw.setantialias(True) if size is None: self.size = self.draw.size else: self.size = size if imageType and imageType not in ('png','jpg'): raise ValueError,'unsupported image type for agg canvas' self.drawType=imageType self.fileName=fileName
def drift_correct_target(): draw_context_length = P.screen_y // 60 while draw_context_length % 3 != 0: # inner dot should be 1/3 size of target draw_context_length += 1 black_brush = Brush((0, 0, 0, 255)) white_brush = Brush((255, 255, 255, 255)) draw_context = Draw("RGBA", [draw_context_length + 2, draw_context_length + 2], (0, 0, 0, 0)) draw_context.ellipse([0, 0, draw_context_length, draw_context_length], black_brush) wd_top = draw_context_length // 3 # size of the inner white dot of the calibration point wd_bot = 2 * draw_context_length // 3 draw_context.ellipse([wd_top, wd_top, wd_bot, wd_bot], white_brush) return aggdraw_to_array(draw_context)
async def circleProgress(self, percent, text=""): image = Image.new("RGB", (self.width, self.height)) draw = Draw(image) pen = Pen("white", 7) radian = percent * 3.6 draw.arc((50, 34, 110, 94), 450 - radian, 90, pen) draw.flush() imDraw = ImageDraw.Draw(image) if len(text) > 0: text = text.capitalize() w, h = imDraw.textsize(text, font=self.fonts['prompt']) imDraw.text(((self.width - w) / 2, (self.height - h) / 2), text, font=self.fonts['prompt'], align="center", fill="#fff") image = invert(image) self.display(image)
from PIL import Image from aggdraw import Draw, Brush transBlack = (0, 0, 0, 0) # shows your example with visible edges solidBlack = (0, 0, 0, 255) # shows shape on a black background transWhite = (255, 255, 255, 0) solidWhite = (255, 255, 255, 255) im = Image.new("RGBA", (600, 600), solidBlack) draw = Draw(im) brush = Brush("yellow") draw.polygon(( 50, 50, 550, 60, 550, 550, 60, 550, ), None, brush) draw.flush() im.save("squar.png") im.show()
class Canvas(CanvasBase): # fonts appear smaller in aggdraw than with cairo # fix that here: fontScale = 1.2 def __init__(self, img=None, imageType=None, # determines file type fileName=None, # if set determines output file name size=None, ): if img is None: try: import Image except ImportError: from PIL import Image if size is None: raise ValueError('please provide either an image or a size') img = Image.new('RGBA', size, "white") self.image = img self.draw = Draw(img) self.draw.setantialias(True) if size is None: self.size = self.draw.size else: self.size = size if imageType and imageType not in ('png', 'jpg'): raise ValueError('unsupported image type for agg canvas') self.drawType = imageType self.fileName = fileName def _doLine(self, p1, p2, pen, **kwargs): if kwargs.get('dash', (0, 0)) == (0, 0): self.draw.line((p1[0], p1[1], p2[0], p2[1]), pen) else: dash = kwargs['dash'] pts = self._getLinePoints(p1, p2, dash) currDash = 0 dashOn = True while currDash < (len(pts) - 1): if dashOn: p1 = pts[currDash] p2 = pts[currDash + 1] self.draw.line((p1[0], p1[1], p2[0], p2[1]), pen) currDash += 1 dashOn = not dashOn def addCanvasLine(self, p1, p2, color=(0, 0, 0), color2=None, **kwargs): if color2 and color2 != color: mp = (p1[0] + p2[0]) / 2., (p1[1] + p2[1]) / 2. color = convertColor(color) self._doLine(p1, mp, Pen(color, kwargs.get('linewidth', 1)), **kwargs) color2 = convertColor(color2) self._doLine(mp, p2, Pen(color2, kwargs.get('linewidth', 1)), **kwargs) else: color = convertColor(color) self._doLine(p1, p2, Pen(color, kwargs.get('linewidth', 1)), **kwargs) def addCanvasText(self, text, pos, font, color=(0, 0, 0), **kwargs): orientation = kwargs.get('orientation', 'E') color = convertColor(color) aggFont = Font(color, faceMap[font.face], size=font.size * self.fontScale) blocks = list(re.finditer(r'\<(.+?)\>(.+?)\</\1\>', text)) w, h = 0, 0 supH = 0 subH = 0 if not len(blocks): w, h = self.draw.textsize(text, aggFont) tw, th = w, h offset = w * pos[2] dPos = pos[0] - w / 2. + offset, pos[1] - h / 2. self.draw.text(dPos, text, aggFont) else: dblocks = [] idx = 0 for block in blocks: blockStart, blockEnd = block.span(0) if blockStart != idx: # untagged text: tblock = text[idx:blockStart] tw, th = self.draw.textsize(tblock, aggFont) w += tw h = max(h, th) dblocks.append((tblock, '', tw, th)) fmt = block.groups()[0] tblock = block.groups()[1] if fmt in ('sub', 'sup'): lFont = Font(color, faceMap[font.face], size=0.8 * font.size * self.fontScale) else: lFont = aggFont tw, th = self.draw.textsize(tblock, lFont) w += tw if fmt == 'sub': subH = max(subH, th) elif fmt == 'sup': supH = max(supH, th) else: h = max(h, th) dblocks.append((tblock, fmt, tw, th)) idx = blockEnd if idx != len(text): # untagged text: tblock = text[idx:] tw, th = self.draw.textsize(tblock, aggFont) w += tw h = max(h, th) dblocks.append((tblock, '', tw, th)) supH *= 0.5 subH *= 0.5 h += supH + subH offset = w * pos[2] if orientation == 'W': dPos = [pos[0] - w + offset, pos[1] - h / 2.] elif orientation == 'E': dPos = [pos[0] + offset, pos[1] - h / 2.] else: dPos = [pos[0] - w / 2. + offset, pos[1] - h / 2.] if supH: dPos[1] += supH for txt, fmt, tw, th in dblocks: tPos = dPos.copy() if fmt == 'sub': tPos[1] += subH elif fmt == 'sup': tPos[1] -= supH if fmt in ('sub', 'sup'): lFont = Font(color, faceMap[font.face], size=0.8 * font.size * self.fontScale) else: lFont = aggFont self.draw.text(tPos, txt, lFont) dPos[0] += tw return (tw + th * .4, th + th * .4, offset) def addCanvasPolygon(self, ps, color=(0, 0, 0), fill=True, stroke=False, **kwargs): if not fill and not stroke: return dps = [] for p in ps: dps.extend(p) color = convertColor(color) brush = None pen = None if fill: brush = Brush(color) if stroke: pen = Pen(color) self.draw.polygon(dps, pen, brush) def addCanvasDashedWedge(self, p1, p2, p3, dash=(2, 2), color=(0, 0, 0), color2=None, **kwargs): pen = Pen(color, kwargs.get('linewidth', 1)) dash = (3, 3) pts1 = self._getLinePoints(p1, p2, dash) pts2 = self._getLinePoints(p1, p3, dash) if len(pts2) < len(pts1): pts2, pts1 = pts1, pts2 for i in range(len(pts1)): self.draw.line((pts1[i][0], pts1[i][1], pts2[i][0], pts2[i][1]), pen) def flush(self): self.draw.flush() if self.fileName: self.image.save(self.fileName)
def draw(self): ''' Render the image. Assumes that set_data has already been called. Returns a Python Image Library (PIL) Image object. ''' img = Image.new('RGB', (self.width, self.height), self.bgcol) canvas = Draw(img) # create the projection. Here we use an equidistant cylindrical projection, # but others may work with tweaking of the parameters. proj = Proj(proj=self.proj, a=self.width/(2*pi), # set the radius of the earth such that our # projections work x_0=self.width/2, # center horizontally on the image y_0=self.height/2) # center verticallly on the image # two branches below will use the same sequence of commands to # draw a great-circle on the map, so the common elements are wrapped # up into a locally defined function. Given a matrix of points and # a pen, draw the path through the points. def draw_(pts, pen): lons, lats = pts.T x, y = proj(lons, lats) y = self.height - y path = reduce(operator.add, zip(x, y)) canvas.line(path, pen) # loop over every coordinate pair for i, (lon1, lat1, lon2, lat2) in enumerate(self.data[self.order]): # calculate the fraction of the paths already drawn, and use # it to create a pen of the appropriate color frac = i / float(self.data_size) pen = Pen(self.cols(frac), self.line_width) # find the intermediate coordinates along a line between the two # coordinates pts = self.geo.npts(lon1, lat1, lon2, lat2, self.gc_resolution) pts = np.array(pts) # if the longitudinal distance between the two points (travelling # through the prime meridian) is more than 180 degrees, it's faster # to *not* travel through the prime meridian, so we have to special- # case the drawing of the lines. if abs(lon1 - lon2) >= HALF_ROTATION: # find the index of the path where the line wraps around the image (cut_point,), = np.where(np.abs(np.diff(pts[:,0])) > HALF_ROTATION) # draw the two resultant lines separately pts1 = pts[:cut_point+1,:] pts2 = pts[cut_point+1:,:] # plot one point after the break on each sides so that the # paths go to the edge of the screen x1, y1 = pts[cut_point+2, :] x2, y2 = pts[cut_point+1, :] if x1 > 0: pts1 = np.vstack((pts1, [-HALF_ROTATION, y1])) pts2 = np.vstack(([HALF_ROTATION, y2], pts2)) else: pts1 = np.vstack((pts1, [HALF_ROTATION, y1])) pts2 = np.vstack(([-HALF_ROTATION, y2], pts2)) draw_(pts1, pen) draw_(pts2, pen) else: # the path does not wrap the image, so we can simply draw # it as-is draw_(pts, pen) canvas.flush() return img
class Canvas(CanvasBase): # fonts appear smaller in aggdraw than with cairo # fix that here: fontScale=1.2 def __init__(self, img=None, imageType=None, # determines file type fileName=None, # if set determines output file name size=None, ): if img is None: import Image if size is None: raise ValueError,'please provide either an image or a size' img = Image.new('RGBA',size,"white") self.image = img self.draw = Draw(img) self.draw.setantialias(True) if size is None: self.size = self.draw.size else: self.size = size if imageType and imageType not in ('png','jpg'): raise ValueError,'unsupported image type for agg canvas' self.drawType=imageType self.fileName=fileName def _doLine(self, p1, p2, pen, **kwargs): if kwargs.get('dash',(0,0)) == (0,0): self.draw.line((p1[0],p1[1],p2[0],p2[1]),pen) else: dash = kwargs['dash'] pts = self._getLinePoints(p1,p2,dash) currDash = 0 dashOn = True while currDash<(len(pts)-1): if dashOn: p1 = pts[currDash] p2 = pts[currDash+1] self.draw.line((p1[0],p1[1],p2[0],p2[1]),pen) currDash+=1 dashOn = not dashOn def addCanvasLine(self, p1, p2, color=(0,0,0), color2=None, **kwargs): if color2 and color2!=color: mp = (p1[0]+p2[0])/2.,(p1[1]+p2[1])/2. color = convertColor(color) self._doLine(p1,mp,Pen(color,kwargs.get('linewidth',1)),**kwargs) color2 = convertColor(color2) self._doLine(mp,p2,Pen(color2,kwargs.get('linewidth',1)),**kwargs) else: color = convertColor(color) self._doLine(p1,p2,Pen(color,kwargs.get('linewidth',1)),**kwargs) def addCanvasText(self,text,pos,font,color=(0,0,0),**kwargs): orientation=kwargs.get('orientation','E') color = convertColor(color) aggFont = Font(color,faceMap[font.face],size=font.size*self.fontScale) blocks = list(re.finditer(r'\<(.+?)\>(.+?)\</\1\>',text)) w,h = 0,0 supH=0 subH=0 if not len(blocks): w,h=self.draw.textsize(text,aggFont) bw,bh=w*1.1,h*1.1 dPos = pos[0]-bw/2.,pos[1]-bh/2. bgColor=kwargs.get('bgColor',(1,1,1)) bgColor = convertColor(bgColor) self.draw.rectangle((dPos[0],dPos[1],dPos[0]+bw,dPos[1]+bh), None,Brush(bgColor)) dPos = pos[0]-w/2.,pos[1]-h/2. self.draw.text(dPos,text,aggFont) else: dblocks=[] idx=0 for block in blocks: blockStart,blockEnd=block.span(0) if blockStart != idx: # untagged text: tblock = text[idx:blockStart] tw,th=self.draw.textsize(tblock,aggFont) w+=tw h = max(h,th) dblocks.append((tblock,'',tw,th)) fmt = block.groups()[0] tblock = block.groups()[1] if fmt in ('sub','sup'): lFont = Font(color,faceMap[font.face],size=0.8*font.size*self.fontScale) else: lFont = aggFont tw,th=self.draw.textsize(tblock,lFont) w+=tw if fmt == 'sub': subH = max(subH,th) elif fmt=='sup': supH = max(supH,th) else: h = max(h,th) dblocks.append((tblock,fmt,tw,th)) idx = blockEnd if idx!=len(text): # untagged text: tblock = text[idx:] tw,th=self.draw.textsize(tblock,aggFont) w+=tw h = max(h,th) dblocks.append((tblock,'',tw,th)) supH *= 0.25 subH *= 0.25 h += supH + subH bw,bh=w*1.1,h #dPos = pos[0]-bw/2.,pos[1]-bh/2. dPos = [pos[0]-w/2.,pos[1]-h/2.] if orientation=='W': dPos = [pos[0]-w,pos[1]-h/2.] elif orientation=='E': dPos = [pos[0],pos[1]-h/2.] else: dPos = [pos[0]-w/2,pos[1]-h/2.] bgColor=kwargs.get('bgColor',(1,1,1)) bgColor = convertColor(bgColor) self.draw.rectangle((dPos[0],dPos[1],dPos[0]+bw,dPos[1]+bh), None,Brush(bgColor)) if supH: dPos[1]+=supH for txt,fmt,tw,th in dblocks: tPos = dPos[:] if fmt=='sub': tPos[1]+=subH elif fmt=='sup': tPos[1]-=supH if fmt in ('sub','sup'): lFont = Font(color,faceMap[font.face],size=0.8*font.size*self.fontScale) else: lFont = aggFont self.draw.text(tPos,txt,lFont) dPos[0]+=tw def addCanvasPolygon(self,ps,color=(0,0,0),fill=True,stroke=False,**kwargs): if not fill and not stroke: return dps = [] for p in ps: dps.extend(p) color = convertColor(color) brush=None pen=None if fill: brush = Brush(color) if stroke: pen = Pen(color) self.draw.polygon(dps,pen,brush) def addCanvasDashedWedge(self,p1,p2,p3,dash=(2,2),color=(0,0,0), color2=None,**kwargs): pen = Pen(color,kwargs.get('linewidth',1)) dash = (3,3) pts1 = self._getLinePoints(p1,p2,dash) pts2 = self._getLinePoints(p1,p3,dash) if len(pts2)<len(pts1): pts2,pts1=pts1,pts2 for i in range(len(pts1)): self.draw.line((pts1[i][0],pts1[i][1],pts2[i][0],pts2[i][1]),pen) def flush(self): self.draw.flush() if self.fileName: self.image.save(self.fileName)
from PIL import Image from aggdraw import Draw, Brush transBlack = (0, 0, 0, 0) # shows your example with visible edges solidBlack = (0, 0, 0, 255) # shows shape on a black background transWhite = (255, 255, 255, 0) solidWhite = (255, 255, 255, 255) im = Image.new("RGBA", (600, 600), solidBlack) draw = Draw(im) brush = Brush("yellow") draw.polygon( ( 50, 50, 550, 60, 550, 550, 60, 550, ), None, brush ) draw.flush() im.save("squar.png") im.show()
def test_graphics(): from aggdraw import Draw, Pen, Brush draw = Draw("RGB", (500, 500)) pen = Pen("black") brush = Brush("black") draw.line((50, 50, 100, 100), pen) draw.rectangle((50, 150, 100, 200), pen) draw.rectangle((50, 220, 100, 270), brush) draw.rectangle((50, 290, 100, 340), brush, pen) draw.rectangle((50, 360, 100, 410), pen, brush) draw.ellipse((120, 150, 170, 200), pen) draw.ellipse((120, 220, 170, 270), brush) draw.ellipse((120, 290, 170, 340), brush, pen) draw.ellipse((120, 360, 170, 410), pen, brush) draw.polygon((190+25, 150, 190, 200, 190+50, 200), pen) draw.polygon((190+25, 220, 190, 270, 190+50, 270), brush) draw.polygon((190+25, 290, 190, 340, 190+50, 340), brush, pen) draw.polygon((190+25, 360, 190, 410, 190+50, 410), pen, brush)
def test_flush(): from aggdraw import Draw from PIL import Image im = Image.new("RGB", (600, 800)) draw = Draw(im) assert draw.flush().mode == 'RGB'
def test_transform(): from aggdraw import Draw draw = Draw("RGB", (500, 500)) draw.settransform() draw.settransform((250, 250)) draw.settransform((1, 0, 250, 0, 1, 250)) draw.settransform((2.0, 0.5, 250, 0.5, 2.0, 250)) draw.settransform()