from PIL import Image
import numpy as np
# 中点直线法
def MidPointLine(x1, y1, x2, y2): # 传入两个点(x1,y1)和(x2,y2),画出通过这两点的直线
tag = 0
dx = x2 - x1 # x的距离
dy = y2 - y1 # y的距离
if abs(dx) < abs(dy): # 如果 |k| >1 ,坐标互换
x1, y1 = y1, x1 # 坐标互换
x2, y2 = y2, x2 # 坐标互换
tag = 1
if x1 > x2: # 确保x1 < x2
x1, x2 = x2, x1 # 坐标互换
y1, y2 = y2, y1 # 坐标互换
a = y1 - y2
b = x2 - x1
d = a + (b / 2) # d为中点带入到直线方程的值
if y1 < y2: # 斜率 > 0
x = x1 # 初始点的x坐标
y = y1 # 初始点的y坐标
while x < x2: # 没画到最后
if d < 0: # 中点位于直线下方
x = x + 1 # 直线靠近(x+1,y+1),所以y要加一
y = y + 1 # 直线靠近(x+1,y+1),所以x要加一
d = d + a + b
else: # 中点位于直线上方
x = x + 1 # 直线靠近(x+1,y),所以x要加一
d = d + a
if tag: # 斜率 > 1
img[x, y] = 1
else:
img[y, x] = 1
else: # 斜率 <= 0
x = x2 # 初始点的x坐标
y = y2 # 初始点的y坐标
while x > x1: # 没画到最后
if d < 0: # 中点位于直线下方
y = y + 1 # 直线靠近(x-1,y+1),所以y要加一
x = x - 1 # 直线靠近(x-1,y+1),所以x要减一
d = d - a + b
else: # 中点位于直线上方
x = x - 1 # 直线靠近(x-1,y),所以x要减一
d = d - a
if tag:
img[x, y] = 1
else:
img[y, x] = 1
# Bresenham算法
def Bresenham(x1, y1, x2, y2):
dx = abs(x2 - x1) # 水平偏移量
dy = abs(y2 - y1) # 垂直偏移量
sx = 1 if x2 > x1 else -1 # 每次的增量
sy = 1 if y2 > y1 else -1 # 每次的增量
erro = dx / 2 if dx > dy else -dy / 2
while x1 != x2 or y1 != y2: # 没画到最后
img[y1, x1] = 1
e2 = erro
if e2 > -dx:
erro -= dy
x1 += sx # 下一个点是(x+sx,y)
if e2 < dy:
erro += dx
y1 += sy # 下一个点是(x,y+sy)
# 中点圆算法
def Circle_Midpoint(x0, y0, r): # 输入圆心和半径
tx = 0
ty = r
d = 1.25 - r # 初始点在(0,r)
while tx <= ty:
# 利用圆的八分对称性画点
img[y0 + tx, x0 + ty] = 1
img[y0 + tx, x0 - ty] = 1
img[y0 - tx, x0 + ty] = 1
img[y0 - tx, x0 - ty] = 1
img[y0 + ty, x0 + tx] = 1
img[y0 + ty, x0 - tx] = 1
img[y0 - ty, x0 + tx] = 1
img[y0 - ty, x0 - tx] = 1
if d < 0: # 当d<0时,下一个点是(x,y-1)
d += 2 * tx + 3
else: # 当d>=0时,下一个点是(x,y-1)
d += 2 * (tx - ty) + 5
ty -= 1
tx += 1
# 中点圆算法(画半圆)
def Circle_Midpoint2(x0, y0, r): # 输入圆心和半径
tx = 0
ty = r
d = 1.25 - r # 初始点在(0,r)
while tx <= ty:
# 利用圆的八分对称性画点
img[y0 + tx, x0 + ty] = 1
img[y0 + tx, x0 - ty] = 1
img[y0 + ty, x0 + tx] = 1
img[y0 + ty, x0 - tx] = 1
if d < 0: # 当d<0时,下一个点是(x,y-1)
d += 2 * tx + 3
else: # 当d>=0时,下一个点是(x,y-1)
d += 2 * (tx - ty) + 5
ty -= 1
tx += 1
# 中点圆算法(画上半圆)
def Circle_Midpoint3(x0, y0, r): # 输入圆心和半径
tx = 0
ty = r
d = 1.25 - r # 初始点在(0,r)
while tx <= ty:
# 利用圆的八分对称性画点
img[y0 - tx, x0 + ty] = 1
img[y0 - tx, x0 - ty] = 1
img[y0 - ty, x0 + tx] = 1
img[y0 - ty, x0 - tx] = 1
if d < 0: # 当d<0时,下一个点是(x,y-1)
d += 2 * tx + 3
else: # 当d>=0时,下一个点是(x,y-1)
d += 2 * (tx - ty) + 5
ty -= 1
tx += 1
def Circle_Midpoint4(x0, y0, r): # 输入圆心和半径
tx = 0
ty = r
d = 1.25 - r # 初始点在(0,r)
while tx <= ty:
# 利用圆的八分对称性画点
img[y0 + tx, x0 + ty] = 1 # 绘制像素点
if d < 0: # 当d<0时,下一个点是(x,y-1)
d += 2 * tx + 3
else: # 当d>=0时,下一个点是(x,y-1)
d += 2 * (tx - ty) + 5
ty -= 1
tx += 1
def Circle_Midpoint5(x0, y0, r): # 输入圆心和半径
tx = 0
ty = r
d = 1.25 - r # 初始点在(0,r)
while tx <= ty:
# 利用圆的八分对称性画点
img[y0 - tx, x0 + ty] = 1
if d < 0: # 当d<0时,下一个点是(x,y-1)
d += 2 * tx + 3
else: # 当d>=0时,下一个点是(x,y-1)
d += 2 * (tx - ty) + 5
ty -= 1
tx += 1
def Circle_Midpoint6(x0, y0, r): # 输入圆心和半径
tx = 0
ty = r
d = 1.25 - r # 初始点在(0,r)
while tx <= ty:
# 利用圆的八分对称性画点
img[y0 + tx, x0-ty] = 1
img[y0 - tx, x0-ty] = 1
if d < 0: # 当d<0时,下一个点是(x,y-1)
d += 2 * tx + 3
else: # 当d>=0时,下一个点是(x,y-1)
d += 2 * (tx - ty) + 5
ty -= 1
tx += 1
def Circle_Midpoint7(x0, y0, r): # 输入圆心和半径
tx = 0
ty = r
d= 1.25-r # 初始点在(0,r)
while tx <= ty:
# 利用圆的八分对称性画点
img[y0 - tx, x0 + ty] = 1 # 绘制像素点
img[y0 - tx, x0 - ty] = 1 # 绘制像素点
d=d+ 2 * tx + 3
else: # 当d>=0时,下一个点是(x,y-1)
d += 2 * (tx - ty) + 5
ty -= 1
tx += 1
def Circle_Midpoint8(x0, y0, r): # 输入圆心和半径
tx = 0
ty = r
d = 1.25 - r # 初始点在(0,r)
while tx <= ty:
# 利用圆的八分对称性画点
img[y0 - tx, x0 - ty] = 1 # 绘制像素点
if d < 0: # 当d<0时,下一个点是(x,y-1)
d += 2 * tx + 3
else: # 当d>=0时,下一个点是(x,y-1)
d += 2 * (tx - ty) + 5
ty -= 1
tx += 1
def draw(x, y):
Circle_Midpoint2(int(x / 2), int(y / 2) +100, 150) # 身体的下半个圆
Bresenham(int(x / 2) -150, int(y / 2) - 150, int(x / 2) -150, int(y / 1.36)-80) # 左边身体的直线
Bresenham(int(x / 2)+150, int(y / 2) - 150, int(x / 2)+150, int(y / 1.36)-80 ) # 右边身体的直线
Circle_Midpoint3(int(x / 2), int(y / 2) -150, 150) # 身体的上半个圆
Circle_Midpoint(int(x / 1.75)-20, int(y / 2.8), 40) # 右眼睛
Circle_Midpoint(int(x / 2.3)-20, int(y / 2.8), 40) # 左眼
for i in range(17, 21):
Circle_Midpoint(int(x / 1.75), int(y / 2.8), i)
Circle_Midpoint(int(x / 2.3), int(y / 2.8), i)
Circle_Midpoint2(int(x / 2)-10, int(y / 2) -50, 50) # 身体的下半个圆
# 小胳膊
Bresenham(int(x / 2) + 150, int(y / 2) - 20, int(x / 2) + 200, int(y / 2) + 40)
Bresenham(int(x / 2) - 150, int(y / 2) - 20, int(x / 2) - 200, int(y / 2) + 40)
Bresenham(int(x / 2) + 200, int(y / 2) + 40, int(x / 2) + 150, int(y / 2) + 100)
Bresenham(int(x / 2) - 200, int(y / 2) + 40, int(x / 2) - 150, int(y / 2) + 100)
# 小腿
Bresenham(int(x / 2) - 70, int(y / 1.36) + 47, int(x / 2) - 70, int(y / 1.36) + 100) # 左腿
Bresenham(int(x / 2) - 50, int(y / 1.36) + 52, int(x / 2) - 50, int(y / 1.36) + 120)
Bresenham(int(x / 2) - 50, int(y / 1.36) + 120, int(x / 2) - 100, int(y / 1.36) + 120)
Bresenham(int(x / 2) - 70, int(y / 1.36) + 100, int(x / 2) - 100, int(y / 1.36) + 100)
Circle_Midpoint5(int(x / 2) + 90, int(y / 2) + 310, 30) # 右边的鞋
Circle_Midpoint6(int(x / 2) - 90, int(y / 2) + 298, 15) # 左边的鞋
Bresenham(int(x / 2) + 70, int(y / 1.36) + 47, int(x / 2) + 70, int(y / 1.36) + 100) # 右腿
Bresenham(int(x / 2) + 50, int(y / 1.36) + 52, int(x / 2) + 50, int(y / 1.36) + 120)
Bresenham(int(x / 2) + 50, int(y / 1.36) + 120, int(x / 2) + 117, int(y / 1.36) + 120)
Bresenham(int(x / 2) + 70, int(y / 1.36) + 100, int(x / 2) + 110, int(y / 1.36) + 100)
# 头发
Circle_Midpoint4(int(x / 2) - 250, int(y / 2) - 395, 200) # 左边那根毛
Circle_Midpoint8(int(x / 2) + 250, int(y / 2) - 290, 200) # 右毛
Bresenham(int(x / 2) , int(y / 1.36) -580, int(x / 2), int(y / 1.36) -490) # 中间毛
Bresenham(int(x / 2) -80, int(y / 1.36)-150 ,int( x / 2) + 80, int(y / 1.36)-150 ) # 衣服
Bresenham(int(x / 2) - 80, int(y / 1.36) - 150, int(x / 2) - 80, int(y / 1.36)-50) # 衣服左边那个竖
Bresenham(int(x / 2) + 80, int(y / 1.36) - 150, int(x / 2) + 80, int(y / 1.36) - 50) # 衣服右边那个竖
Bresenham(int(x / 2) - 147, int(y / 1.36) - 50, int(x / 2) -80, int(y / 1.36) - 50) # 衣服下面那个左横线
Bresenham(int(x / 2) + 147, int(y / 1.36) - 50, int(x / 2)+ 80, int(y / 1.36) - 50) # 衣服下面那个右横线
Bresenham(int(x / 2) - 50, int(y / 1.36) - 115, int(x / 2) +50, int(y / 1.36) - 115) # 小口袋的横线
Circle_Midpoint2(int(x / 2), int(y / 2) +75, 50) # 口袋的下半个圆
Bresenham(int(x / 2) -150, int(y / 1.36) -255, int(x / 2) -80, int(y / 1.36)-150) # 背带裤的左带子
Bresenham(int(x / 2)+150, int(y / 1.36) - 255, int(x / 2) +80, int(y / 1.36)-150 ) # 背带裤的左带子
if __name__ == '__main__':
high = 800 # 画布的宽
width = 800 # 画布的高
img = np.zeros([high, width])
for i in range(high): # 白色图片
for j in range(width):
img[i, j] = 250
draw(high, width) # 绘图
#Circle_Bresenham(100,100,50)
img = Image.fromarray(img.astype('uint8')).convert('RGB')
img.show()
用Python画小黄人
于 2023-06-07 11:36:42 首次发布