<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>橋本商会</title>
	<atom:link href="http://shokai.org/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://shokai.org/blog</link>
	<description>なんか作ったりした記録を忘れないうちに書くblog</description>
	<lastBuildDate>Sat, 13 Mar 2010 06:02:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<atom:link rel="hub" href="http://pubsubhubbub.appspot.com/" />
			<item>
		<title>mbed NXP LPC1768を買った</title>
		<link>http://shokai.org/blog/archives/5085</link>
		<comments>http://shokai.org/blog/archives/5085#comments</comments>
		<pubDate>Fri, 12 Mar 2010 19:05:33 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[mbed]]></category>
		<category><![CDATA[NXP LPC1768]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=5085</guid>
		<description><![CDATA[
rain_yukizoraが東京に来ていて、2人でスタバでmbedをいじったりした。
Basic StampやGainerのように、ブレッドボードに刺す事を前提にピンが裏に出ている。でもその時はブレッドボードを持ち歩い [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://amenotiyukizora.blog76.fc2.com/">rain_yukizora</a>が東京に来ていて、2人でスタバでmbedをいじったりした。<br />
Basic StampやGainerのように、ブレッドボードに刺す事を前提にピンが裏に出ている。でもその時はブレッドボードを持ち歩いて無かったので、基板上のLEDとシリアル通信等を試した。ピンク色の物体は鞄の中でピンが折れないように基盤裏につけてる梱包材。<br />
<br />
<a href="http://www.flickr.com/photos/shokai/4426890661/" title="R0014222.JPG by shokai, on Flickr"><img src="http://farm5.static.flickr.com/4017/4426890661_f4a2e4cd9c.jpg" width="500" height="375" alt="R0014222.JPG" /></a><br />
<br />
mbedはエディタとコンパイラがwebサービス側にあり、開発は全てwebブラウザ上で行う。そしてできたバイナリをダウンロードしてマイコンに書き込み、実行させるという謎の16bitマイコンボード。<br />
<br />
開発言語はC++。どうやら高価な商法コンパイラとライブラリ群がサーバー側にあるらしい。<br />
例えばHTTPClientのライブラリがあり、DNSなども解決してくれるので<a href="http://mbed.org/projects/cookbook/wiki/EMAC/HTTPClient">twitterに認証してtweetする</a>とかが簡単にできたりする。40円ぐらいで売ってるEhternetコネクタをそのまま接続するだけで<a href="http://mbed.org/projects/cookbook/wiki/EMAC">LANケーブルが刺せるようになる</a>とか、既にいろいろ揃っている。Audio IOやリチウムポリマー電池を使うための回路もボード上にあるように見える。<br />
<br />
<br />
<a href="http://mbed.org/">mbed.org</a>のトップページに貼られているビデオを見れば雰囲気がわかる。<br />
<object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/7LPDRcahhUE&#038;hl=ja_JP&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/7LPDRcahhUE&#038;hl=ja_JP&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object><br />
<br />
<br />
■購入<br />
<a href="http://www.switch-science.com/products/detail.php?product_id=250">スイッチサイエンス</a>で6000円台後半で買った。秋月では<a href="http://akizukidenshi.com/catalog/g/gM-03596/">6000円で売ってる</a>けど、スイッチサイエンスで物を買った事が無かったので買ってみた。注文した翌日に届いて驚いた。<br />
秋月の方は「評価キット」という名前でCDや箱やケーブルなどが付いてきて得な様に見えるけど、スイッチサイエンスの方にもちゃんと付いてた。<br />
<br />
しばらくの間は6000円ぐらいで、そのうち1万円ぐらいに値上げするらしい。<br />
<br />
<br />
<br />
■アカウントを取る<br />
mbedをUSBケーブルでMacに接続すると、USBドライブとしてマウントされる。（Windowsでも同様）<br />
<br />
<br />
開くとMBED.HTMというファイルが入っている<br />
<a href="http://www.flickr.com/photos/shokai/4427682172/" title="ピクチャ 1 by shokai, on Flickr"><img src="http://farm5.static.flickr.com/4048/4427682172_754a45a45b_o.png" width="373" height="305" alt="ピクチャ 1" /></a><br />
<br />
<br />
webブラウザが開き、<a href="https://mbed.org/account/login/?next=/">アカウント登録画面</a>に行く。この画面は普通に誰でも見れるけど、USBデバイスとしてmbedが刺さっていないとsignupできないようになっている。どうやっているのかな・・・<br />
<br />
<br />
アカウントを取るとこんなプロフィールページができる。publishしたnotebookやプログラムが見れる。<br />
<a href="http://mbed.org/users/shokai/">http://mbed.org/users/shokai/</a><br />
<br />
<br />
<br />
■コードを書く<br />
ログインして右上のcompilerのリンクから、IDEが開く。新規プロジェクト作成して、<a href="http://mbed.org/handbook/">handbook</a>を参考にしながらコードを書いてみた。<br />
まず新規プロジェクト作成した時点でとりあえずLEDを一つ0.5秒間隔で点滅させるプログラムが書かれているので、ああこういう感じなのか〜とすんなり入れる。<br />
<a href="http://www.flickr.com/photos/shokai/4427682300/" title="ピクチャ 4 by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2773/4427682300_87cdcb5dfc_o.png" width="871" height="727" alt="ピクチャ 4" /></a><br />
<br />
main.cpp<br />
<pre class="prettyprint">
#include&nbsp;"mbed.h"<br />
<br />
Serial&nbsp;pc(USBTX,&nbsp;USBRX);&nbsp;//&nbsp;tx,&nbsp;rx<br />
<br />
DigitalOut&nbsp;myled1(LED1);<br />
DigitalOut&nbsp;myled2(LED2);<br />
<br />
int&nbsp;main()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;while(1)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myled1&nbsp;=&nbsp;1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myled2&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc.printf("led&nbsp;1&nbsp;on\r\n");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait(0.5);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myled1&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myled2&nbsp;=&nbsp;1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc.printf("led&nbsp;2&nbsp;on\r\n");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait(0.2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</pre>
左上の「Compile」ボタンを押すとコンパイルされる。エラーが無い場合、いきなりプログラムがダウンロードされる。<br />
<br />
<br />
<br />
■プログラムを書き込み、実行する<br />
USBドライブとしてマウントされてるmbedにbinを投げ込んで、基板上のリセットボタンを押すと実行される。<br />
<a href="http://www.flickr.com/photos/shokai/4427682220/" title="ピクチャ 2 by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2718/4427682220_af4b15455f_o.png" width="363" height="272" alt="ピクチャ 2" /></a><br />
<br />
<br />
基板上のLEDが点滅すると同時に、シリアル通信もちゃんと来ていた。<br />
1つのUSBコネクタだけど、同時にUSBストレージと /dev/tty.usbmodem622 の2つのデバイスとして認識されている。<br />
<a href="http://www.flickr.com/photos/shokai/4427807430/" title="ピクチャ 7 by shokai, on Flickr"><img src="http://farm5.static.flickr.com/4058/4427807430_4069267b6f_o.png" width="753" height="482" alt="ピクチャ 7" /></a><br />
MacやLinuxではドライバは必要ない。Windowsも<a href="http://mbed.org/handbook/SerialPC">SerialPC – handbook – Trac</a>にあるドライバをインストールすれば使えるらしい。<br />
<br />
<br />
■プログラムを公開する<br />
エディタ画面でプロジェクト名を右クリックして「publish」ができる。プロジェクト名に &#8211; (ハイフン)が入っているとHTTPステータスコード500でconnection errorというのが出て、publishできない。 _ (アンダーバー)を使った。<br />
<a href="http://www.flickr.com/photos/shokai/4426994897/" title="ピクチャ 5 by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2803/4426994897_6605067430.jpg" width="414" height="405" alt="ピクチャ 5" /></a><br />
<br />
公開したプログラム<br />
<a href="http://mbed.org/users/shokai/programs/led_serial/606nu/">led_serial | mbed</a><br />
<br />
コードがブラウザ上で見れない。まあそのうち改良されるだろう。<br />
コメントや星を付けれるし、「import program into compiler」を押せば他人のプログラムでもすぐ自分で編集できる。<br />
importは、他にもtarで固められたファイルかSVNのリポジトリのアドレスを指定する事もできる。<br />
<br />
<br />
<br />
■感想<br />
便利なライブラリが揃っていて、現状でもう十分面白いボードになっていると思う。<br />
<br />
あとはネットワーク上にあってユーザアカウントがあるのだから、もっと色々できそう。組み込み系は開発効率よりもコミュニケーション効率の低さがまずいと思うので、web上にエディタがあるという事がそのへんをどうにかする手段になりそう。<br />
<br />
人の作ったコードをimportするだけではなくライブラリとして使えるようになると思うので、何かRSSのparserとかjsonのシリアライザとかから作っていってみるとリソースが積み重なって面白い事になるかも。<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/5085/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>モバイルSuicaの履歴をtwitterに流したかった</title>
		<link>http://shokai.org/blog/archives/5072</link>
		<comments>http://shokai.org/blog/archives/5072#comments</comments>
		<pubDate>Tue, 23 Feb 2010 08:38:03 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[mobilesuica]]></category>
		<category><![CDATA[nokogiri]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[WWW::Mechanize]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=5072</guid>
		<description><![CDATA[
xtunnelのためにスクレイピングの勉強をしていて、Mechanize+hpricotからMechanize+nokogiriの組み合わせに乗り換えようと色々と使ってみている中でできた物のひとつ。
昔しゃお先生がやっ [...]]]></description>
			<content:encoded><![CDATA[<p>
xtunnelのためにスクレイピングの勉強をしていて、Mechanize+hpricotからMechanize+nokogiriの組み合わせに乗り換えようと色々と使ってみている中でできた物のひとつ。<br />
昔しゃお先生がやっていたのを俺もやりたくて3ヶ月ぐらい前に作ったけど、mobilesuica.comのおサイフケータイ使用履歴は1日一度早朝に更新される仕様に変更されたらしくボツになった。<br />
<br />
<br />
結局idやcssなどの手がかりが無くて手動で要素を取り出す事になり、nokogiriはHTMLタグを除去するのにしか使わなかった<br />
MobileSuica.rb<br />
<pre class="prettyprint">
#!/usr/bin/env&nbsp;ruby<br />
#&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-<br />
require&nbsp;'rubygems'<br />
require&nbsp;'nokogiri'<br />
require&nbsp;'mechanize'<br />
require&nbsp;'kconv'<br />
<br />
module&nbsp;MobileSuica<br />
&nbsp;&nbsp;def&nbsp;MobileSuica.get(user,pass)<br />
&nbsp;&nbsp;&nbsp;&nbsp;agent&nbsp;=&nbsp;WWW::Mechanize.new<br />
&nbsp;&nbsp;&nbsp;&nbsp;agent.user_agent_alias&nbsp;=&nbsp;'Windows&nbsp;IE&nbsp;7'<br />
&nbsp;&nbsp;&nbsp;&nbsp;page&nbsp;=&nbsp;agent.get('http://www.mobilesuica.com/iq/ir/SuicaDisp.aspx?returnId=SFRCMMEPC03')<br />
&nbsp;&nbsp;&nbsp;&nbsp;login_form&nbsp;=&nbsp;page.forms_with(:name&nbsp;=&gt;&nbsp;'form1').first<br />
&nbsp;&nbsp;&nbsp;&nbsp;login_form.fields_with(:name&nbsp;=&gt;&nbsp;'MailAddress').first.value&nbsp;=&nbsp;user<br />
&nbsp;&nbsp;&nbsp;&nbsp;login_form.fields_with(:name&nbsp;=&gt;&nbsp;'Password').first.value&nbsp;=&nbsp;pass<br />
&nbsp;&nbsp;&nbsp;&nbsp;page&nbsp;=&nbsp;login_form.click_button<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;page.body.toutf8.split(/&lt;tr&gt;/).delete_if{|tr|<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;!(tr&nbsp;=~&nbsp;/&amp;yen;/m)<br />
&nbsp;&nbsp;&nbsp;&nbsp;}.map{|tr|<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr.gsub(/\n/,"").split(/\r/)[0..5].map{|line|&nbsp;#&nbsp;月日,種別,利用場所,種別,利用場所,残額<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nokogiri(line).inner_text.chomp.strip.gsub(/[\t　]/,"")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;end<br />
end<br />
</pre>
<br />
<br />
mobilesuicaのユーザ名、パスワードで履歴を2次元配列として取り出せる。<br />
<pre class="prettyprint">
require 'MobileSuica'<br />
MobileSuica.get("user", "pass")<br />
</pre>
月日、種別、利用場所、種別、利用場所、残額の順になる<br />
<pre>
01/30<br />
入<br />
川崎<br />
出<br />
横浜<br />
5,110<br />
01/30<br />
入<br />
相鉄横浜<br />
窓出<br />
川崎<br />
5,320<br />
</pre>
<br />
<br />
<br />
履歴のうち最新の駅名をtwitterに投稿する。-dつけて起動するとdaemonになる<br />
tweet-mobilesuica.rb<br />
<pre class="prettyprint">
#!/usr/bin/env&nbsp;ruby<br />
#&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-<br />
require&nbsp;'rubygems'<br />
require&nbsp;'webrick'<br />
require&nbsp;'twitter'<br />
require&nbsp;'MobileSuica'<br />
<br />
def&nbsp;start(conf)<br />
&nbsp;&nbsp;loop&nbsp;do<br />
&nbsp;&nbsp;&nbsp;&nbsp;begin<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;first&nbsp;=&nbsp;MobileSuica.get(conf["suica_user"],&nbsp;conf["suica_pass"]).first<br />
&nbsp;&nbsp;&nbsp;&nbsp;rescue<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;first&nbsp;=&nbsp;nil<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;first&nbsp;!=&nbsp;nil<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last&nbsp;=&nbsp;first&nbsp;if&nbsp;!last<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;first&nbsp;!=&nbsp;last&nbsp;#&nbsp;1回前に取得した履歴と比較<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;first<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;'-'*10<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;first[1]&nbsp;==&nbsp;'入'&nbsp;&amp;&amp;&nbsp;first[3]&nbsp;==&nbsp;'出'&nbsp;#&nbsp;降車履歴の時<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message&nbsp;=&nbsp;first[4].chomp.strip+"なう&nbsp;(suica)"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;!(message&nbsp;=~&nbsp;/#{conf["ngwords"]}/)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;conf["nopost"]&nbsp;!=&nbsp;true<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpAuth&nbsp;=&nbsp;Twitter::HTTPAuth.new(conf["twitter_user"],&nbsp;conf["twitter_pass"])<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tw&nbsp;=&nbsp;Twitter::Base.new(httpAuth)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tw.update(message)&nbsp;#&nbsp;twitter&nbsp;post<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;message<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last&nbsp;=&nbsp;first<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;sleep&nbsp;60*60*1.5&nbsp;#&nbsp;1時間半待つ<br />
&nbsp;&nbsp;end<br />
end<br />
<br />
conf&nbsp;=&nbsp;YAML::load&nbsp;open&nbsp;File.dirname(__FILE__)+'/config.yaml'<br />
if&nbsp;ARGV[0]&nbsp;==&nbsp;'-d'<br />
&nbsp;&nbsp;WEBrick::Daemon.start&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;start(conf)<br />
&nbsp;&nbsp;}<br />
else<br />
&nbsp;&nbsp;start(conf)<br />
end<br />
</pre>
<br />
<br />
設定ファイル。自宅の駅名などはngwordsに入れておく<br />
config.yaml<br />
<pre class="prettyprint">
#&nbsp;config.yaml<br />
#&nbsp;mobilesuica.com&nbsp;user/pass<br />
suica_user&nbsp;:&nbsp;'username@docomo.ne.jp'<br />
suica_pass&nbsp;:&nbsp;'12345678'<br />
<br />
#&nbsp;twitter&nbsp;user/pass<br />
twitter_user&nbsp;:&nbsp;'shokai'<br />
twitter_pass&nbsp;:&nbsp;'password'<br />
<br />
#&nbsp;postしない駅名を正規表現で<br />
ngwords&nbsp;:&nbsp;"(東京|横浜)"<br />
<br />
#&nbsp;for&nbsp;debug<br />
#nopost&nbsp;:&nbsp;"true"<br />
</pre>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/5072/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使ってるchrome extensions</title>
		<link>http://shokai.org/blog/archives/5062</link>
		<comments>http://shokai.org/blog/archives/5062#comments</comments>
		<pubDate>Mon, 15 Feb 2010 12:24:01 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=5062</guid>
		<description><![CDATA[
LDRにいろいろ付ける系のgreasemonkeyはGM_系の関数がまだ実装されてないので、LDRだけはFirefoxで見ている。
テキストエリアを外部テキストエディタで開くIt&#8217;s all text相当の [...]]]></description>
			<content:encoded><![CDATA[<p>
LDRにいろいろ付ける系のgreasemonkeyはGM_系の関数がまだ実装されてないので、LDRだけはFirefoxで見ている。<br />
テキストエリアを外部テキストエディタで開くIt&#8217;s all text相当の拡張もあったけど、server側のインストールやら起動が面倒なのでblog書くのはFirefox使う。<br />
<br />
普段の調べ物とSBMへの投稿、twitterぐらいならこれらを入れてあれば十分。一番重要なのはTaberarelooでdeliciousとはてなブックマークとlivedoor clipにすばやくクロスポストができる事。<br />
<br />
意外なことにchrome keyconfigにLDRizeが入っている。AdBlock+は要素の指定がなんか面倒くさい。<br />
<br />
pbtweet、chrome FullFeed、fldr_show_fc2_images.user.jsはMacはdev版のchromeなら使える。<br />
<br />
GM_系が一通り実装されるのと、URLバーの履歴検索がFirefoxみたいに一部一致でも利用頻度の高い順にソートされて表示されるようになればFirefoxから乗り換えられるな。<br />
chromeのURLバーは前方一致が優先されるので、例えばりそな銀行のログインページに行きたい場合、Firefoxだと「res」まで打てば候補にすぐ出てくるが、chromeなら「ib.res」まで打ち込まないと <a href="https://ib.resonabank.co.jp/IB/0102/SC_N_0102_010.aspx">https://ib.resonabank.co.jp/IB/0102/SC_N_0102_010.aspx</a> が出てこない。ibとか思い出せない。「りそな→reso」なら連想できる。URLがおかしい気もするが、サービス毎にサブドメイン振っているケースはいっぱいあるし、サブドメインは覚えられない。 <a href="https://e-navi.rakuten-kc.co.jp/ava_top">https://e-navi.rakuten-kc.co.jp/ava_top</a> とか。<br />
<a href="http://www.flickr.com/photos/shokai/4358526959/" title="chrome extensions by shokai, on Flickr"><img src="http://farm5.static.flickr.com/4044/4358526959_e7aac2a818_o.png" width="811" height="789" alt="chrome extensions" /></a><br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/5062/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ユビキタスコンテンツシンポジウム 2010</title>
		<link>http://shokai.org/blog/archives/5058</link>
		<comments>http://shokai.org/blog/archives/5058#comments</comments>
		<pubDate>Mon, 08 Feb 2010 10:51:56 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Event]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=5058</guid>
		<description><![CDATA[
来週16日(火)に、日吉でシンポジウムがあります。事前予約の受付がはじまりました

本人そっくりのロボットの石黒先生や、Leading Edge Designの山中俊治先生が来ます。参加費無料。
xtel: Ubiqu [...]]]></description>
			<content:encoded><![CDATA[<p>
来週16日(火)に、日吉でシンポジウムがあります。事前予約の受付がはじまりました<br />
<br />
<a href="http://robot.watch.impress.co.jp/cda/news/2006/07/21/93.html">本人そっくりのロボット</a>の石黒先生や、<a href="http://www.lleedd.com/">Leading Edge Design</a>の山中俊治先生が来ます。参加費無料。<br />
<ul><li><a href="http://xtel.sfc.keio.ac.jp/jp/2010/01/_2010.html">xtel: Ubiquitous Content Project: ユビキタスコンテンツシンポジウム 2010　開催のお知らせ</a></li></ul>
<br />
以下リリース文引用<br />
</p>
<blockquote><p>
2010年2月16日、「ユビキタスコンテンツ製作支援システムの研究」は、神奈川県横浜市港北区日吉・藤原記念ホールにて、「ユビキタスコンテンツシンポジウム2010」を開催致します。<br />
<br />
本プロジェクトは、JSTの戦略的創造研究推進事業CRESTによって支援を受けたプロジェクトで、平成16年度から5年間の研究プロジェクトとして「ユビキタスコンテンツ」という新しいコンテンツジャンルを提案し、基盤技術開発、デザイン理論構築、コンテンツ制作の3軸から研究を実施してまいりました。<br />
<br />
ユビキタスコンテンツは、私たちの衣食住遊に新たな経験と感動をもたらすコンテンツです。それらはモノや環境に溶け込み、ヒトや状況によってダイミックに変化します。また、ネットワークと接続されることにより各々のコンテンツのユーザ経験が蓄積され、蓄積されたデータをもとにコンテンツ同士の連動が可能となります。<br />
<br />
このようなユビキタスコンテンツを制作するためのプラットフォームとしてわれわれが開発したxtelは、近距離無線通信が可能な小型基板moxa、 MCUボードのためのprogramming・runtime環境Talktic、動画、音声などの連続情報を扱うことが可能なP2Pネットワークライブラリ EntityCollaborator、コンテンツ経験の連動と蓄積を可能にするwebサービスLifeの4つのツールで構成されています。<br />
<br />
さらに、本プロジェクトの成果であるユビキタスコンテンツのためのデザイン理論は、デザイン思考とティンカリングと呼ばれるプロセスを通して、効率よく良質なユビキタスコンテンツを創出することを支援します。このデザイン理論は、xtelの開発環境にも生かされており、デザイン思考とティンカリングを実行しやすくなるように、xtelの開発環境が設計・構築されています。<br />
<br />
本プロジェクトを締めくくる今回のシンポジウムでは、ロボット研究者の石黒 浩 大阪大学大学院教授、プロダクトデザイナーの山中 俊治 慶應義塾大学環境情報学部教授をゲストスピーカとしてお招きし、トークセッションを行います。また、シンポジウムでは、5年間の活動内容をまとめた書籍「xtel: 生活を豊かにするインタラクションデザイン」をお配りする予定です。<br />
<br />
日時・場所：<br />
　　2010年2月16日(火)　10:30-15:30 (開場 10:00)<br />
　　慶應義塾大学日吉キャンパス 藤原記念ホール<br />
<br />
<br />
プログラム：<br />
　　10:30 &#8211; 10:40 代表挨拶<br />
　　10:40 &#8211; 12:10 「親しみのデザイン」<br />
　　　　　　　　　　　石黒 浩 大阪大学大学院 基礎工学研究科 教授<br />
　　　　　　　　　　　奥出 直人 慶應義塾大学 メディアデザイン研究科 教授<br />
　　12:10 &#8211; 13:30 　休憩<br />
　　13:30 &#8211; 15:00 「美しさのデザイン」<br />
　　　　　　　　　　　山中 俊治 慶應義塾大学 環境情報学部 教授<br />
　　　　　　　　　　　稲蔭 正彦 慶應義塾大学 メディアデザイン研究科 教授<br />
　　15:00 閉会挨拶<br />
<br />
<br />
事前登録方法：<br />
　　シンポジウムへのご来場をお考えの方は、<br />
　　・お名前<br />
　　・所属<br />
　　・電話番号<br />
　　・メールアドレス<br />
　　を添えて、office [at] dlb.sfc.keio.ac.jpまでメールをお送りください。<br />
<br />
　　なおシンポジウムの詳細は随時 webにてご連絡差し上げます。<br />
　　http://xtel.sfc.keio.ac.jp/<br />
<br />
<br />
本件に関するお問い合わせ先<br />
　　〒223-8526　神奈川県横浜市港北区日吉4-1-1　<br />
　　慶應義塾大学日吉キャンパス 協生館C6S04<br />
　　CREST ユビキタスコンテンツプロジェクト<br />
　　Tel. 045-564-2483<br />
　　Fax. 045-564-2540<br />
　　E-mail: office [at] dlb.sfc.keio.ac.jp<br />
</p></blockquote>
<p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/5058/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>wavファイルの音量を調整する</title>
		<link>http://shokai.org/blog/archives/5053</link>
		<comments>http://shokai.org/blog/archives/5053#comments</comments>
		<pubDate>Sat, 06 Feb 2010 06:28:55 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[sound]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[wav]]></category>
		<category><![CDATA[WavFile.rb]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=5053</guid>
		<description><![CDATA[
音量の小さいwavファイルのボリュームを上げる。上げすぎて音割れしないようにする。

前に作ったWavFile.rbを使ったら簡単にできた
橋本商会 » Rubyでwavファイルをいじる WavFile.rbを作った
 [...]]]></description>
			<content:encoded><![CDATA[<p>
音量の小さいwavファイルのボリュームを上げる。上げすぎて音割れしないようにする。<br />
<br />
前に作った<a href="http://shokai.org/projects/ruby-wavfile/index.cgi/file/a324224bc098/WavFile.rb">WavFile.rb</a>を使ったら簡単にできた<br />
<ul><li><a href="http://shokai.org/blog/archives/4886">橋本商会 » Rubyでwavファイルをいじる WavFile.rbを作った</a></li></ul>
<br />
16ビットwavは+-32768、8ビットwavは+-128の範囲の配列で波形が表現されている。<br />
ソースのwavの波形を配列に取り出して、その中で最大の値を取りだし、全体を何倍すれば+-32768の間になるかの倍率を計算して全部かけ算すれば音量を調整できる。<br />
<br />
<a href="http://shokai.org/projects/ruby-wavfile/index.cgi/file/a324224bc098/maximizeVolume.rb">maximizeVolume.rb</a><br />
<pre class="prettyprint">
#!/usr/bin/env&nbsp;ruby<br />
#&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-<br />
#&nbsp;wavの音量を最大に調節する<br />
require&nbsp;File.dirname(__FILE__)&nbsp;+&nbsp;'/WavFile'<br />
<br />
if&nbsp;ARGV.size&nbsp;&lt;&nbsp;2<br />
&nbsp;&nbsp;puts&nbsp;'ruby&nbsp;maximizeVolume.rb&nbsp;input.wav&nbsp;output.wav'<br />
&nbsp;&nbsp;exit&nbsp;1<br />
end<br />
<br />
in_file&nbsp;=&nbsp;ARGV.shift<br />
out_file&nbsp;=&nbsp;ARGV.shift<br />
<br />
format,&nbsp;data&nbsp;=&nbsp;WavFile::read&nbsp;open(in_file)<br />
<br />
puts&nbsp;format.to_s<br />
<br />
bit&nbsp;=&nbsp;'s*'&nbsp;if&nbsp;format.bitPerSample&nbsp;==&nbsp;16&nbsp;#&nbsp;int16_t<br />
bit&nbsp;=&nbsp;'c*'&nbsp;if&nbsp;format.bitPerSample&nbsp;==&nbsp;8&nbsp;#&nbsp;signed&nbsp;char<br />
wavs&nbsp;=&nbsp;data.data.unpack(bit)<br />
<br />
puts&nbsp;"このwav中の最大音量:&nbsp;#{wavs.max}"<br />
<br />
volume_ratio&nbsp;=&nbsp;32768/wavs.max.to_f&nbsp;if&nbsp;format.bitPerSample&nbsp;==&nbsp;16<br />
volume_ratio&nbsp;=&nbsp;128/wavs.max.to_f&nbsp;if&nbsp;format.bitPerSample&nbsp;==&nbsp;8<br />
puts&nbsp;"補正倍率:&nbsp;#{volume_ratio}"<br />
<br />
wavs_fixed&nbsp;=&nbsp;wavs.map{|w|<br />
&nbsp;&nbsp;(w*volume_ratio).to_i<br />
}<br />
puts&nbsp;"補正されたwav中の最大音量:&nbsp;#{wavs_fixed.max}"<br />
<br />
data.data&nbsp;=&nbsp;wavs_fixed.pack(bit)<br />
<br />
open(out_file,&nbsp;"w"){|out|<br />
&nbsp;&nbsp;WavFile::write(out,&nbsp;format,&nbsp;[data])<br />
}<br />
</pre>
<br />
<br />
使う<br />
<pre>
ruby maximizeVolume.rb input.wav out.wav<br />
</pre>
<br />
約24倍されてout.wavに保存された<br />
<pre>
フォーマットID: 1<br />
チャンネル数: 1<br />
サンプリングレート: 44100 (Hz)<br />
byte per sec: 88200<br />
bit per sample: 16 <br />
ブロックサイズ: 2<br />
このwav中の最大音量: 1335<br />
補正倍率: 24.5453183520599<br />
補正されたwav中の最大音量: 32768<br />
</pre>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/5053/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>json_builderを特殊文字のエスケープ、true、false、nullに対応させた</title>
		<link>http://shokai.org/blog/archives/5046</link>
		<comments>http://shokai.org/blog/archives/5046#comments</comments>
		<pubDate>Sat, 30 Jan 2010 01:56:23 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[json_builder.h]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=5046</guid>
		<description><![CDATA[
前：橋本商会 » C++でmapやvectorをJSON出力するjson_builder.hを作った


ダブルクオートなどを含む文字列を値に保持するためのエスケープ処理にboost::regexを使ったので、libboost_regex-mt.aをコンパイル時に読み込まないとならなくなった → Makefileの例
まさかboost::regex_replaceで頭にバックスラッシュをつけるのに、バックスラッシュ4つで置換するとは思わなかった


こんな風に使う。true, false, nullを入れられるようになった
test.cpp

#include&#160;&#60;iostream&#62;
#include&#160;&#60;string&#62;
#include&#160;&#60;map&#62;
#include&#160;&#60;boost/any.hpp&#62;
#include&#160;"../json_builder.h"

int&#160;main(int&#160;argc,&#160;char*&#160;argv[]){
&#160;&#160;std::map&#60;string,boost::any&#62;&#160;user;
&#160;&#160;user["name"]&#160;=&#160;std::string("shokai");
&#160;&#160;user["fullname"]&#160;=&#160;std::string("sho&#160;hashimoto");
&#160;&#160;user["age"]&#160;=&#160;25;
&#160;&#160;user["test"]&#160;=&#160;1.23;
&#160;&#160;user["null"]&#160;=&#160;json_builder::null;
&#160;&#160;user["true"]&#160;=&#160;true;
&#160;&#160;user["false"]&#160;=&#160;false;

&#160;&#160;string&#160;json&#160;=&#160;json_builder::toJson(user);
&#160;&#160;cout&#160;&#60;&#60;&#160;json&#160;&#60;&#60;&#160;endl;
&#160;&#160;return&#160;0;
}



実行結果

{"age":"25","false":false,"fullname":"sho hashimoto","name":"shokai","null":null,"test":"1.23","true":true}




C++でnullを表現するために適当な構造体を定義してしまったけど、こういうので良いんだろうか？
json_builder.h

#include&#160;&#60;iostream&#62;
#include&#160;&#60;string&#62;
#include&#160;&#60;map&#62;
#include&#160;&#60;vector&#62;
#include&#160;&#60;boost/any.hpp&#62;
#include&#160;&#60;boost/tuple/tuple.hpp&#62;
#include&#160;&#60;boost/format.hpp&#62;
#include&#160;&#60;boost/foreach.hpp&#62;
#include&#160;&#60;boost/regex.hpp&#62;

using&#160;namespace&#160;std;
using&#160;namespace&#160;boost;

#define&#160;null&#160;json_null()

namespace&#160;json_builder{
&#160;&#160;struct&#160;json_null{};

&#160;&#160;string&#160;toJson(any&#160;value){
&#160;&#160;&#160;&#160;if(value.type()&#160;==&#160;typeid(vector&#60;any&#62;)){
&#160;&#160;&#160;&#160;&#160;&#160;string&#160;result_str;
&#160;&#160;&#160;&#160;&#160;&#160;vector&#60;any&#62;&#160;vec&#160;=&#160;any_cast&#60;vector&#60;any&#62;&#160;&#62;(value);
&#160;&#160;&#160;&#160;&#160;&#160;for(int&#160;i&#160;=&#160;0;&#160;i&#160;&#60;&#160;vec.size();&#160;i++){
	result_str&#160;+=&#160;toJson(vec[i]);
	if(i&#160;&#60;&#160;vec.size()-1)&#160;result_str&#160;+=&#160;",";
&#160;&#160;&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;&#160;&#160;result_str&#160;=&#160;str(format("[%s]")&#160;%&#160;result_str);
&#160;&#160;&#160;&#160;&#160;&#160;return&#160;result_str;
&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;else&#160;if(value.type()&#160;==&#160;typeid(map&#60;string,any&#62;)){
&#160;&#160;&#160;&#160;&#160;&#160;string&#160;result_str;
&#160;&#160;&#160;&#160;&#160;&#160;map&#60;string,any&#62;&#160;m&#160;=&#160;any_cast&#60;map&#60;string,any&#62;&#160;&#62;(value);
&#160;&#160;&#160;&#160;&#160;&#160;string&#160;key;
&#160;&#160;&#160;&#160;&#160;&#160;any&#160;value;
&#160;&#160;&#160;&#160;&#160;&#160;int&#160;i&#160;=&#160;0;
&#160;&#160;&#160;&#160;&#160;&#160;BOOST_FOREACH(tie(key,value),&#160;m){
	result_str&#160;+=&#160;str(format("\"%s\":%s")&#160;%&#160;key&#160;%&#160;toJson(value));
	if(++i&#160;&#60;&#160;m.size())&#160;result_str&#160;+=&#160;",";
&#160;&#160;&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;&#160;&#160;result_str&#160;=&#160;str(format("{%s}")&#160;%&#160;result_str);
&#160;&#160;&#160;&#160;&#160;&#160;return&#160;result_str;
&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;else&#160;if(value.type()&#160;==&#160;typeid(json_null)){
&#160;&#160;&#160;&#160;&#160;&#160;return&#160;string("null");
&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;else&#160;if(value.type()&#160;==&#160;typeid(string)){
&#160;&#160;&#160;&#160;&#160;&#160;return&#160;str(format("\"%s\"")&#160;%&#160;
		&#160;&#160;&#160;regex_replace(any_cast&#60;string&#62;(value),&#160;regex("[\"\'\\\\/]"),&#160;"\\\\$0"));
&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;else&#160;if(value.type()&#160;==&#160;typeid(bool)){
&#160;&#160;&#160;&#160;&#160;&#160;if(any_cast&#60;bool&#62;(value))&#160;return&#160;string("true");
&#160;&#160;&#160;&#160;&#160;&#160;return&#160;string("false");
&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;else&#160;if(value.type()&#160;==&#160;typeid(int)){
&#160;&#160;&#160;&#160;&#160;&#160;return&#160;str(format("\"%d\"")&#160;%&#160;any_cast&#60;int&#62;(value));
&#160;&#160;&#160;&#160;}
&#160;&#160;&#160;&#160;else&#160;if(value.type()&#160;==&#160;typeid(double)){
&#160;&#160;&#160;&#160;&#160;&#160;return&#160;str(format("\"%d\"")&#160;%&#160;any_cast&#60;double&#62;(value));
&#160;&#160;&#160;&#160;}
&#160;&#160;}

}



]]></description>
			<content:encoded><![CDATA[<p>
前：<a href="http://shokai.org/blog/archives/5021">橋本商会 » C++でmapやvectorをJSON出力するjson_builder.hを作った</a><br />
<br />
<br />
ダブルクオートなどを含む文字列を値に保持するためのエスケープ処理にboost::regexを使ったので、libboost_regex-mt.aをコンパイル時に読み込まないとならなくなった → <a href="http://bitbucket.org/shokai/json-builder/src/abbc9d0a382d/test/Makefile">Makefileの例</a><br />
まさかboost::regex_replaceで頭にバックスラッシュをつけるのに、<a href="http://d.hatena.ne.jp/shokai/20100127/1264606980">バックスラッシュ4つで置換</a>するとは思わなかった<br />
<br />
<br />
こんな風に使う。true, false, nullを入れられるようになった<br />
<a href="http://bitbucket.org/shokai/json-builder/src/abbc9d0a382d/test/test.cpp">test.cpp</a><br />
<pre class="prettyprint">
#include&nbsp;&lt;iostream&gt;<br />
#include&nbsp;&lt;string&gt;<br />
#include&nbsp;&lt;map&gt;<br />
#include&nbsp;&lt;boost/any.hpp&gt;<br />
#include&nbsp;"../json_builder.h"<br />
<br />
int&nbsp;main(int&nbsp;argc,&nbsp;char*&nbsp;argv[]){<br />
&nbsp;&nbsp;std::map&lt;string,boost::any&gt;&nbsp;user;<br />
&nbsp;&nbsp;user["name"]&nbsp;=&nbsp;std::string("shokai");<br />
&nbsp;&nbsp;user["fullname"]&nbsp;=&nbsp;std::string("sho&nbsp;hashimoto");<br />
&nbsp;&nbsp;user["age"]&nbsp;=&nbsp;25;<br />
&nbsp;&nbsp;user["test"]&nbsp;=&nbsp;1.23;<br />
&nbsp;&nbsp;user["null"]&nbsp;=&nbsp;json_builder::null;<br />
&nbsp;&nbsp;user["true"]&nbsp;=&nbsp;true;<br />
&nbsp;&nbsp;user["false"]&nbsp;=&nbsp;false;<br />
<br />
&nbsp;&nbsp;string&nbsp;json&nbsp;=&nbsp;json_builder::toJson(user);<br />
&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;json&nbsp;&lt;&lt;&nbsp;endl;<br />
&nbsp;&nbsp;return&nbsp;0;<br />
}<br />
</pre>
<br />
<br />
実行結果<br />
<pre>
{"age":"25","false":false,"fullname":"sho hashimoto","name":"shokai","null":null,"test":"1.23","true":true}<br />
</pre>
<br />
<br />
<br />
C++でnullを表現するために適当な構造体を定義してしまったけど、こういうので良いんだろうか？<br />
<a href="http://bitbucket.org/shokai/json-builder/src/abbc9d0a382d/json_builder.h">json_builder.h</a><br />
<pre class="prettyprint">
#include&nbsp;&lt;iostream&gt;<br />
#include&nbsp;&lt;string&gt;<br />
#include&nbsp;&lt;map&gt;<br />
#include&nbsp;&lt;vector&gt;<br />
#include&nbsp;&lt;boost/any.hpp&gt;<br />
#include&nbsp;&lt;boost/tuple/tuple.hpp&gt;<br />
#include&nbsp;&lt;boost/format.hpp&gt;<br />
#include&nbsp;&lt;boost/foreach.hpp&gt;<br />
#include&nbsp;&lt;boost/regex.hpp&gt;<br />
<br />
using&nbsp;namespace&nbsp;std;<br />
using&nbsp;namespace&nbsp;boost;<br />
<br />
#define&nbsp;null&nbsp;json_null()<br />
<br />
namespace&nbsp;json_builder{<br />
&nbsp;&nbsp;struct&nbsp;json_null{};<br />
<br />
&nbsp;&nbsp;string&nbsp;toJson(any&nbsp;value){<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(value.type()&nbsp;==&nbsp;typeid(vector&lt;any&gt;)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;result_str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vector&lt;any&gt;&nbsp;vec&nbsp;=&nbsp;any_cast&lt;vector&lt;any&gt;&nbsp;&gt;(value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;vec.size();&nbsp;i++){<br />
	result_str&nbsp;+=&nbsp;toJson(vec[i]);<br />
	if(i&nbsp;&lt;&nbsp;vec.size()-1)&nbsp;result_str&nbsp;+=&nbsp;",";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result_str&nbsp;=&nbsp;str(format("[%s]")&nbsp;%&nbsp;result_str);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result_str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(map&lt;string,any&gt;)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;result_str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map&lt;string,any&gt;&nbsp;m&nbsp;=&nbsp;any_cast&lt;map&lt;string,any&gt;&nbsp;&gt;(value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;key;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;any&nbsp;value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BOOST_FOREACH(tie(key,value),&nbsp;m){<br />
	result_str&nbsp;+=&nbsp;str(format("\"%s\":%s")&nbsp;%&nbsp;key&nbsp;%&nbsp;toJson(value));<br />
	if(++i&nbsp;&lt;&nbsp;m.size())&nbsp;result_str&nbsp;+=&nbsp;",";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result_str&nbsp;=&nbsp;str(format("{%s}")&nbsp;%&nbsp;result_str);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result_str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(json_null)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;string("null");<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(string)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;str(format("\"%s\"")&nbsp;%&nbsp;<br />
		&nbsp;&nbsp;&nbsp;regex_replace(any_cast&lt;string&gt;(value),&nbsp;regex("[\"\'\\\\/]"),&nbsp;"\\\\$0"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(bool)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(any_cast&lt;bool&gt;(value))&nbsp;return&nbsp;string("true");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;string("false");<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(int)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;str(format("\"%d\"")&nbsp;%&nbsp;any_cast&lt;int&gt;(value));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(double)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;str(format("\"%d\"")&nbsp;%&nbsp;any_cast&lt;double&gt;(value));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
<br />
}<br />
</pre>
<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/5046/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>最近作ったYahooPipes</title>
		<link>http://shokai.org/blog/archives/5034</link>
		<comments>http://shokai.org/blog/archives/5034#comments</comments>
		<pubDate>Wed, 27 Jan 2010 07:22:50 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[YahooPipes]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=5034</guid>
		<description><![CDATA[
Pipes: 秋月電子 新製品FullFeed
秋月のRSSが無くなったので、新製品ページから取り出した。


Pipes: ストロベリー・リナックス FullFeed
strawberry-linux.comのnew [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://pipes.yahoo.com/shokai/akizukidenshi">Pipes: 秋月電子 新製品FullFeed</a><br />
秋月のRSSが無くなったので、新製品ページから取り出した。<br />
<br />
<br />
<a href="http://pipes.yahoo.com/shokai/strawberry_linux">Pipes: ストロベリー・リナックス FullFeed</a><br />
strawberry-linux.comのnews feedがタイトルのみ配信だったので<br />
<br />
どちらも商品イメージとデータシートへのリンクと価格を入れてある。<br />
<br />
千石は元気の良いblogで新製品を教えてくれる。spark funと液晶工房もblogがある。スイッチサイエンスもフィード作ろうかと思ったけど新製品ページが半年ぐらい更新されてなかったからやめた。マルツもblogあるけど勉強会情報しかなくて、新製品情報はwebで一覧できない。電子工作系はいまだに新製品情報をネットで効率的に収集する手段が乏しいな。<br />
<br />
<br />
<a href="http://pipes.yahoo.com/pipes/pipe.info?_id=a814d8184634fbd81ac7c3263ec2b752">Pipes: twitter list timeline</a><br />
twitterのlist機能にrssが無いので。list出た時に作ったんだけど、twitterのHTMLが変わっていつのまにか動かなくなってたのを修理した。<br />
ユーザ名とlist名を入れるとRSSを出す。他人の作ったlistをいろいろ購読してみてる。<br />
<br />
<br />
pipesってソースのHTMLが変わっていつのまにかエラーになってるんだけど、RSSリーダに登録してるだけだと配信されなくなるだけで、「動かなくなった」事に気づけないんだよなあ<br />
なんとかならないものか。1件も出力できなかったら一番上にエラー文を入れるようにすればいいのか？<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/5034/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++でmapやvectorをJSON出力するjson_builder.hを作った</title>
		<link>http://shokai.org/blog/archives/5021</link>
		<comments>http://shokai.org/blog/archives/5021#comments</comments>
		<pubDate>Wed, 27 Jan 2010 04:08:06 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[json_builder.h]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=5021</guid>
		<description><![CDATA[
C++でJSONというと、json.orgにもライブラリがたくさん紹介されているとおり色々ある。でも単に出力するだけの物で、ヘッダファイル一つで簡単に使えるのが無かったので作ってみた。
ちょっとstringの連結コスト [...]]]></description>
			<content:encoded><![CDATA[<p>
C++でJSONというと、<a href="http://www.json.org/json-ja.html">json.org</a>にもライブラリがたくさん紹介されているとおり色々ある。でも単に出力するだけの物で、ヘッダファイル一つで簡単に使えるのが無かったので作ってみた。<br />
ちょっとstringの連結コストがかかる気もするけど、まあいいか。<br />
<br />
今のところ、std::map&lt;string,any&gt;とstd::vector&lt;any&gt;とstringとintとdoubleが入る。つまりkeyはstringのみで、値はboost::anyをかぶせている。もちろんmapやvectorは入れ子にできる。<br />
<br />
boost::anyは何でも入れられる便利な型。<br />
参考：<a href="http://d.hatena.ne.jp/shokai/20100103/1262524286">boost::any &#8211; 橋本詳解</a><br />
<br />
<br />
必要なのはこれだけだけど、boost::any、tuple、format、foreachが必要。<br />
json_builder.h最新版は<a href="http://bitbucket.org/shokai/json-builder/src/tip/json_builder.h">bitbucketからどうぞ</a>。<br />
<br />
<a href="http://bitbucket.org/shokai/json-builder/src/c9959e7d40c2/json_builder.h">json_builder.h</a><br />
<pre class="prettyprint">
#include&nbsp;&lt;iostream&gt;<br />
#include&nbsp;&lt;string&gt;<br />
#include&nbsp;&lt;map&gt;<br />
#include&nbsp;&lt;vector&gt;<br />
#include&nbsp;&lt;boost/any.hpp&gt;<br />
#include&nbsp;&lt;boost/tuple/tuple.hpp&gt;<br />
#include&nbsp;&lt;boost/format.hpp&gt;<br />
#include&nbsp;&lt;boost/foreach.hpp&gt;<br />
<br />
using&nbsp;namespace&nbsp;std;<br />
using&nbsp;namespace&nbsp;boost;<br />
<br />
namespace&nbsp;json_builder{<br />
&nbsp;&nbsp;string&nbsp;toJson(any&nbsp;value){<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(value.type()&nbsp;==&nbsp;typeid(vector&lt;any&gt;)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;result_str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vector&lt;any&gt;&nbsp;vec&nbsp;=&nbsp;any_cast&lt;vector&lt;any&gt;&nbsp;&gt;(value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;vec.size();&nbsp;i++){<br />
	result_str&nbsp;+=&nbsp;toJson(vec[i]);<br />
	if(i&nbsp;&lt;&nbsp;vec.size()-1)&nbsp;result_str&nbsp;+=&nbsp;",";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result_str&nbsp;=&nbsp;str(format("[%s]")&nbsp;%&nbsp;result_str);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result_str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(map&lt;string,any&gt;)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;result_str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map&lt;string,any&gt;&nbsp;m&nbsp;=&nbsp;any_cast&lt;map&lt;string,any&gt;&nbsp;&gt;(value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;key;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;any&nbsp;value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BOOST_FOREACH(tie(key,value),&nbsp;m){<br />
	result_str&nbsp;+=&nbsp;str(format("\"%s\":%s")&nbsp;%&nbsp;key&nbsp;%&nbsp;toJson(value));<br />
	if(++i&nbsp;&lt;&nbsp;m.size())&nbsp;result_str&nbsp;+=&nbsp;",";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result_str&nbsp;=&nbsp;str(format("{%s}")&nbsp;%&nbsp;result_str);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result_str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(string)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;str(format("\"%s\"")&nbsp;%&nbsp;any_cast&lt;string&gt;(value));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(int)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;str(format("\"%d\"")&nbsp;%&nbsp;any_cast&lt;int&gt;(value));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(value.type()&nbsp;==&nbsp;typeid(double)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;str(format("\"%d\"")&nbsp;%&nbsp;any_cast&lt;double&gt;(value));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
<br />
}<br />
</pre>
jsonは要素数不定のただの木なので、再帰でtree walkして要素の型を見て文字列に直して連結し直すだけの関数一つになった。シンプル。<br />
見ての通り、&#8221;や&#8217;や[や{はescapeしていないので、それらを含む文字列をtoJsonするとparseできないjsonができる。とりあえず今は入れる前にescapeしておいてほしい。<br />
単純にバックスラッシュつければいいだけなのかな？ → <a href="http://shokai.org/blog/archives/5046">対応した</a><br />
<br />
<br />
使ってみる。一つのstd::mapをjsonのhashとして標準出力する例<br />
<a href="http://bitbucket.org/shokai/json-builder/src/c9959e7d40c2/test/test.cpp">test.cpp</a><br />
<pre class="prettyprint">
#include&nbsp;&lt;iostream&gt;<br />
#include&nbsp;&lt;string&gt;<br />
#include&nbsp;&lt;map&gt;<br />
#include&nbsp;&lt;boost/any.hpp&gt;<br />
#include&nbsp;"../json_builder.h"<br />
<br />
int&nbsp;main(int&nbsp;argc,&nbsp;char*&nbsp;argv[]){<br />
&nbsp;&nbsp;std::map&lt;string,boost::any&gt;&nbsp;user;<br />
&nbsp;&nbsp;user["name"]&nbsp;=&nbsp;std::string(&#8221;shokai&#8221;);&nbsp;//&nbsp;string<br />
&nbsp;&nbsp;user["fullname"]&nbsp;=&nbsp;std::string(&#8221;sho&nbsp;hashimoto&#8221;);<br />
&nbsp;&nbsp;user["age"]&nbsp;=&nbsp;25;&nbsp;//&nbsp;int<br />
&nbsp;&nbsp;user["test"]&nbsp;=&nbsp;1.23;&nbsp;//&nbsp;double<br />
<br />
&nbsp;&nbsp;string&nbsp;json&nbsp;=&nbsp;json_builder::toJson(user);<br />
&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;json&nbsp;&lt;&lt;&nbsp;endl;<br />
&nbsp;&nbsp;return&nbsp;0;<br />
}<br />
</pre>
<br />
<br />
出力<br />
<pre class="prettyprint">
{"age":"25","fullname":"sho&nbsp;hashimoto","name":"shokai","test":"1.23"}<br />
</pre>
<br />
<br />
<br />
より複雑に、mapやvectorを入れ子にした例<br />
<a href="http://bitbucket.org/shokai/json-builder/src/c9959e7d40c2/test/test.cpp">test2.cpp</a><br />
<pre class="prettyprint">
#include&nbsp;&lt;iostream&gt;<br />
#include&nbsp;&lt;string&gt;<br />
#include&nbsp;&lt;map&gt;<br />
#include&nbsp;&lt;vector&gt;<br />
#include&nbsp;&lt;boost/any.hpp&gt;<br />
#include&nbsp;"../json_builder.h"<br />
<br />
using&nbsp;namespace&nbsp;json_builder;<br />
using&nbsp;namespace&nbsp;std;<br />
using&nbsp;namespace&nbsp;boost;<br />
<br />
int&nbsp;main(int&nbsp;argc,&nbsp;char*&nbsp;argv[]){<br />
&nbsp;&nbsp;map&lt;string,any&gt;&nbsp;obj;<br />
&nbsp;&nbsp;obj["test"]&nbsp;=&nbsp;string("testtest");<br />
<br />
&nbsp;&nbsp;map&lt;string,any&gt;&nbsp;user;<br />
&nbsp;&nbsp;user["name"]&nbsp;=&nbsp;string("shokai");<br />
&nbsp;&nbsp;user["fullname"]&nbsp;=&nbsp;string("sho&nbsp;hashimoto");<br />
&nbsp;&nbsp;user["age"]&nbsp;=&nbsp;25;<br />
&nbsp;&nbsp;user["test"]&nbsp;=&nbsp;6.78;<br />
&nbsp;&nbsp;obj["user"]&nbsp;=&nbsp;user;<br />
<br />
&nbsp;&nbsp;std::vector&lt;any&gt;&nbsp;vec;<br />
&nbsp;&nbsp;vec.push_back(string("aaaa"));<br />
&nbsp;&nbsp;vec.push_back(1234.56);<br />
&nbsp;&nbsp;vec.push_back(string("hello&nbsp;work"));<br />
&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;vector&lt;any&gt;&nbsp;vec2;<br />
&nbsp;&nbsp;vec2.push_back(string("nested&nbsp;std::vector"));<br />
&nbsp;&nbsp;vec2.push_back(string("bbbbb"));<br />
&nbsp;&nbsp;vec.push_back(vec2);&nbsp;//&nbsp;std::vecotrの入れ子<br />
<br />
&nbsp;&nbsp;obj["params"]&nbsp;=&nbsp;vec;<br />
&nbsp;&nbsp;string&nbsp;json&nbsp;=&nbsp;json_builder::toJson(obj);<br />
&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;json&nbsp;&lt;&lt;&nbsp;endl;<br />
<br />
&nbsp;&nbsp;return&nbsp;0;<br />
}<br />
</pre>
<br />
<br />
出力<br />
<pre class="prettyprint">
{"params":["aaaa","1234.56","hello work",["nested std::vector","bbbbb"]],<br />
"test":"testtest","user":{"age":"25","fullname":"sho hashimoto","name":"shokai","test":"6.78"}}<br />
</pre>
<br />
<br />
出力したjsonが正しいかどうか、確認するために<a href="http://bitbucket.org/shokai/json-builder/src/c9959e7d40c2/test/json-parse.rb">rubyのjsonモジュールでrubyのオブジェクトに読み込むコード</a>をtestフォルダに置いておいた。<br />
<pre class="prettyprint">
{"params"=>["aaaa", "1234.56", "hello work", ["nested std::vector", "bbbbb"]],<br />
 "user"=><br />
  {"name"=>"shokai", "fullname"=>"sho hashimoto", "test"=>"6.78", "age"=>"25"},<br />
 "test"=>"testtest"}<br />
parse success<br />
</pre>
ちゃんと読み込めた。<br />
<br />
<br />
<br />
BOOST_FOREACHが涙が出るほど便利だった！！<br />
<ul>
  <li><a href="http://d.hatena.ne.jp/faith_and_brave/20091002/1254469396">std::mapをBoost.Foreachで回すときにキーと値を簡単に取り出す - Faith and Brave - C++で遊ぼう</a></li>
  <li><a href="http://miyano.s53.xrea.com/cgi-bin/sb/sb.cgi?cid=3-boost%20-%20Foreach">Pasture | C++::boost - Foreach</a></li>
</ul>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/5021/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>scansnapと裁断機を買って本を電子化しまくる</title>
		<link>http://shokai.org/blog/archives/4999</link>
		<comments>http://shokai.org/blog/archives/4999#comments</comments>
		<pubDate>Sun, 03 Jan 2010 08:07:10 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[scansnap]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=4999</guid>
		<description><![CDATA[
scansnapと裁断機を買った。合計3万6000円ぐらいだったと思う


最近はちょっとした待ち時間に、iPhoneでpdf化したRubyレシピブックをよく読んでいる。


漫画なんかも、24インチの液晶に出せばむし [...]]]></description>
			<content:encoded><![CDATA[<p>
scansnapと裁断機を買った。合計3万6000円ぐらいだったと思う<br />
<br />
<br />
最近はちょっとした待ち時間に、iPhoneでpdf化したRubyレシピブックをよく読んでいる。<br />
<a href="http://www.flickr.com/photos/shokai/4191564846/" title="写真 2 by shokai, on Flickr"><img src="http://farm5.static.flickr.com/4003/4191564846_85cdd6f0ed.jpg" width="480" height="320" alt="写真 2" /></a><br />
<br />
漫画なんかも、24インチの液晶に出せばむしろ元の本より大きくなっていい。<br />
あと、中高の頃に毎年度みんなの作文や部活の大会記録がまとめられた200ページぐらいの本が作られていたんだけどそれもスキャンして全部パソコンに入れておいた。OCRもかけてあるので、これで黒歴史を検索できる。どこでもこういう本を見れるのは、友達に会った時とかにネタになって面白い。<br />
<br />
<br />
買ったのは11月に出たscansnap s1300。サイズはティッシュ箱ぐらい。3,4秒で1枚、裏表まとめて読み込める。普通のフラットヘッドスキャナと違ってプリンタの様に自動でページ送りしてくれるので、500ページの本を20分ちょっとで読み込めた。名刺だとサイズが小さいのでもっと速い。<br />
一冊の本を解体するのに1分、スキャンしてpdf出力に20分（この間、原稿を100枚ずつぐらい入れる）、必要であればスキャン後にOCRをかけるのに10分ぐらいかかる。<br />
webで検索すると一度に20枚程度しかセットできないと書いてあるが、そうでもない。確かに厚さを測るセンサー？か何かが働いていて最初から100枚入れておくと「原稿が読み取れない」というエラーが出るが、最初に20枚ぐらい入れてスキャン開始して、すぐ80枚ぐらい突っ込んでスキャンさせている。<br />
<br />
ネットワーク共有すると普通のスキャナとしてしか使えないので、Windows XP homeが入っている古いネットブックにscansnapをつないで、Tight VNC Serverを起動させておいてMac OSXに最初から入っている画面共有で遠隔操作している。<br />
<br />
<br />
<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B002X492PK/shokai-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/312CXhUFZEL._SL160_.jpg" alt="FUJITSU ScanSnap S1300 FI-S1300" style="border: none;" /></a></div><div class="amazlet-info" style="float:left;margin-left:15px;line-height:120%"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B002X492PK/shokai-22/ref=nosim/" name="amazletlink" target="_blank">FUJITSU ScanSnap S1300 FI-S1300</a><div class="amazlet-powered-date" style="font-size:7pt;margin-top:5px;font-family:verdana;line-height:120%">posted with <a href="http://www.amazlet.com/browse/ASIN/B002X492PK/shokai-22/ref=nosim/" title="FUJITSU ScanSnap S1300 FI-S1300" target="_blank">amazlet</a> at 10.01.03</div></div><div class="amazlet-detail">富士通 (2009-11-21)<br />売り上げランキング: 720<br /></div><div class="amazlet-review" style="margin-top:10px; margin-bottom:10px"><div class="amazlet-review-average" style="margin-bottom:5px">おすすめ度の平均: <img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-5-0.gif" alt="5.0" /></div><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-5-0.gif" alt="5" /> ストレスフリー<br /></div><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B002X492PK/shokai-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jp で詳細を見る</a></div></div><div class="amazlet-footer" style="clear: left"></div></div>
<br />
<br />
本を解体する為にこの裁断機を買った。14000円ぐらい。<br />
<a href="http://atq.ck.valuecommerce.com/servlet/atq/referral?sid=2219441&#038;pid=877935733&#038;vcptn=shpg%2Fp%2FQJIyR7FRPKvZlsm7mv4slxKT&#038;vc_url=http%3A%2F%2Fstore.shopping.yahoo.co.jp%2Fshop-nexstage%2F542.html" target="_blank" ><img border="0" src="http://a248.e.akamai.net/f/248/37952/1h/image.shopping.yahoo.co.jp/i/g/shop-nexstage_542" alt="大型ペーパーカッター 裁断機"><br />大型ペーパーカッター 裁断機<img Src="http://atq.ad.valuecommerce.com/servlet/atq/gifbanner?sid=2219441&#038;pid=877935733&#038;vcptn=shpg%2Fp%2FQJIyR7FRPKvZlsm7mv4slxKT" height="1" width="1" border="0"></a><br />
<br />
<br />
まだ必要ないので買ってないけど、替え刃も発見した。<br />
<a href="http://atq.ck.valuecommerce.com/servlet/atq/referral?sid=2219441&#038;pid=877935733&#038;vcptn=shpg%2Fp%2FQJIyR7FRPKvZlsm7mv4slxKT&#038;vc_url=http%3A%2F%2Fstore.shopping.yahoo.co.jp%2Fshop-nexstage%2F903.html" target="_blank" ><img border="0" src="http://a248.e.akamai.net/f/248/37952/1h/image.shopping.yahoo.co.jp/i/g/shop-nexstage_903" alt="コピー用紙500枚らくらくカット/人気　商品大型ペーパーカッター用『替え刃』"><br />コピー用紙500枚らくらくカット/人気　商品大型ペーパーカッター用『替え刃』<img Src="http://atq.ad.valuecommerce.com/servlet/atq/gifbanner?sid=2219441&#038;pid=877935733&#038;vcptn=shpg%2Fp%2FQJIyR7FRPKvZlsm7mv4slxKT" height="1" width="1" border="0"></a><br />
<br />
ジャンプぐらいの厚い雑誌でも切れる。このサイズの裁断機では妙に安い（他の半額程度）だが、そのかわり届いた時点で油でぬるぬるしている。<br />
軍手とぞうきんを用意しておいて、よく拭いた。<br />
<br />
刃の部分には茶色い油？が付着しているので、試しにいらない本を裁断してみて油の拭き残しが無いか確かめる必要がある。<br />
<br />
油がついた。（古本ぐらしは新しいのを持っているので、2003年版を試し切りに使った）<br />
<a href="http://www.flickr.com/photos/shokai/4190333178/" title="R0013859.JPG by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2768/4190333178_ee5e6a0f0a.jpg" width="500" height="375" alt="R0013859.JPG" /></a><br />
<br />
<br />
■裁断する<br />
まずスキャンできるように本をバラバラにする。<br />
<br />
表紙を外す<br />
<a href="http://www.flickr.com/photos/shokai/4191350556/" title="R0013860.JPG by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2802/4191350556_f56b48fdd7.jpg" width="500" height="375" alt="R0013860.JPG" /></a><br />
<br />
<br />
しっかり押さえる<br />
<a href="http://www.flickr.com/photos/shokai/4190592651/" title="R0013861.JPG by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2490/4190592651_f54f4a9364.jpg" width="500" height="375" alt="R0013861.JPG" /></a><br />
<br />
<br />
切る<br />
<a href="http://www.flickr.com/photos/shokai/4190593131/" title="R0013862.JPG by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2487/4190593131_93763f9a9e.jpg" width="500" height="375" alt="R0013862.JPG" /></a><br />
<br />
<br />
切る。裁断機の刃が超鋭いので、あんまり力はいらない。<br />
<a href="http://www.flickr.com/photos/shokai/4191356564/" title="R0013863.JPG by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2608/4191356564_4023060bbf.jpg" width="500" height="375" alt="R0013863.JPG" /></a><br />
<br />
<br />
バラバラにした本をscansnapに入れる<br />
<a href="http://www.flickr.com/photos/shokai/4190617877/" title="R0013867.JPG by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2800/4190617877_60f654a6a3.jpg" width="500" height="375" alt="R0013867.JPG" /></a><br />
<br />
<br />
iPhoneアプリのGoodReaderを使って転送して、読める。<br />
<a href="http://www.flickr.com/photos/shokai/4190802439/" title="写真 1 by shokai, on Flickr"><img src="http://farm5.static.flickr.com/4006/4190802439_9aafa1a1b8.jpg" width="320" height="480" alt="写真 1" /></a><br />
<br />
<br />
<br />
■OCRをかける<br />
scansnap managerにOCR機能が内蔵されていて、pdfを検索可能な状態にできる。<br />
Windows版はまともだが、Mac版は日本語と英語どちらかしか選べない。日本語でOCRをかけるとローマ字が全角になってしまう。<br />
<br />
縦書きの認識はうまくいっていない。自動認識らしいが、横書きだと誤認識してしまう。手動で指定する事も出来ない。<br />
<br />
<br />
技術書とかは、本の状態よりも検索できた方が便利な事が多い気がする。先に本の内容と流れを把握していれば。<br />
<a href="http://www.flickr.com/photos/shokai/4207880283/" title="scanしたRubyレシピブック by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2568/4207880283_2f4c4d9dc2.jpg" width="483" height="500" alt="scanしたRubyレシピブック" /></a><br />
<br />
<br />
<br />
■スキャンの設定<br />
画質は「スーパーファイン」にしている。ちょっとファイルサイズ大きいけど、ストレージはどんどん大きくなるから別に構わない。<br />
<br />
いろいろ試したが、「カラーモードの選択」を「自動」にしていると、例えばこういうページを「グレースケール」ではなく「白黒」として誤認識してしまう事があった。式の部分の背景がグレーの部分がおかしくなってしまう事がある。<br />
<a href="http://www.flickr.com/photos/shokai/4191589408/" title="写真 1 by shokai, on Flickr"><img src="http://farm3.static.flickr.com/2697/4191589408_3e9ff58b90.jpg" width="480" height="320" alt="写真 1" /></a><br />
<br />
なので毎回手動でカラーモードは指定している。<br />
<br />
「原稿の向きを自動的に補正」も、たまに間違えるのでオフにしている。上側を先にscansnapに入れれば必要ない。<br />
「白紙ページを自動的に削除」はきっちり働くのでオン。<br />
「継続読み取りを有効」はしておいたほうがいい。継続して1つのpdfファイルに追記していける。<br />
<br />
<br />
■PDFの編集<br />
Windows用のpdf編集ソフトがついている。ページの回転や結合ができて、scansnapの仕上げにはUIがAcrobat Proよりも優れている。<br />
MacではAdobe Acrobat Professional等が必要。<br />
<br />
<br />
■電子化したくない本<br />
文系の本は、俺はライティングスペースに鉛筆で書き込むので電子化したくない。<br />
あと、やっぱりパラパラ流し見できないので、本の内容と流れが頭に入るまでは電子化したくないな。<br />
<br />
文庫で縦書きの小説は電子化してもいいが、ビューアとしてiPhoneの画面サイズだと絶妙に読みにくい。縦書きだと画面からはみだすか、超小さい字になる。<br />
<br />
<br />
やっぱり技術書と漫画と名刺やはがき、説明書、場所を取るから捨てたいんだけど数年後に確実に見たくなる本（卒業文集とか？）をスキャンすればいいんじゃないだろうか。<br />
あと数年すれば電子化した本を再び製本しなおす方法も整ってくると思うし。<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/4999/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>OpenCVで画像のサイズを求めるgearman workerを作って、Rubyから呼ぶ</title>
		<link>http://shokai.org/blog/archives/4987</link>
		<comments>http://shokai.org/blog/archives/4987#comments</comments>
		<pubDate>Sun, 03 Jan 2010 03:29:08 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[boost]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[gearman]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=4987</guid>
		<description><![CDATA[
ファイル名を渡すと画像サイズを返すgearman workerを作った。

{"width":1600,&#160;"height":1200}

という風にJSON風に値を返す。


以前画像のだいたいの色を求めるg [...]]]></description>
			<content:encoded><![CDATA[<p>
ファイル名を渡すと画像サイズを返すgearman workerを作った。<br />
<pre class="prettyprint">
{"width":1600,&nbsp;"height":1200}<br />
</pre>
という風にJSON風に値を返す。<br />
<br />
<br />
以前<a href="http://shokai.org/blog/archives/4966">画像のだいたいの色を求めるgearman worker</a>を作ってたんだけど、C++で書いたworker側を単独で動作テストする事ができなくてどうしようか悩んだ。テスト用のclientと同時に作らなければならなくて、どちらにバグがあるのか切り分けるのが面倒だった。<br />
<br />
そこで、workerの起動時に<br />
<pre>
./imgsizeWorker --test "/path/to/imagefile.jpg"<br />
</pre>
という風にgearman clientから来る引数と同じ形式で渡すと、単体のプログラムとしても動作チェックできるようにした。<br />
<br />
<br />
こうすると普通にworkerとして起動する。<br />
<pre>
./imgsizeWorker -s localhost -p 7003<br />
</pre>
これはboost::program_optionsでやると便利だった。<br />
今後はこのコードを雛形にすればC++とOpenCVで高速に画像解析して、gearmand経由でスクリプト言語から呼び出しまくれる。<br />
<br />
<br />
■使ったライブラリ<br />
boostライブラリを中心にいろいろ使った。<br />
<br />
opencv1.0は画像サイズを取得する為だけに使った。GUIを使って無いのにcvLoadImage()のためだけにhighgui.hを読み込んでいる。<br />
<br />
boost::tupleとboost::tieを使うと返り値を複数返す関数が作れるので、画像の情報を返すのに便利。そういえばRubyでは普通に使ってたけどC#3.5やAS3.0ではタプル無かったな。欲しい。ASはArrayに何でも入れやすいからいいか。<br />
<a href="http://d.hatena.ne.jp/shokai/20091231/1262248887">boost::tupleで多値を受け取る &#8211; 橋本詳解</a><br />
<a href="http://d.hatena.ne.jp/shokai/20091231/1262249708">boost::tieでtupleを展開 &#8211; 橋本詳解</a><br />
<br />
boost::formatでprintf風にstd::stringをフォーマット。<br />
boost::program_optionsで引数をparseする。<br />
<a href="http://d.hatena.ne.jp/shokai/20090729/1248884601">boost::program_optionsでコマンドライン引数を読む &#8211; 橋本詳解</a><br />
<br />
rubyはxing-gearman-rubyを使った。<br />
<a href="http://shokai.org/blog/archives/4919">橋本商会 » Cでgearman workerを書いてRubyのclientから呼び出す</a><br />
<br />
<br />
■プログラム<br />
libgearmanのgearman_worker_add_serverはIPアドレスを渡さないとならないので、一応ホスト名を解決するようにした。<br />
<br />
<a href="http://shokai.org/projects/gearman-study/index.cgi/file/3a774a6d883d/imgsize/imgsizeWorker.cpp">imgsizeWorker.cpp</a><br />
<pre class="prettyprint">
//&nbsp;画像サイズを返すgearman&nbsp;worker<br />
#include&nbsp;&lt;stdio.h&gt;<br />
#include&nbsp;&lt;stdlib.h&gt;<br />
#include&nbsp;&lt;unistd.h&gt;<br />
#include&nbsp;&lt;string&gt;<br />
#include&nbsp;&lt;iostream&gt;<br />
#include&nbsp;&lt;cv.h&gt;<br />
#include&nbsp;&lt;highgui.h&gt;<br />
#include&nbsp;&lt;boost/program_options.hpp&gt;<br />
#include&nbsp;&lt;boost/regex.hpp&gt;<br />
#include&nbsp;&lt;boost/format.hpp&gt;<br />
#include&nbsp;&lt;boost/tuple/tuple.hpp&gt;<br />
#include&nbsp;&lt;boost/tuple/tuple_io.hpp&gt;<br />
#include&nbsp;&lt;libgearman/gearman.h&gt;<br />
<br />
using&nbsp;namespace&nbsp;boost;<br />
using&nbsp;namespace&nbsp;std;<br />
<br />
tuple&lt;int,&nbsp;int&gt;&nbsp;get_size(string&nbsp;fileName);&nbsp;//&nbsp;画像のwidth,heightを返す<br />
string&nbsp;imgsize(string&nbsp;fileName);&nbsp;//&nbsp;gearman&nbsp;workerとしてclientに返すstringに整形する<br />
void&nbsp;*job_imgsize(gearman_job_st&nbsp;*job,&nbsp;void&nbsp;*cb_arg,&nbsp;size_t&nbsp;*result_size,&nbsp;gearman_return_t&nbsp;*ret_ptr);<br />
<br />
int&nbsp;main(int&nbsp;argc,&nbsp;char*&nbsp;argv[])&nbsp;{<br />
&nbsp;&nbsp;program_options::options_description&nbsp;opts("options");<br />
&nbsp;&nbsp;opts.add_options()<br />
&nbsp;&nbsp;&nbsp;&nbsp;("help,h",&nbsp;"helpを表示")<br />
&nbsp;&nbsp;&nbsp;&nbsp;("server,s",&nbsp;program_options::value&lt;string&gt;(),&nbsp;"gearmanサーバーのアドレス")<br />
&nbsp;&nbsp;&nbsp;&nbsp;("port,p",&nbsp;program_options::value&lt;int&gt;(),&nbsp;"gearmanサーバーのport番号")<br />
&nbsp;&nbsp;&nbsp;&nbsp;("test,t",&nbsp;program_options::value&lt;string&gt;(),&nbsp;"gearman&nbsp;worker単体テスト用query");<br />
&nbsp;&nbsp;program_options::variables_map&nbsp;argmap;<br />
&nbsp;&nbsp;program_options::store(parse_command_line(argc,&nbsp;argv,&nbsp;opts),&nbsp;argmap);<br />
&nbsp;&nbsp;program_options::notify(argmap);<br />
<br />
&nbsp;&nbsp;if(!argmap.count("help")){<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(argmap.count("test")){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;"---test---"&nbsp;&lt;&lt;&nbsp;endl;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;gearman_param&nbsp;=&nbsp;argmap["test"].as&lt;string&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imgsize(gearman_param);&nbsp;//&nbsp;単体でworkerとしてのテスト<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}else&nbsp;if(argmap.count("server")&nbsp;&amp;&amp;&nbsp;argmap.count("port")){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gearman_worker_st&nbsp;worker;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gearman_worker_create(&amp;worker);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;g_server&nbsp;=&nbsp;argmap["server"].as&lt;string&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;g_port&nbsp;=&nbsp;argmap["port"].as&lt;int&gt;();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;hostent&nbsp;*g_host&nbsp;=&nbsp;gethostbyname((char*)g_server.c_str());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;g_server_addr&nbsp;=&nbsp;str(format("%d.%d.%d.%d")&nbsp;%<br />
				&nbsp;(uint)(uchar)g_host-&gt;h_addr[0]&nbsp;%<br />
				&nbsp;(uint)(uchar)g_host-&gt;h_addr[1]&nbsp;%<br />
				&nbsp;(uint)(uchar)g_host-&gt;h_addr[2]&nbsp;%<br />
				&nbsp;(uint)(uchar)g_host-&gt;h_addr[3]);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gearman_worker_add_server(&amp;worker,&nbsp;g_server_addr.c_str(),&nbsp;g_port);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gearman_worker_add_function(&amp;worker,&nbsp;"img_size",&nbsp;0,&nbsp;job_imgsize,&nbsp;NULL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;str(format("---start&nbsp;worker&nbsp;(%s:%d)---")&nbsp;%<br />
		&nbsp;&nbsp;g_server_addr&nbsp;%&nbsp;g_port)&nbsp;&lt;&lt;&nbsp;endl;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(true)&nbsp;gearman_worker_work(&amp;worker);&nbsp;//&nbsp;workerとして待機<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;cerr&nbsp;&lt;&lt;&nbsp;"server,portが必要です"&nbsp;&lt;&lt;&nbsp;endl;<br />
&nbsp;&nbsp;cerr&nbsp;&lt;&lt;&nbsp;opts&nbsp;&lt;&lt;&nbsp;endl;<br />
&nbsp;&nbsp;return&nbsp;1;<br />
&nbsp;&nbsp;<br />
}<br />
<br />
//&nbsp;opencvで画像サイズを取得<br />
tuple&lt;int,&nbsp;int&gt;&nbsp;get_size(string&nbsp;fileName){<br />
&nbsp;&nbsp;IplImage&nbsp;*img&nbsp;=&nbsp;cvLoadImage(fileName.c_str());<br />
&nbsp;&nbsp;if(!img){<br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;make_tuple(-1,&nbsp;-1);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;make_tuple(img-&gt;width,&nbsp;img-&gt;height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;cvReleaseImage(&amp;img);<br />
&nbsp;&nbsp;}<br />
}<br />
<br />
//&nbsp;画像サイズを取得してgearman&nbsp;serverに返すstringに整形する<br />
string&nbsp;imgsize(string&nbsp;fileName){<br />
&nbsp;&nbsp;string&nbsp;result_str&nbsp;=&nbsp;"";<br />
&nbsp;&nbsp;int&nbsp;width,&nbsp;height;<br />
&nbsp;&nbsp;tie(width,&nbsp;height)&nbsp;=&nbsp;get_size(fileName);<br />
&nbsp;&nbsp;if(width&nbsp;&gt;&nbsp;0&nbsp;&amp;&amp;&nbsp;height&nbsp;&gt;&nbsp;0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;result_str&nbsp;+=&nbsp;str(format("{\"width\":%d,&nbsp;\"height\":%d}")	<br />
		&nbsp;&nbsp;&nbsp;&nbsp;%&nbsp;width&nbsp;%&nbsp;height);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;result_str&nbsp;=&nbsp;"error&nbsp;:&nbsp;image&nbsp;load&nbsp;error";<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;fileName&nbsp;&lt;&lt;&nbsp;"&nbsp;=&gt;&nbsp;"&nbsp;&lt;&lt;&nbsp;result_str&nbsp;&lt;&lt;&nbsp;endl;<br />
&nbsp;&nbsp;return&nbsp;result_str;<br />
}<br />
<br />
//&nbsp;gearman&nbsp;worker&nbsp;job<br />
void&nbsp;*job_imgsize(gearman_job_st&nbsp;*job,&nbsp;void&nbsp;*cb_arg,&nbsp;size_t&nbsp;*result_size,&nbsp;gearman_return_t&nbsp;*ret_ptr){<br />
&nbsp;&nbsp;string&nbsp;fileName&nbsp;=&nbsp;(char*)gearman_job_workload(job);<br />
&nbsp;&nbsp;string&nbsp;result_str&nbsp;=&nbsp;imgsize(fileName);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;char&nbsp;*result&nbsp;=&nbsp;(char*)strdup(result_str.c_str());<br />
&nbsp;&nbsp;*result_size&nbsp;=&nbsp;result_str.size();<br />
&nbsp;&nbsp;*ret_ptr&nbsp;=&nbsp;GEARMAN_SUCCESS;<br />
&nbsp;&nbsp;return&nbsp;result;<br />
}<br />
</pre>
<br />
<br />
<a href="http://shokai.org/projects/gearman-study/index.cgi/file/3a774a6d883d/imgsize/Makefile">Makefile</a><br />
<pre class="prettyprint">
#&nbsp;Mac用Makefile<br />
SRC&nbsp;=&nbsp;imgsizeWorker.cpp<br />
DST&nbsp;=&nbsp;imgsizeWorker<br />
<br />
prefix=/opt/local<br />
INCPATH=$(prefix)/include<br />
LIBPATH=$(prefix)/lib<br />
<br />
CV_LIBS=&nbsp;-lcv&nbsp;-lcvaux&nbsp;-lcxcore&nbsp;-lhighgui<br />
BOOST_LIBS=&nbsp;$(LIBPATH)/libboost_program_options-mt.a<br />
<br />
GEAR_INCPATH=/usr/local/include<br />
GEAR_LIBPATH=/usr/local/lib<br />
GEAR_LIBS=$(GEAR_LIBPATH)/libgearman.a<br />
<br />
all:<br />
	g++&nbsp;-O&nbsp;$(SRC)&nbsp;-o&nbsp;$(DST)&nbsp;-I$(INCPATH)/opencv&nbsp;-L.&nbsp;-L$(LIBPATH)&nbsp;$(CV_LIBS)&nbsp;-I$(INCPATH)/boost&nbsp;$(BOOST_LIBS)&nbsp;-I$(GEAR_INCPATH)/libgearman&nbsp;-L.&nbsp;-L$(GEAR_LIBPATH)&nbsp;$(GEAR_LIBS)<br />
</pre>
<br />
<br />
client側。workerからの返り値の先頭にerrorが書いていなかったらJSONとしてparseする<br />
<a href="http://shokai.org/projects/gearman-study/index.cgi/file/3a774a6d883d/imgsize/testclient.rb">testclient.rb</a><br />
<pre class="prettyprint">
#!/usr/bin/env&nbsp;ruby<br />
#&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-<br />
require&nbsp;'rubygems'<br />
require&nbsp;'gearman'<br />
require&nbsp;'json'<br />
<br />
if&nbsp;ARGV.size&nbsp;&lt;&nbsp;1<br />
&nbsp;&nbsp;puts&nbsp;'画像へのパスが必要'<br />
&nbsp;&nbsp;puts&nbsp;'ruby&nbsp;testclient.rb&nbsp;~/path/to/images/*.png'<br />
&nbsp;&nbsp;exit&nbsp;1<br />
end<br />
<br />
c&nbsp;=&nbsp;Gearman::Client.new(['localhost:7003'])<br />
taskset&nbsp;=&nbsp;Gearman::TaskSet.new(c)<br />
<br />
ARGV.sort{|a,b|&nbsp;a.split(/\//).last.to_i&nbsp;&lt;=&gt;&nbsp;b.split(/\//).last.to_i}.each{|name|<br />
&nbsp;&nbsp;puts&nbsp;"add&nbsp;task&nbsp;#{name}"<br />
&nbsp;&nbsp;task&nbsp;=&nbsp;Gearman::Task.new("img_size",&nbsp;name+"\0")<br />
&nbsp;&nbsp;task.on_complete{|result|<br />
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;!(result&nbsp;=~&nbsp;/^error/)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;"return:&nbsp;#{name}&nbsp;=&gt;&nbsp;"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;JSON.parse(result)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;"return:&nbsp;#{name}&nbsp;=&gt;&nbsp;#{result}"<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;taskset.add_task(task)<br />
}<br />
taskset.wait(100)&nbsp;#&nbsp;wait&nbsp;100(sec)<br />
</pre>
<br />
<br />
&amp;をつけていくつかworkerを起動する<br />
<pre class="prettyprint">
./imgsizeWorker -s localhost -p 7003&#038;<br />
./imgsizeWorker -s localhost -p 7003&#038;<br />
</pre>
<br />
<br />
clientからtask登録。フォルダ内のjpgファイルを全部登録する<br />
<pre class="prettyprint">
ruby testclient.rb ~/Pictures/selected/*.jpg<br />
</pre>
サイズが返ってくる<br />
<pre class="prettyprint">
add task /Users/sho/Pictures/selected/a66dab3a.jpg<br />
add task /Users/sho/Pictures/selected/3ed6f38e.jpg<br />
add task /Users/sho/Pictures/selected/77ab53f0.jpg<br />
add task /Users/sho/Pictures/selected/889bd644.jpg<br />
add task /Users/sho/Pictures/selected/73177294.jpg<br />
return: /Users/sho/Pictures/selected/a66dab3a.jpg => {"height"=>1200, "width"=>1600}<br />
return: /Users/sho/Pictures/selected/3ed6f38e.jpg => {"height"=>1200, "width"=>1600}<br />
return: /Users/sho/Pictures/selected/77ab53f0.jpg => {"height"=>1200, "width"=>1600}<br />
return: /Users/sho/Pictures/selected/889bd644.jpg => {"height"=>800, "width"=>1280}<br />
return: /Users/sho/Pictures/selected/73177294.jpg => {"height"=>1200, "width"=>1600}<br />
</pre>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/4987/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
