Python Imaging Library (PIL) Drawing--Rounded rectangle with gradient

后端 未结 3 1649
半阙折子戏
半阙折子戏 2020-12-16 23:25

I am trying to use PIL to draw a rectangle with rounded corners and a gradient fill for the color. I found a cool web site ( http://web.archive.org/web/20130306020911/http:/

3条回答
  •  清歌不尽
    2020-12-17 00:07

    This is a very brute force method, but it gets the job done. Code to produce the gradients was borrowed from here.

    from PIL import Image, ImageDraw
    
    def channel(i, c, size, startFill, stopFill):
        """calculate the value of a single color channel for a single pixel"""
        return startFill[c] + int((i * 1.0 / size) * (stopFill[c] - startFill[c]))
    
    def color(i, size, startFill, stopFill):
        """calculate the RGB value of a single pixel"""
        return tuple([channel(i, c, size, startFill, stopFill) for c in range(3)])
    
    def round_corner(radius):
        """Draw a round corner"""
        corner = Image.new('RGBA', (radius, radius), (0, 0, 0, 0))
        draw = ImageDraw.Draw(corner)
        draw.pieslice((0, 0, radius * 2, radius * 2), 180, 270, fill="blue")
        return corner
    
    def apply_grad_to_corner(corner, gradient, backwards = False, topBottom = False):
        width, height = corner.size
        widthIter = range(width)
    
        if backwards:
            widthIter.reverse()
    
        for i in xrange(height):
            gradPos = 0
        for j in widthIter:
                    if topBottom:
                        pos = (i,j)
                    else:
                        pos = (j,i)
            pix = corner.getpixel(pos)
                gradPos+=1
            if pix[3] != 0:
                corner.putpixel(pos,gradient[gradPos])
    
        return corner
    
    def round_rectangle(size, radius, startFill, stopFill, runTopBottom = False):
        """Draw a rounded rectangle"""
        width, height = size
        rectangle = Image.new('RGBA', size)
    
        if runTopBottom:
          si = height
        else:
          si = width
    
        gradient = [ color(i, width, startFill, stopFill) for i in xrange(si) ]
    
        if runTopBottom:
            modGrad = []
            for i in xrange(height):
               modGrad += [gradient[i]] * width
            rectangle.putdata(modGrad)
        else:
            rectangle.putdata(gradient*height)
    
        origCorner = round_corner(radius)
    
        # upper left
        corner = origCorner
        apply_grad_to_corner(corner,gradient,False,runTopBottom)
        rectangle.paste(corner, (0, 0))
    
        # lower left
        if runTopBottom: 
            gradient.reverse()
            backwards = True
        else:
            backwards = False
    
    
        corner = origCorner.rotate(90)
        apply_grad_to_corner(corner,gradient,backwards,runTopBottom)
        rectangle.paste(corner, (0, height - radius))
    
        # lower right
        if not runTopBottom: 
            gradient.reverse()
    
        corner = origCorner.rotate(180)
        apply_grad_to_corner(corner,gradient,True,runTopBottom)
        rectangle.paste(corner, (width - radius, height - radius))
    
        # upper right
        if runTopBottom: 
            gradient.reverse()
            backwards = False
        else:
            backwards = True
    
        corner = origCorner.rotate(270)
        apply_grad_to_corner(corner,gradient,backwards,runTopBottom)
        rectangle.paste(corner, (width - radius, 0))
    
        return rectangle
    
    img = round_rectangle((200, 200), 70, (255,0,0), (0,255,0), True)
    img.save("test.png", 'PNG')
    

    Running from left to right (runTopBottom = False):

    enter image description here

    Running from top to bottom (runTopBottom = True):

    enter image description here

提交回复
热议问题