def round_corner_jpg(image, radius): """Round a JPG image""" mask = Image.new('L', image.size) draw = Draw(mask) brush = Brush('white') width, height = mask.size draw.pieslice((0, 0, radius * 2, radius * 2), 90, 180, None, brush) draw.pieslice((width - radius * 2, 0, width, radius * 2), 0, 90, None, brush) draw.pieslice((0, height - radius * 2, radius * 2, height), 180, 270, None, brush) draw.pieslice((width - radius * 2, height - radius * 2, width, height), 270, 360, None, brush) draw.rectangle((radius, radius, width - radius, height - radius), brush) draw.rectangle((radius, 0, width - radius, radius), brush) draw.rectangle((0, radius, radius, height - radius), brush) draw.rectangle((radius, height - radius, width - radius, height), brush) draw.rectangle((width - radius, radius, width, height - radius), brush) draw.flush() image = image.convert('RGBA') image.putalpha(mask) return image
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)
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)
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)