pil拼接图片实践-拼接南都亿像素

最近有个词挺火的,微博上疯狂转载,这就是“南都亿像素”。其中有张“全国政协十一届五次会议开幕”的图片达到了惊人的12亿像素,局部放大以后几乎能看清图片上每个人,这张图片其实是由很多小图片拼接成的,我对这个很是好奇,别的不多说,这里讲如何拼接成一张大图。

我打开了一款Python开发的Proxy,它能直接显示出所有的HTTP请求,然后清空缓存,把浏览器的代理服务器设置好,打开“全国政协十一届五次会议开幕”这个页面。通过Proxy可以看到页面发出的请求地址。我发现这个大图片其实是由一张张小图片拼成的。通过一番探索得到的图片地址的规律,如“http://nd.oeeee.com/images/ztpics/yixiangsu/list/20120306lhhc/zhx.tiles/l7/01_01.jpg”,其中“l7/01_01.jpg”这一部分中的“l7”代表缩放级别,7为最高级,表示清晰度最高。后面的“01_01”中,前一个“01”表示行数,后一个表示列数,如“02_03”代表第二行第三张图片。得到这个规律就好说了,我又通过猜URL和缩放图片得到了这张亿像素的图片由85*55张照片组成。到这里,得到的信息已经够把所有的图片下载下来了,具体代码如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
For:
by Lerry  http://lerry.org
Start from 2012-03-08 17:09
Last edit at 2012-03-08 17:09
'''
import os
import urllib

base_dir = os.path.join(os.getcwd(), 'imgs/')
url = 'http://nd.oeeee.com/images/ztpics/yixiangsu/list/20120306lhhc/zhx.tiles/l7/'
def get_range(n):
    temp = range(1,n+1)
    result = []
    for i in temp:
        i = str(i)
        if len(i) == 1:
            result.append('0'+i)
        else:
            result.append(i)    
    return result
def down_one(url, name):
    if not os.path.exists(name):
        pic = urllib.urlopen(url).read()
        print 'Downloaded: ',name
        f = open(name,'wb')
        f.write(pic)
        f.close()


if __name__ == "__main__":
    for m in get_range(55):
        for n in get_range(85):
            fname = '%s_%s.jpg' % (m, n)
            print url+fname
            down_one(url+fname,base_dir+fname)

然后要考虑如何将图片拼接成一张大图片,代码如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
For:
by Lerry  http://lerry.org
Start from 2012-03-08 19:17
Last edit at 2012-03-08 19:17
'''
import PIL.Image as Image
import os,sys
from download import get_range


w = 85*512
h = 55*512

a = 512
base_dir = os.path.join(os.getcwd(), 'imgs/')

toImage = Image.new('RGBA', (w, h))

for m in get_range(85):
    for n in get_range(55):
        fname = '%s_%s.jpg' % (n, m)
        fromImage = Image.open(base_dir+fname)
        i, j = int(m), int(n)
        toImage.paste(fromImage,((i-1)*a, (j-1)*a))

toImage.save('result.jpg')

以前没有用过PIL这个库,用法挺简单的,临时学了下,参考了这里的代码。

程序写好后,一运行直接提示“Memory Error”,估计是内存不足。于是我把它拖到了一台服务器上,2颗6核AMD的U,16G内存,安装PIL还遇到了些问题,不过Google一下都能解决。第一次运行后,发现拼出来的图不对,看了看是逻辑搞错了,两层For循环的问题。改了下,大约花了一分半钟,才结束,而且运行时占用了4.6G内存,怪不得在我的4G内存的本上直接报错,这是运行时的htop截图:

图是生成了,但是有88.9MB之大,我就拖回本地,看了看缩略图是正确的。但是Mint Debian默认的图片浏览器打不开,估计是图片太大,我又用GIMP试,还是打不开,重启进win7,先后试了win7自带图片浏览器、Photoshop7.0,Photoshop CS3,Picasa3.9,都无法正常浏览。难道这图真的打不开?这时想到了ACDSee,这东西我一般都不用,觉得不如系统自带的简洁,于是去下了最新版的ACDSee12,可以打开浏览、缩放,但是这个软件太臃肿了,我又试了试经典的ACDSee5.0,仍然能流畅打开并缩放。看来真的是一物降一物。好吧,大家可以试一试。

2,410 views, since 2012-03-09