微信地球
在手机重启后打开微信的那一刻,你会看到一张著名的照片。
可能是站在月亮上看地球的效果。
你有没有想过如果上面的地球转动会发生什么?
素材
这里有两种表面材料,一种是地球表面材料,另一种是云图材料。
还有一个微信地球的素材。
基本原理
基本的贴图方法在本博的前一篇文章(《用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视频教程!!