カテゴリー別アーカイブ: python

WebMapServiceでGIS

GoogleMapのような地図のレンダリング機能が欲しくなりました。

しかもPythonで。

検索するとすぐ発見。

OwsLib。

インストールも簡単

sudo easy_install OWSLib

ちなみに、easy_installが使えない人は、先に以下のコマンドを実行。(Ubuntuでの話)

sudo apt-get install python-setuptools

さて、OWSLibの公式サイトに書いてあるスクリプトをチョロッと改造して、

東京近辺の地図を出してみました。

nasaが持っている地図から取得。

[sourcecode language=”python”]
#!/usr/bin/env python
# -*- coding:UTF-8 -*-

from owslib.wms import WebMapService
wms = WebMapService("http://wms.jpl.nasa.gov/wms.cgi", version="1.1.1")
img = wms.getmap( layers=[‘global_mosaic’],
styles=[‘visual_bright’],
srs=’EPSG:4326′,
bbox=(139.25, 35.25, 140.25, 36.25),
size=(640, 640),
format=’image/jpeg’,
transparent=True
)
out = open(‘tokyo_1.jpg’, ‘wb’)
out.write(img.read())
out.close()
[/sourcecode]

実行すると、tokyo_2.jpgファイルが作成されます。

こんな感じ。

tokyo_1

簡単ですね。

WMSのサイトを変えて、日本の国土地理院の行政区画の区分地図を取得。

[sourcecode language=”python”]
#!/usr/bin/env python
# -*- coding:UTF-8 -*-

from owslib.wms import WebMapService
wms = WebMapService("http://www.finds.jp/ws/kiban25000wms.cgi", version="1.1.1")
img = wms.getmap( layers=[‘AdmArea’],
srs=’EPSG:4326′,
bbox=(139.25, 35.25, 140.25, 36.25),
size=(640, 640),
format=’image/jpeg’,
transparent=True
)
out = open(‘tokyo_2.jpg’, ‘wb’)
out.write(img.read())
out.close()
[/sourcecode]

tokyo_2

これも簡単。

pythonで画像表示

pythonのGUIモジュールであるpygtkを使うと、簡単にウィンドウアプリケーションが作成できます。

しかもRADツールであるgladeインターフェース・デザイナを使えば、GUIの構成もサクサクです。

ということで、指定した画像を表示するアプリケーションを作ってみます。

環境はpythonとpygtkが動けばOKです。

まずは、pythonのコードです。

simage.pyファイルとして、保存して下さい。

[sourcecode language=”python”]
#! /usr/bin/env python
# -*- coding: UTF-8 -*-

# インポート
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade

# メインウィンドウクラスの定義
class MainWindow:

# コンストラクタ
def __init__(self):
# gladeファイルから一発でGUIを構築
self.widgets = gtk.glade.XML("simage.glade", "window")

# イベントハンドラの割り当て
self.auto_connects()

# GtkImageをscrolledwindowに追加する
self.image = gtk.Image()
self["scrolledwindow"].add_with_viewport(self.image)

# MainWindowを表示する
self["window"].show_all()

# イベントハンドラの追加(gtk_ではじまるメソッドを登録)
def auto_connects(self):
event_handlers = {}
for (itemname, value) in self.__class__.__dict__.items():
if callable(value) and itemname.startswith(‘gtk_’):
event_handlers[itemname[4:]] = getattr(self, itemname)
self.widgets.signal_autoconnect(event_handlers)

# 指定されたアイテムが見つからない時に呼び出す(widgetの呼び出しを簡単にする)
def __getitem__(self, key):
return self.widgets.get_widget(key)

# ウィンドウの「閉じる」ボタンを押したときのイベントハンドラ
def gtk_on_window_delete_event(self, widget, event=None):
gtk.main_quit()

# メニューの「終了」を選んだときのイベントハンドラ
def gtk_on_quit_menu_item_activate(self, widget):
gtk.main_quit()

# メニューの「開く」を選んだときのイベントハンドラ
def gtk_on_open_menu_item_activate(self, widget):
dlg = gtk.FileChooserDialog(
"画像を開く",
None,
gtk.FILE_CHOOSER_ACTION_OPEN,
(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,gtk.RESPONSE_OK
)
)
dlg.set_default_response(gtk.RESPONSE_OK)

# 画像ファイルのフィルタを作る
filter = gtk.FileFilter()
filter.set_name("Images")
filter.add_mime_type("image/jpeg")
filter.add_mime_type("image/gif")
filter.add_mime_type("image/png")
filter.add_pattern("*.jpg")
filter.add_pattern("*.gif")
filter.add_pattern("*.png")
dlg.add_filter(filter)

# すべてのファイルのフィルタも作る
filter = gtk.FileFilter()
filter.set_name("All files")
filter.add_pattern("*")
dlg.add_filter(filter)

# ダイアログの表示
res = dlg.run()

# 「OK」ボタンを押したら、画像ファイルを開く
if res == gtk.RESPONSE_OK:
self.open_image(dlg.get_filename())

# ダイアログの破棄
dlg.destroy()

# 指定された画像を開く
def open_image( self, filename ):
self.image.set_from_file(filename)

# スタートアップ
if __name__ == "__main__":
window = MainWindow()
gtk.main()
[/sourcecode]

続いて、gladeファイルです。

simage.gladeファイルとして保存して下さい。

[sourcecode language=”xml”]
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!–Generated with glade3 3.4.5 on Thu Apr 30 17:55:07 2009 –>
<glade-interface>
<widget class="GtkWindow" id="window">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="title" translatable="yes">Simple Image Viewer</property>
<property name="default_width">350</property>
<property name="default_height">350</property>
<signal name="destroy" handler="on_window_destroy"/>
<signal name="delete_event" handler="on_window_delete_event"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">ファイル(_F)</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkImageMenuItem" id="open_menu_item">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">開く(_O)</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_open_menu_item_activate"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image2">
<property name="stock">gtk-open</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit_menu_item">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">終了(_Q)</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_quit_menu_item_activate"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image5">
<property name="stock">gtk-quit</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">1</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkStatusbar" id="statusbar">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="spacing">2</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
[/sourcecode]

このgladeファイルは、gladeインターフェース・デザイナver3で作成しましたので、そのまま読み込むことができます。

よって、このXMLファイルは理解していなくても、gtkモジュールが勝手に解釈してくれます。

pythonコードをみると、22行目でGtkImageをロードしています。

gladeインターフェース・デザイナにもGtkImageはありますので、そこで設置しておけば良いはず。

しかし、設置して実行してみると、gladeの初期化(16行目)で警告が表示され、
ウィンドウのスクロールが正常に動作しませんでした。

./simage.py:16: GtkWarning: gtk_scrolled_window_add(): cannot add non scrollable widget use gtk_scrolled_window_add_with_viewport() instead
self.widgets = gtk.glade.XML(“simage.glade”, “window”)

とりあえず、プログラムでGtkImageを設置すると大丈夫です。

ということで、100行も書かずに画像ビューワが完成です。