WebP是Google近几年推出的新型网络图片格式,有静态和动态两种类型,其中静态webp比jpg和png的压缩率都要大,而且失真率接近于png,远胜于jpg,因为他支持8位的透明通道。而动态webp比gif好了不止一两点,gif只支持2位的透明通道,而且图片锯齿严重。OK,既然有这么牛逼的图片格式,我们当然要好好使用了,而且现在Android端有Facebook推出的Fresco框架完美支持,不仅静态还是动态。可惜,现在制作WebP的工具寥寥无几,更不用说动态WebP了,只能靠Google提供的命令行工具,但是对于批量图片转换,命令未免太长了,着实不方便,故写下了这篇文章。
为了三种开发系统(Mac OS X,Windows,Linux)都能使用,这次就使用wxPython做这个GUI程序吧,最后再用pyinstaller打包到各个平台,好了,废话不多说,上源代码,由于篇幅原因,这里只贴关键逻辑代码。
# -*- coding: utf-8 -*-
__author__ = 'linfuyuan'
import base_window
import wx
import os
import my_process as mp
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import platform
import codecs
import shutil
class MyDialog(base_window.MyDialog1):
def __init__(self, parent):
base_window.MyDialog1.__init__(self, parent)
self.my_process_dlg = mp.MyProcess(None, self.onCancel)
self.is_cancel = False
self.env = platform.system()
def on_choose_dir(self, event):
file_wildcard = "*"
dlg = wx.FileDialog(self, u"请选择图片目录",
os.getcwd(),
style=wx.OPEN | wx.MULTIPLE,
wildcard=file_wildcard)
if dlg.ShowModal() == wx.ID_OK:
file_names = dlg.GetPaths()
for fn in file_names:
self.m_listBox1.Append(fn)
# self.pic_gallery.Add(wx.StaticText(self, -1, fn), 0, wx.ALIGN_LEFT)
dlg.Destroy()
pass
def on_png_to_webp(self, event):
items = self.m_listBox1.GetItems()
if len(items) > 0 and self.lib_exist():
command = 'lib_mac%simg2webp' % os.sep
if self.env == 'Linux':
command = 'lib_linux%simg2webp' % os.sep
elif self.env == 'Windows':
command = 'lib_windows%simg2webp.exe' % os.sep
self.my_process_dlg.m_staticText3.SetLabel(u'处理中')
self.my_process_dlg.m_button5.SetLabel(u'取消')
self.is_cancel = False
self.my_process_dlg.m_gauge1.SetRange(len(items))
self.my_process_dlg.m_gauge1.SetValue(0)
self.my_process_dlg.Show()
count = 0
dest_dir = '%s%shappy_webp' % (os.getcwd(), os.sep)
if not os.path.exists(dest_dir):
os.mkdir(dest_dir)
tmp_dir = '%s%stmp' % (os.getcwd(), os.sep)
if not os.path.exists(tmp_dir):
os.mkdir(tmp_dir)
for item in items:
if not self.is_cancel:
filename = item[item.rindex(os.sep):]
shutil.copy(item, '%s%s' % (tmp_dir, os.sep))
os.system(
'%s %s%s%s -o %s%s%s.webp' % (
command, tmp_dir, os.sep, filename, dest_dir, os.sep,
item[item.rindex(os.sep) + 1:item.rindex('.')]))
os.remove('%s%s%s' % (tmp_dir, os.sep, filename))
count += 1
self.my_process_dlg.m_gauge1.SetValue(count)
else:
break
self.my_process_dlg.m_staticText3.SetLabel(u"输出路径:%s" % dest_dir)
self.my_process_dlg.m_button5.SetLabel(u'完成')
def on_webp_to_animate(self, event):
items = self.m_listBox1.GetItems()
if len(items) > 0 and self.lib_exist():
command = 'lib_mac%swebpmux' % os.sep
if self.env == 'Linux':
command = 'lib_linux%swebpmux' % os.sep
elif self.env == 'Windows':
command = 'lib_windows%swebpmux' % os.sep
self.my_process_dlg.m_staticText3.SetLabel(u'处理中')
self.my_process_dlg.m_button5.SetLabel(u'取消')
self.is_cancel = False
self.my_process_dlg.m_gauge1.SetRange(len(items))
self.my_process_dlg.m_gauge1.SetValue(0)
self.my_process_dlg.Show()
dest_dir = '%s%shappy_animate_webp' % (os.getcwd(), os.sep)
gap = int(self.m_textCtrl1.GetValue())
if not os.path.exists(dest_dir):
os.mkdir(dest_dir)
tmp_dir = '%s%stmp' % (os.getcwd(), os.sep)
if not os.path.exists(tmp_dir):
os.mkdir(tmp_dir)
tmp_files = []
for item in items:
filename = item[item.rindex(os.sep):]
shutil.copy(item, '%s%s' % (tmp_dir, os.sep))
tmp_files.append('%s%s%s' % (tmp_dir, os.sep, filename))
# webpmux -frame 1.webp +100 -frame 2.webp +100+50+50 -frame 3.webp +100+50+50+1+b -loop 10 -bgcolor 255,255,255,255 -o anim_container.webp
os.system(
'%s %s -o %s%sanimate.webp' % (command,
' '.join(['-frame %s +%d+0+0+1+b' % (x, gap) for x in tmp_files]),
dest_dir,
os.sep))
for tf in tmp_files:
os.remove(tf)
self.my_process_dlg.m_gauge1.SetValue(len(items))
self.my_process_dlg.m_staticText3.SetLabel(u"输出路径:%s" % dest_dir)
self.my_process_dlg.m_button5.SetLabel(u'完成')
def onClear(self, event):
self.m_listBox1.Clear()
def onCancel(self):
self.is_cancel = True
self.my_process_dlg.Close()
def lib_exist(self):
if self.env == 'Darwin':
if not os.path.exists('lib_mac'):
dlg = wx.MessageDialog(None,
u"请到http://download.csdn.net/detail/xanxus46/9794013 下载并解压到%s下" % os.getcwd(),
u"lib_mac/webp类库找不到")
dlg.ShowModal()
dlg.Destroy()
return False
else:
return True
elif self.env == 'Linux':
if not os.path.exists('lib_linux'):
dlg = wx.MessageDialog(None,
u"请到http://download.csdn.net/detail/xanxus46/9793858 下载并解压到%s下" % os.getcwd(),
u"lib_linux/webp类库找不到"
)
dlg.ShowModal()
dlg.Destroy()
return False
else:
return True
elif self.env == 'Windows':
if not os.path.exists('lib_windows'):
dlg = wx.MessageDialog(None,
u"请到http://download.csdn.net/detail/xanxus46/9794046 下载并解压到%s下" % os.getcwd(),
u"lib_windows\\webp类库找不到")
dlg.ShowModal()
dlg.Destroy()
return False
else:
return True
else:
return True
其余的可参考http://download.csdn.net/detail/xanxus46/9794411完整的代码
下面介绍一下用pyinstaller打包好的程序的使用方法吧
下载地址:
windows http://download.csdn.net/detail/xanxus46/9794351
mac http://download.csdn.net/detail/xanxus46/9794400,程序是main.cpp不是main,两者运行当前目录不同~
linux 由于google提供的libwep二进制程序运行不了,需要编译源码,我就没弄了
使用很简单,打开软件会看到主界面
点击选择图片,然后如果是需要png转webp则选择png图片,需要静态webp转动态webp则选择webp图片,填上每帧的时间间隔,可多选。点击清除可清除已选的所有图片。
注意,这里不要选文件名带有中文的图片,因为python自古以来的编码问题,你懂的,但路径中可以带中文,这没问题。转化过程中,可能会报错,最可能是libwebp工具包不在当前目录,这里提供几个下载地址,其他的自行百度到google开发者页面下载吧,需要番羽墙你也懂得。
libwebp工具包下载地址:
windows64位:http://download.csdn.net/detail/xanxus46/9794046
mac:http://download.csdn.net/detail/xanxus46/9794013,mac真心简单
linux:http://download.csdn.net/detail/xanxus46/9793858,这个在ubuntu12.04运行不了,需要重新编译源码,不过其他系统可以尝试一下
转化完成后,会在程序的当前目录产生两个文件夹,一个是png转webp的目录happy_webp,另一个是静态转动态的目录happy_animate_webp,文件名和原来一样,只是扩展名改成webp,如图
对于webp图片的查看,可以用chrome浏览器打开,毕竟是google自家的产品嘛。
在用windows的程序时,可能会出现什么windows imaging component找不到的错误,这时需要从微软官网上下载,http://www.microsoft.com/en-us/download/details.aspx?id=32,windows问题真不少,博主推荐大家用mac的程序,几乎不会有什么兼容性问题哈~
好了,程序介绍完毕,欢迎大家留言咨询~