当前位置: 首页 > 图灵资讯 > 行业资讯> 用Python实现让微信地球转起来附代码!

用Python实现让微信地球转起来附代码!

来源:图灵python
时间: 2025-02-09 17:51:57

微信地球

在手机重启后打开微信的那一刻,你会看到一张著名的照片。

f05a3d9fbf3aa6079f718fd5da59469.png

可能是站在月亮上看地球的效果。

你有没有想过如果上面的地球转动会发生什么?

素材

这里有两种表面材料,一种是地球表面材料,另一种是云图材料。

799350bbcf9569b7a83c98ab0718c37.pnga1fe28b76ca4044da95c954f15c1e90.png还有一个微信地球的素材。

1a99b2f141a6f765951097ec39c51d3.png

基本原理

基本的贴图方法在本博的前一篇文章(《用python旋转地球》)中提到,重点是双层材料的动态效果。云图是灰度图,白色代表云厚,黑色代表云薄。我们根据颜色设置不同的透明度。

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

问题是地球旋转360°云图只旋转了180°,必须加倍到720°实现连续运动。

应根据实际效果调整具体的云透明度设置。

GIF压缩

顺便介绍一个比较好用的压缩GIF在线工具。

https://www.iloveimg.com/zh-cn/compress-image/compress-gif

直接生成的GIF动图超过了传输限制,无法上传。用这个工具压缩后,文件体积大大缩小,但图片效果肉眼无法察觉。

完整代码

具体逻辑解释的步骤,请看《用python旋转地球》,这里贴上完整的代码。

fromPILimportImage,ImageDraw
importmath
importnumpyasnp
importimageio
defcalcsperexy2XYZ(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_pide(v03,maxHeight)
v1y=np.true_pide(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
returnv2lon,v1lat
defcalcshperlatlong2XY(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)
returnv3x2,v3y2
defgetPic(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=[]
foriinrange(w):
forjinrange(h):
r=math.sqrt((i-w/2)**2+(j-h/2)**2)
ifr<circleSize/2:
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=calcshperlatlong2XY(nplon,nplat,width-1,height)
npx2,npy2=calcshperlatlong2XY(nplon2,nplat2,width-1,height)
color=arrayBack[npy,npx]
color2=arrayCloud[npy2,npx2]
foriinrange(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)
ifc0>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)
returnimg
if__name__='__main__':
frames=[]
str1='微信地球_mask.png'
img1=Image.new('RGB',(750,1334))
img2=Image.open(str1)
foriinrange(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知识,请关注Python视频教程!!