首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python 90行代码让微信地球转起来,你也可以!

作者 | xiaorang

责编?|?Aholiab

头图 | CSDN 下载自视觉中国

出品 | CSDN(ID:CSDNnews)

手机重启后打开微信的一瞬间,会看到一幅有名的图片,上面站着一个“张小龙”。

你可曾想过这样一个问题,如果上面那个地球转起来会是怎样?就像下面这样:

效果简直不要太酷炫,那么这样一个酷炫的操作是怎么做出来的呢?我们接着往下看。

这里共需要准备三样素材:

地球表面素材

云图素材

微信地球的抠图素材

地球表面素材如下所示:

云图素材如下所示:

微信地球抠图素材如下所示:

这里重点讲双层素材的动态效果。云图是灰度图,白色地方代表云层厚,黑色的地方代表那里云层薄,我们根据颜色设置不同的透明度。

如果云图与地面的选择速度相同,会显得不自然,我们这里让云层旋转速度比地面旋转速度慢一半,产生相对运动的效果。

这样带来的问题是,地球旋转360°后云图只旋转了180°,必须加倍到720°才能实现连续运动。

具体的云层透明度设置,参数需根据实际效果进行调整。

接下来是GIF压缩,顺便给大家介绍一个比较好用的GIF压缩工具iloveimg。用这个工具可以直接生成GIF动图,并且不会超过传输限制。用此工具压缩后文件体积大幅缩小,但图片效果没有肉眼可以察觉的影响。

那么,最关键的一步来了,我们该如何用Python实现旋转地球的效果呢?完整代码如下所示:

from?PIL?import?Image,?ImageDraw

import?math

import?numpy?as?np

import?imageio

def?calcSphereXY2XYZ(px,?py,?maxHeight,?longOffset):

v0x=?np.array(px)

v0y=?np.array(py)

v03=?np.subtract(v0x,?maxHeight)

v04=?np.subtract(v0y,?maxHeight)

v1x=?np.true_divide(v03,?maxHeight)

v1y=?np.true_divide(v04,?maxHeight)

#?print(max(v1x),?min(v1x))

v07=?np.power(v1x,2)

v08=?np.power(v1y,2)

v09=?np.add(v07,v08)

v0a=?np.subtract(1,v09)

v1z=?np.power(v0a,1/2)??????????????????????????????????#?z

#?print('z:',?max(v1z),?min(v1z))

v1lat=?np.multiply(v1y,?math.pi/2)??????????????????????#?lat

v0lon=?np.arctan2(v1z,?-v1x)

v1lon=?np.add(v0lon,?longOffset)???????????????????????#?long

v2lon=?np.fmod(v1lon,?math.pi*2)???????????????????????#?long

return?v2lon,?v1lat

def?calcShpereLatLong2XY(vlon,?vlat,?width,?height):

v3x0=np.multiply(vlon,?width/2/math.pi)

v3y0=np.multiply(vlat,?height/math.pi)

v3y1=np.add(v3y0,?height/2)

v3x2=v3x0.astype(np.integer)

v3y2=v3y1.astype(np.integer)

return?v3x2,?v3y2

def?getPic(a):

#?imgBack=?Image.open('地球3.jpg')

imgBack=?Image.open('世界地球日地图_8K_2.jpg')

imgCloud=?Image.open('世界地球云地图_8K.jpg')

width=?imgBack.size[0]

height=?imgBack.size[1]

imgBack=?imgBack.convert('RGBA')

arrayBack=?np.array(imgBack)

arrayCloud=?np.array(imgCloud)

circleSize=?508

img2=?Image.new('RGBA',?(circleSize,circleSize))

img=?Image.new('RGBA',?(circleSize,circleSize),?'black')

w=?img.size[0]

h=?img.size[1]

pxList=[]

pyList=[]

for?i?in?range(w):

for?j?in?range(h):

r=?math.sqrt((i-w/2)**2+(j-h/2)**2)

if?r

pxList.append(i)

pyList.append(j)

nplon,?nplat=?calcSphereXY2XYZ(pxList,?pyList,?h/2,?a)

nplon2,?nplat2=?calcSphereXY2XYZ(pxList,?pyList,?h/2,?a/2)

#?nplon,?nplat=?rotSphere(nplon,?nplat,?)

npx,?npy=?calcShpereLatLong2XY(nplon,?nplat,?width-1,?height)

npx2,?npy2=?calcShpereLatLong2XY(nplon2,?nplat2,?width-1,?height)

color=?arrayBack[npy,?npx]

color2=?arrayCloud[npy2,?npx2]

for?i?in?range(len(pxList)):

x=?pxList[i]

y=?pyList[i]

cc=color[i]

#?print(cc)

cc=?tuple(cc)

img.putpixel((x,y),?cc)

c2=?color2[i]

c0=?int(c2[0]*1.6)

if?c0>255:

c0=255

c_alpha=?int(c2[0]*0.9)

c2=?(c0,c0,c0,c_alpha)

img2.putpixel((x,y),?c2)

r,g,b,a=?img2.split()

img.paste(img2,?(0,0),?mask=a)

return?img

if?__name__=='__main__':

frames=[]

str1=?'微信地球_mask.png'

img1=?Image.new('RGB',?(750,1334))

img2=?Image.open(str1)

for?i?in?range(0,?720,?12):

a=?-i*math.pi/?180

img=?getPic(a)

img1.paste(img,(122,424))

r,g,b,alpha=img2.split()

img1.paste(img2,?(0,0),?mask=alpha)

str1=?'temp%03d.png'%i

print(str1)

img1.save(str1)

im?=?imageio.imread(str1)

frames.append(im)

#?img.show()

imageio.mimsave('earth.gif',?frames,?'GIF',?duration=0.20)

对Python感兴趣的同学,可以将上面代码down下来慢慢研究。通过对小项目的实现可以快速提升代码的实操能力。

你学会了吗?如有疑问欢迎在评论区留言。

更多精彩推荐

时隔 15 年,苹果的自研 ARM 芯片为何能取代 Intel 处理器?

从微信「拍一拍」,我想到了那些神奇的一行代码功能

AI 又进阶!除了鉴别 PS 图片,还能一键卸妆!

无代码开发到底是不是伪需求?

程序员端午炫富指南~

Spring 从入门到入土——AOP 就这么简单!| 原力计划

硬核!国外开发者用 25 美元做了个区块链警佩相机!

你点的每个“在看”,我都认真当成了喜欢

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200626A09WVP00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com