2012年12月6日木曜日

グラデーション画像からAndroidのXMLを自動生成する

このエントリーをはてなブックマークに追加
Androidでは、画像ファイルをそのままアプリにはめこむのではなく、XMLでスタイルを定義することで、画像を作成することができます。

ここで、デザイナが下記のような画像ファイルでボタンを作成したとします。

 
が、エンジニアは、ここで困ります。XMLでグラデーションを描画するためには、グラデーションの始まりと終わりの色の16進数を入力する必要があるからです。エンジニアがカラーピッカーを立ち上げ、RGBを取得し、16進数に変換する・・・なんて非常に手間がかかります。

というわけで、画像を引数として与えると、XMLを生成してくれるPythonスクリプトを書きました。画像ライブラリとしてPILが必要です。
GitHub

python generateDrawableXML.py [img_path]
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from PIL import Image

def getCenterList(_list, order=1):
    if order > 0:
        return [i for (i, x) in enumerate(_list) if x == max(_list)]
    else:
        return [i for (i, x) in enumerate(_list) if x == min(_list)]

def getHexColor(rgb):
    return '#FF' + getHexStr(rgb[0]) + getHexStr(rgb[1]) + getHexStr(rgb[2])

def getHexStr(color):
    hexStr = hex(color)[2:].upper()
    return hexStr if len(hexStr) == 2 else '0' + hexStr

def main(path):
    img = Image.open(path)
    img = img.resize((1, img.size[1]))
    img = img.convert("RGB")

    rgbs        = list(img.getdata())
    height      = len(rgbs)
    startRGB    = rgbs[0]
    endRGB      = rgbs[len(rgbs) - 1]
    centerRGB   = None
    centerIndex = 0

    rs, gs, bs = [], [], []
    for rgb in rgbs:
        rs.append(rgb[0])
        gs.append(rgb[1])
        bs.append(rgb[2])

    for i in [-1, 1]:
        centerSet = set(getCenterList(rs, i)) & set(getCenterList(gs, i)) & set(getCenterList(bs, i))
        if len(centerSet) == 0: continue
        index = list(centerSet)[0]
        if index != 0 and index != (height - 1):
            centerRGB   = rgbs[index]
            centerIndex = index

    centerStr = ""
    if centerRGB:
        centerStr = """
        android:centerColor="%s"
        android:centerY="%s"
        """ % (getHexColor(centerRGB), round(float(centerIndex) / float(height - 1), 1))


    print """
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:angle="270"
        android:type="linear"
        android:startColor="%s"
        android:endColor="%s"%s
        />
</shape>""" % (getHexColor(startRGB), getHexColor(endRGB), centerStr)

if __name__ == '__main__':
    argvs = sys.argv
    if len(argvs) != 2:
        print("python " + argvs[0] + " [img_path]")
    else:
        main(argvs[1])

実行すると下記XMLが生成されます。
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:angle="270"
        android:type="linear"
        android:startColor="#FF330F55"
        android:endColor="#FFC45D19"
        />
</shape>

また、center要素がある画像でも大丈夫。

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:angle="270"
        android:type="linear"
        android:startColor="#FFFFC081"
        android:endColor="#FFFFA349"
        android:centerColor="#FFFF8101"
        android:centerY="0.6"
        />
</shape>

※横方向のグラデーションや、円型のグラデーションには対応していません。

2012年12月2日日曜日

ジオメディアサミット2012に参加した

このエントリーをはてなブックマークに追加
 普段、プログラムをペッと貼るだけのblogだけど、たまにはこういうのも書いてみる。

ジオメディアサミット に参加してきた。面白い事例があったのでいくつか紹介

  1. CITO
    GPS情報を頼りに、ユーザ間で仮想の宝物を隠して見つけ合ったりするGeocachingというサービスがあるんだけど、宝探しをしている間はGPSから割り出した周辺をウロウロと歩きまわる必要がある。そこで、その間にゴミを拾おうというのがCITO (Cache In Trash Out)のコンセプト。
    ピリカ
    のユーザでも、犬の散歩中やラジオ体操に行く途中、ランニング中など、「ながら」でのゴミ拾いを行う方が多いので、ゴミ拾いはGeocachingとの相性が非常にいいと思う。

  2. Navitimeのカープローブ
    Navitimeでは、サービスCAR NAVITIMEのユーザから送信されるGPS測位データを収集し、渋滞情報の解析に役立てている。センサを持つモビリティの問題である電池寿命も、車から電源を確保できるので問題ない。データ量も圧倒的で、VICSを利用した渋滞情報とは違うアプローチで興味深い。

    参考までに、車ではなく人にセンサ機器を持たせ、周辺状況をセンシングするヒューマンプローブという手法も紹介。
    東京大学空間情報科学研究センターの中の人の流れプロジェクトでは、各都市圏のパーソントリップ調査データをもとに人の位置・時間情報を取得することができる。パーソントリップ調査データは、人が"いつ、どこからどこへ移動したか"を調査したもので、例えばAさんは「8:00に家を出発→8:15に◯◯駅発→8:40に△△駅着→9:00に会社着」などである。ただ、これだと地点間の移動のみで、実際にどのような経路を辿ったか?ということがわからないので、人の流れプロジェクトでは、途中経路を推測により補間して1分毎の人の移動経路を提供している。
    ただ、パーソントリップ調査データは、アンケートで実施しているため、正確性が乏しい。実際には、8:13に家を出たにも関わらず、アンケート上では8:15としたり、場合によっては8:00と書いてしまうこともある。つまり、切りの良い時刻にデータが集まってしまい、現実データと観測データが乖離してしまう。(ただ、これは2年ほど前の時点で、今はどうなっているか不明)
    最近だと、東日本大震災の際の人の移動経路を動画にしている。



  3. Geo-Fuse
    georepublic社のGeo-Fuseは、地域別統計データを地図上にマッピングする際の煩雑な作業をなくすサービスである。説明スライドはコチラ。プログラムを一切書くことなく、統計データのマッピングができて非常に便利。
    ちなみに東京23区別ピリカ数はコチラから見れます。