GoogleMap的切片地址改变了,以下内容已成历史:)
我们最近的遥感实习要做野外调绘,没想到老师给的图竟然比 Google Map 上的图还要旧,想想干脆就把 Google Map 上的图下载下来参考一下。
主要代码是这里面的:http://intepid.com/stuff/gmkh/ ,它是JS写的,我改成 Python,并增加大图拼接的功能。
Python 里面有两个数学库,一个是叫 cmath 另一个是 math。cmath 里面的东西好像比 math 的少,比如 log() 就只有 math 库里面才有。JS 代码转为 Python 基本上没有难度,就是有些比如 ? : 的运算符不同,还有一些格式上有问题而已。
一开始本来想用 urllib 来下载图片就行了,但是它没有像 httplib 那样的可以知道返回的状态(比如是 200 还是 404)。在某些放大级别下因为找不到图片是会返回 404 的,所以 httplib 在这里还是比较有用的。httplib.HTTPConnection()的参数里面的字符串是不需要有"http://"的,一开始我写成了httplib.HTTPConnection("http://kh2.google.com")那样,调试了半天才知道是这个错误。
因为下载下来的是图片数据,不是普通的文本,所以写入文件时的 open() 函数要用 "wb" 标志。要不然写入的时候程序会把 0x0A 都变为 0x0D 0x0A(回车换行符),这样图片就显示不对了。
# -*- coding:UTF-8 -*-
import
Image
import
httplib
from
math
import
*
class
MapImage():
"""
将经纬度坐标转换为 Google Map 的 URL,并且可以把图片下载下来,合成一幅大图。 下载后的图片依次命名为 1.jpg 2.jpg ...,最后合并的大图命名为 map.jpg 合并成大图的话需要 PIL 库。
"""
def
__init__
(self, Zoom
=
10
, nX
=
3
, nY
=
3
):
"""
nX 和 nY 的设置就会由3x3个图生成大图。 Zoom 是放大级别(1 - 20),某些地区的最大级别不到 20 或更小。
"""
self.w
=
0 self.h
=
0 self.nx
=
nX self.ny
=
nY self.zoom
=
Zoom self.outputImg
=
"
map.jpg
"
self.imgFiles
=
[]
def
SetTiles(self, nX, nY): self.nx
=
nX self.ny
=
nY
def
SetZoom(self, Zoom): self.zoom
=
Zoom
def
GetAddress(self, lon, lat):
"
转换为 Mercator 投影
"
PI
=
3.1415926535897
digits
=
20
x
=
(
180.0
+
lon)
/
360.0
y
=
-
lat
*
PI
/
180.0
y
=
0.5
*
log( (
1
+
sin(y))
/
(
1
-
sin(y)) ) y
*=
1.0
/
(
2
*
PI) y
+=
0.5
quad
=
"
t
"
lookup
=
"
qrts
"
while
digits
>
0: x
-=
floor(x) y
-=
floor(y) quad
=
quad
+
lookup[(x
>=
0.5
and
1
or
0)
+
(y
>=
0.5
and
2
or
0)] x
*=
2
y
*=
2
digits
-=
1
return
quad
def
GetNextTileX(self, addr, forward):
"
获得下一个横图块
"
if
addr
==
''
:
return
addr parent
=
addr[:len(addr)
-
1
] last
=
addr[len(addr)
-
1
]
if
last
==
'
q
'
: last
=
'
r
'
if
(
not
forward): parent
=
self.GetNextTileX(parent, forward)
elif
last
==
'
r
'
: last
=
'
q
'
if
(forward): parent
=
self.GetNextTileX(parent, forward)
elif
last
==
'
s
'
: last
=
'
t
'
if
(forward): parent
=
self.GetNextTileX(parent, forward)
elif
last
==
'
t
'
: last
=
'
s
'
if
(
not
forward): parent
=
self.GetNextTileX(parent, forward)
return
parent
+
last
def
GetNextTileY(self, addr, forward):
"
获得下一个纵图块
"
if
addr
==
''
:
return
addr parent
=
addr[:len(addr)
-
1
] last
=
addr[len(addr)
-
1
]
if
last
==
'
q
'
: last
=
'
t
'
if
(
not
forward): parent
=
self.GetNextTileY(parent, forward)
elif
last
==
'
r
'
: last
=
'
s
'
if
(
not
forward): parent
=
self.GetNextTileY(parent, forward)
elif
last
==
'
s
'
: last
=
'
r
'
if
(forward): parent
=
self.GetNextTileY(parent, forward)
elif
last
==
'
t
'
: last
=
'
q
'
if
(forward): parent
=
self.GetNextTileY(parent, forward)
return
parent
+
last
def
GetURL(self, lat, lon):
"""
转换经纬度为 URL。 输入经度、纬度
"""
address
=
[] addr
=
self.GetAddress(lon, lat) cursor
=
addr[:self.zoom] cursor
=
self.GetNextTileX(cursor,0) cursor
=
self.GetNextTileY(cursor,0)
for
x
in
range(0, self.nx): c2
=
cursor cursor
=
self.GetNextTileX(cursor,
1
)
for
y
in
range(0, self.ny): address.append(
"
/kh?v=3&t=
"
+
c2) c2
=
self.GetNextTileY(c2,
1
) self.imgList
=
address
return
tuple(address)
def
DownloadImg(self):
"
下载列表中的图片
"
files
=
[]
for
imgurl
in
self.imgList:
con1
=
httplib.HTTPConnection(
"
kh2.google.com
"
) con1.request(
"
GET
"
, imgurl) r1
=
con1.getresponse()
try
:
if
r1.status
==
200
: data
=
r1.read() files.append(
"
%s.jpg
"
%
(self.imgList.index(imgurl))) f
=
open(
"
%s.jpg
"
%
(self.imgList.index(imgurl)),
"
wb
"
) f.write(data) f.close()
print
"
%s.jpg OK...
"
%
(self.imgList.index(imgurl))
elif
r1.status
==
404
:
print
"
%s.jpg no found
"
%
(self.imgList.index(imgurl))
else
:
print
"
%s.jpg unkown error
"
%
(self.imgList.index(imgurl))
except
:
print
"
img: %s download error
"
%
(self.imgList.index(imgurl)) self.imgFiles
=
tuple(files)
return
self.imgFiles
def
Merge(self):
"
合并图片
"
self.w
=
self.nx
*
256
self.h
=
self.ny
*
256
img
=
Image.new(
"
RGB
"
, (self.w, self.h)) stepX
=
0 stepY
=
0
for
i
in
self.imgFiles: im
=
Image.open(i) img.paste(im, (0
+
stepX, 0
+
stepY,
256
+
stepX,
256
+
stepY)) stepY
+=
256
if
stepY
>=
self.h: stepX
+=
256
stepY
=
0 img.save(self.outputImg) img.show()
return
self.outputImg gmap
=
MapImage(
20
,
4
,
4
)
print
"
"
.join(gmap.GetURL(
40.703610
,
-
73.931630
))
#
这是New York的某个地方
print
"
"
.join(gmap.DownloadImg())
print
gmap.Merge()
下面是下载拼接后的图,由4x4个小图拼接成。