Python 暴力绘制RGB三色图 Pygame框架下实例

Python 暴力绘制RGB三色图 Pygame框架下


昨天水群,有个群友想要绘制一个三色图,如下
在这里插入图片描述

对于Pygame或者其他的GUI框架,画面显示都是依靠图像的一层层覆盖来实现刷新的。所以当绿色的圆覆盖蓝色的圆时,颜色不会想象中的叠加。
最开始的想法是(未实现,具体实现方法请下翻),根据三色叠加的原理,依次绘制三个圆,判断叠加区域,叠加区域的色彩值=(R1+R2, G1+G2, B1+B2),例如蓝色(0,0,255)与红色(255,0,0)叠加,最终色彩值为(255,0,255)。同理,中间白色区域就是三个颜色的叠加,最终为(255,255,255)也就是白色。
在这里插入图片描述
具体方法如上图,每次绘制后建立一个surface的副本,然后再绘制下一个圆,接着依次对比原surface,找出颜色改变的地方,并且此点原先不能为白色。从而判断这个点就所处在叠加区域,接着在将原点的RGB与现点的RGB相加,即可做到颜色的叠加。
在这里插入图片描述
在这里插入图片描述

但是这种方法想想都头疼,也没创建过surface副本的经验。正在准备硬着头皮上时,有个群友说“这个时候肯定要用数学知识呀,数学总是在该用时想不到”,是啊,确实,用数学方法应该是个不错的办法。

那么就来考虑新办法,但是接下来那个群友的数学方法就比较复杂了,他打算以中间白色区域构成一个等边三角形,然后画弧,具体的我也没太了解,但是看起来也比较复杂。

(最后实现方法)

我的想法是,遍历所有像素点,判断该点与三个圆心的距离,如果距离小于圆的半径,则该点在此圆内,给予该点相应色彩值,如果同时在两个圆内,那么该点相应色彩值就是两个圆颜色的叠加后应有的颜色,同理三个圆(所以说暴力硬算,不过那是电脑该干的了。

说干就干。

  1. 引入pygame模块,并初始化
import pygame
from pygame import *
pygame.init()
  1. 确定三个圆的圆心坐标,及半径值,简要在图中画出其所在位置
circle = [(200, 100), (150, 200), (250, 200)]
r = 100	# 三个圆半径相同,都为 r

for i in circle:
    pygame.draw.circle(window, (255, 255, 255), i, r, 10)
  1. 创建数组,用来判断三个圆对该点的包含情况,初始值都为False
in_circle = [False, False, False]
  1. 开始遍历,核心部分
for y in range(0, 400):  # 对于屏幕 y方向各像素
    for x in range(0, 400):	# 对于屏幕 x方向各像素
        in_circle = [False, False, False]	# 对于遍历的每个点,都恢复 包含情况 的初始值
        for i in range(3):	# 遍历三个圆
            if ((circle[i][0] - x)**2 + (circle[i][1] - y)**2) <= r*r:
            	# (x2-x1)^2 + (y2-y1)^2 <= r^2	两点距离公式,小于圆的半径
                in_circle[i] = True	# 满足则代表该点在此圆内,将in_circle中对应圆的值设为true
        
        # 接下来进入判断部分:
        # 判断被哪几个圆包含:
        if in_circle[0] == False and in_circle[1] == False and in_circle[2] == False:
            # 三个圆都不在 ↑
            window.set_at((x, y), (255, 255, 255))	# 设置该像素点的RGB值
        elif in_circle[0] == True and in_circle[1] == False and in_circle[2] == False:
            # 蓝 ↑
            window.set_at((x, y), (0, 0, 255))	# 设置该像素点的RGB值
        elif in_circle[0] == False and in_circle[1] == True and in_circle[2] == False:
            # 绿 ↑
            window.set_at((x, y), (0, 255, 0))	# 设置该像素点的RGB值
        elif in_circle[0] == False and in_circle[1] == False and in_circle[2] == True:
            # 红 ↑
            window.set_at((x, y), (255, 0, 0))	# 设置该像素点的RGB值
        elif in_circle[0] == True and in_circle[1] == True and in_circle[2] == False:
            # 蓝绿 ↑
            window.set_at((x, y), (0, 255, 255))	# 设置该像素点的RGB值
        elif in_circle[0] == False and in_circle[1] == True and in_circle[2] == True:
            # 绿红 ↑
            window.set_at((x, y), (255, 255, 0))	# 设置该像素点的RGB值
        elif in_circle[0] == True and in_circle[1] == False and in_circle[2] == True:
            # 红蓝 ↑
            window.set_at((x, y), (255, 0, 255))	# 设置该像素点的RGB值
        elif in_circle[0] == True and in_circle[1] == True and in_circle[2] == True:
            # 红绿蓝 ↑
            window.set_at((x, y), (255, 255, 255))	# 设置该像素点的RGB值
            
        # 防止程序出现未响应的情况,加入页面关闭的检测响应
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
        # 每遍历一个点,更新一下屏幕
        pygame.display.update()
  1. 最后,在绘制完后,不让界面关闭,加入一个while循环
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
            break
  1. 最终效果:(要慢一些,我这个快进了哈哈
    在这里插入图片描述

  2. 所有代码

import pygame
from pygame import *
pygame.init()

window = pygame.display.set_mode((400, 400))
pygame.display.set_caption("RGB")

circle = [(200, 100), (150, 200), (250, 200)]
r = 100

in_circle = [False, False, False]
for i in circle:
    pygame.draw.circle(window, (255, 255, 255), i, r, 10)

for y in range(0, 400):
    for x in range(0, 400):
        in_circle = [False, False, False]
        for i in range(3):
            if ((circle[i][0] - x)**2 + (circle[i][1] - y)**2) <= r*r:
                in_circle[i] = True
        # 判断被那几个圆包含
        if in_circle[0] == False and in_circle[1] == False and in_circle[2] == False:
            # 三个圆都不在
            window.set_at((x, y), (255, 255, 255))
        elif in_circle[0] == True and in_circle[1] == False and in_circle[2] == False:
            # 蓝
            window.set_at((x, y), (0, 0, 255))
        elif in_circle[0] == False and in_circle[1] == True and in_circle[2] == False:
            # 绿
            window.set_at((x, y), (0, 255, 0))
        elif in_circle[0] == False and in_circle[1] == False and in_circle[2] == True:
            # 红
            window.set_at((x, y), (255, 0, 0))
        elif in_circle[0] == True and in_circle[1] == True and in_circle[2] == False:
            # 蓝绿
            window.set_at((x, y), (0, 255, 255))
        elif in_circle[0] == False and in_circle[1] == True and in_circle[2] == True:
            # 绿红
            window.set_at((x, y), (255, 255, 0))
        elif in_circle[0] == True and in_circle[1] == False and in_circle[2] == True:
            # 红蓝
            window.set_at((x, y), (255, 0, 255))
        elif in_circle[0] == True and in_circle[1] == True and in_circle[2] == True:
            # 红绿蓝
            window.set_at((x, y), (255, 255, 255))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
        pygame.display.update()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
            break

以上,over!
有更好的方法欢迎评论告知,我向你敬礼呀~
或许我该去学学算法了(
具体的应该还能再优化?
https://blog.csdn.net/zx3517288/article/details/53326420

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值