此处为老的 LinuxGem,新版 LinuxGem 请移步

DIY 一个用于生成桌面墙纸的“网络相机”

galeki posted @ 2009年4月25日 03:52 in 编程技巧与工具 with tags python ImageMagick montage , 6137 阅读

Ben 写了一个 python 脚本——WebCam,区区百十行代码,实现了从网络或本地目录抓取多幅图片并随机拼合到一起,所生成的图片可以作为漂亮的桌面墙纸。这个脚本程序虽然不是非常智能,但是它可以作为一个 python 编程示例供初学者借鉴。您也可以尝试做一个 Lua 或 Ruby 版本


#! /usr/bin/env python
# Copyright 2009 by Benjamin Fogle
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <>.
import sys
import os
import os.path
import urllib2
import tempfile
import math
# Constants.  Change these to customize the script
# In ksh: CONFIG_FILE=$HOME/lectures/examples/LEC-05/webcam_config
CONFIG_FILE=os.getenv('HOME') + '/.webcam_config'
TARGET=os.getenv('HOME') + '/Pictures/Wallpapers/webcam.jpg'
SCREEN_X = 1024
SCREEN_Y = 768
def GetTiles(num_images):
    """Returns a tuple (N,M) representing the tile grid"""
    # This algorithm could be much improved
    tile = math.ceil(math.sqrt(N))
    return (tile, tile)
def GetImageSize(N, M):
    """Returns a the max size of each image based on the screen size
    and the tile grid"
    global SCREEN_X
    global SCREEN_Y
    ImgX = SCREEN_X / N
    ImgY = SCREEN_Y / M
    return (ImgX, ImgY)
def CopyFile(src_fp, dest_fp):
    """Copy a file intelligently"""
    data =   # Copy 48k at a time
    while data:
        data =
    # Note: shutils.copyfileobj does this too.
if len(sys.argv) != 1:
    print "Usage: %s" % (sys.argv[0])
    print "Config file is located in %s" % CONFIG_FILE
# Make sure the config file is readable and that it is a regular file
# There is a better way to do this that we will learn later.
if not os.access(CONFIG_FILE, os.R_OK) or not os.path.isfile(CONFIG_FILE):
    print "Error: %s could not be opened!" % CONFIG_FILE
urls = []           # Url to download from.  Read from config file
captions = []       # Captions for each image. Read from config file
filenames = []      # Temporary file names
config_fp = open(CONFIG_FILE, 'r')
line = config_fp.readline()
while line:
    params = line.split(":::")
    line = config_fp.readline()
# Download each url.  This is how to iterate over mutliple lists at once
for url, caption in zip(urls, captions):
    url_fp = urllib2.urlopen(url)
    # The following two lines are the preffered way to open a temporary
    # file.
    fd, name = tempfile.mkstemp()
    img_fp = os.fdopen(fd, 'w')
    CopyFile(url_fp, img_fp)
    img_fp.close()  # The data won't appear in img_fp until it's closed
    # Use the ImageMagick suite from the shell to add a caption
    os.system("convert '%s' -set comment '%s' '%s'" % \
              (name, caption, name))
# Figure out the parameters
tilex, tiley = GetTiles(N)
imgx, imgy = GetImageSize(tilex, tiley)
# Use ImageMagick again to assemble the wallpaper
cmd = "montage -geometry %dx%d \
               -tile %dx%d \
               -set caption '%%c' \
               -pointsize 32 \
               -size %dx%d \
               -texture plasma: \
               +polaroid \
               -background black "
% (imgx, imgy, tilex, tiley,
                       SCREEN_X, SCREEN_Y)
# Add each image file to the command string
for filename in filenames:
    cmd += '"%s" ' % filename
# Add the output file to the command string and execute
cmd += TARGET
# Cleanup
for filename in filenames:
    os.unlink(filename)     # In ksh:  rm $filename

要运行该脚本,需要您的系统中已经安装 imagemagick(一般 GNU/Linux 会默认为您安装该软件包)。

首先将上述代码复制到 webcam 文件并保存;然后,为该文件的添加可执行权限:

$ chmod  +x  webcam

在使用该脚本之前,需要将所要获取图片的地址信息写入 .webcam_config 文件,例如:

$ echo "file:///home/garfileo/Winter.jpg ::: 冬天" >> $HOME/.webcam_config
$ echo " ::: 昌平∙白虎涧" >> $HOME/.webcam_config
$ echo " ::: 赤水" >> $HOME/.webcam_config
$ echo "file:///home/garfileo/MY-Moutain.jpg ::: 明月山" >> $HOME/.webcam_config

然后,只需要执行 webcam 脚本,便可以在 $HOME/Pictures/Wallpapers 目录(若无该目录,请自行创建)中生成合成图片。上面向 .webcam_config 文件写入的四幅图地址,第一幅与第四幅图位于我的本地目录,而其它两幅均来自网络。每幅图片的地址后面均尾随 ":::" 符号,它是用来间隔图片地址与图片标签名的。这些图片的合成效果如下:

按照上述步骤正确操作,最终可以得到合成图片。不过,如果图片标签名是中文的话,那么最终的合成图中每幅小图的标签应该是一串问号或乱码。这是因为 webcam 脚本是通过调用 imagemagick 图片处理工具箱中的 montage 程序实现图片合成的,如果在图片中使用了中文标签名,那么需要设定中文字体方能在合成图中正确显示中文。要解决这个问题,需要在 webcam 脚本中找到以下代码段:

...... ......

# Use ImageMagick again to assemble the wallpaper

cmd = "montage -geometry %dx%d \
               -tile %dx%d \
               -set caption '%%c' \
               -pointsize 32 \
               ...... ......


...... ......

# Use ImageMagick again to assemble the wallpaper
cmd = "montage -geometry %dx%d \
               -font /usr/share/fonts/winfonts/msyh.ttf \
               -tile %dx%d \
               -set caption '%%c' \
               -pointsize 32 \
               ...... ......


Willing 说:
2009年5月01日 19:21


daf3707 说:
2009年5月09日 21:25



guowei 说:
2009年7月11日 21:11


Traceback (most recent call last):
File "./webcam", line 85, in <module>
url_fp = urllib2.urlopen(url)
File "/usr/lib/python2.6/", line 124, in urlopen
return, data, timeout)
File "/usr/lib/python2.6/", line 383, in open
response = self._open(req, data)
File "/usr/lib/python2.6/", line 401, in _open
'_open', req)
File "/usr/lib/python2.6/", line 361, in _call_chain
result = func(*args)
File "/usr/lib/python2.6/", line 1226, in file_open
return self.open_local_file(req)
File "/usr/lib/python2.6/", line 1262, in open_local_file
raise URLError(msg)
urllib2.URLError: <urlopen error [Errno 2] No such file or directory: '/home/garfileo/Winter.jpg'>

LiYanrui 说:
2009年7月11日 22:39

@guowei: 对配置文件根据你的情况进行自适应修改

登录 *

loading captcha image...
or Ctrl+Enter