用 PIL 绘制二次贝塞尔曲线

PIL(Python Image Library) 中有 line, ellipse, rectangle 等常规绘图的函数,但缺少绘制曲线的函数,今天我的需求中需要绘制一个二次贝塞尔曲线(两个端点,一个控制点)。无奈之下,到网上找了一个 c 语言写的算法,把它写成了 python 的,并且写成了类的形式。

# coding=utf-8
#
 二次贝塞尔曲线绘图程序
#
 木野狐(Neil Chen) http://rchen.cnblogs.com
#
 2007-5-16
#
 根据 c 程序改写为 python 类的形式,参考:
#
 http://hi.baidu.com/sunyante/blog/item/2627d911b3061810b8127b70.html

from  math  import  sqrt
import  Image, ImageDraw

class  Bezier2(object):
    
def   __init__ (self, draw, points, line_width, line_color):
        self.draw 
=  draw
        self.points 
=  points
        self.line_width 
=  line_width
        self.line_color 
=  line_color
        self.current_point 
=  (0, 0)

    
def  moveto(self, p):
        self.current_point 
=  p
    
    
def  lineto(self, p):
        self.draw.line((self.current_point, p), width
= self.line_width, fill = self.line_color)
        self.current_point 
=  p

    
def  render(self):
        NO 
=   3
        KT 
=   5
        m 
=  NO  -   1
        p 
=  {}  #  p[3][2]
         for  i  in  range(0, NO,  2 ):
            p[i] 
=  self.points[i]
        
        l1 
=   1.0   *  (self.points[0][0]  -  self.points[ 1 ][0])
        ll 
=   1.0   *  (self.points[0][ 1 -  self.points[ 1 ][ 1 ])
        l1 
=  sqrt(l1  *  l1  +  ll  *  ll)
        
        l2 
=   1.0   *  (self.points[ 2 ][0]  -  self.points[ 1 ][0])
        ll 
=   1.0   *  (self.points[ 2 ][ 1 -  self.points[ 1 ][ 1 ])
        l2 
=  sqrt(l2  *  l2  +  ll  *  ll)
        
        p[
1 =  (
            ((l1 
+  l2)  *  (l1  +  l2)  *  self.points[ 1 ][0]  -  l2  *  l2  *  self.points[0][0]  -  l1  *  l1  *  self.points[ 2 ][0])  /  ( 2   *  l1  *  l2),
            ((l1 
+  l2)  *  (l1  +  l2)  *  self.points[ 1 ][ 1 -  l2  *  l2  *  self.points[0][ 1 -  l1  *  l1  *  self.points[ 2 ][ 1 ])  /  ( 2   *  l1  *  l2)
        )
        
'''
        # 画出切线
        self.moveto(p[0])
        for i in range(1, m+1):
            self.lineto(p[i])
        
'''
        
        pk 
=  {}   #  pk[129][2]
         for  i  in  range(m  +   1 ):
            pk[i] 
=  p[i]
        
        pt 
=  {}  #  pt[129][2]
         for  k  in  range(KT  +   1 ):
            
for  i  in  range(0, m  +   1 2 ):
                pt[
2 * i]  =  pk[i]
            
for  i  in  range(m):
                pt[
2 * +   1 =  (
                    int(pk[i][0] 
+  pk[i + 1 ][0])  >>   1 ,
                    int(pk[i][
1 +  pk[i + 1 ][ 1 ])  >>   1
                )
            
for  i  in  range( 1 , m):
                pt[
2 * i]  =  (
                    int(pt[
2 * i - 1 ][0]  +  pt[ 2 * i + 1 ][0])  >>   1 ,
                    int(pt[
2 * i - 1 ][ 1 +  pt[ 2 * i + 1 ][ 1 ])  >>   1
                )
            
for  i  in  range( 2 * +   1 ):
                pk[i] 
=  pt[i]
            
            
if  k  ==  KT:
                
break
            m 
<<=   1
        self.moveto(pk[0])
        
for  i  in  range( 1 2 * +   1 ):
            self.lineto(pk[i])

#  测试代码
if   __name__   ==   ' __main__ ' :
    im 
=  Image.new( ' RGBA ' , ( 1024 , 1024 ), ( 255 , 255 , 255 ))
    draw 
=  ImageDraw.Draw(im)

    points 
=  (( 150 , 300 ), ( 300 , 200 ), ( 485 , 300 ))
    b 
=  Bezier2(draw, points,  1 , (0,0, 255 ))
    b.render()
    
    points2 
=  (( 150 , 300 ), ( 100 , 400 ), ( 485 , 300 ))
    b2 
=  Bezier2(draw, points2,  3 , (0, 255 ,0))
    b2.render()
    
    
del  draw
    im.show()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值