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

python

微信地球

手机重启后打开微信的一瞬间,会看到一幅有名的图片。

大概是站在月亮上看地球的效果。

你有没有想过,如果上面那个地球转起来会是怎样?

素材

这里有两个表面素材,一个是地球表面素材,一个是云图素材。

还有一个微信地球的抠图素材。

基本原理

基本的贴图方法在本博前面的文章(《用python实现旋转地球》)中讲过了,这里重点讲双层素材的动态效果。云图是灰度图,白色地方代表云层厚,黑色的地方代表那里云层薄。我们根据颜色设置不同的透明度。

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

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

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

GIF压缩

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

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

直接生成的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<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= 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知识,请关注云海天Python教程!!

以上是 用Python实现让微信地球转起来附代码! 的全部内容, 来源链接: utcz.com/z/528820.html

回到顶部