<?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>Mon, 08 Feb 2010 10:51:56 +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>ユビキタスコンテンツシンポジウム 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>
見ての通り、&#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>14</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>
		<item>
		<title>中吉</title>
		<link>http://shokai.org/blog/archives/4981</link>
		<comments>http://shokai.org/blog/archives/4981#comments</comments>
		<pubDate>Sat, 02 Jan 2010 03:43:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Moblog]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=4981</guid>
		<description><![CDATA[

だけど全体的に悪い事ばっかり書いてあったfrom iphone
 

]]></description>
			<content:encoded><![CDATA[<p>
<div class="photo"><a href='http://shokai.org/blog/wp-content/uploads/2010/01/37e3808047553cedb34daa9b1d7ab2a3.jpg' title='37e3808047553cedb34daa9b1d7ab2a3'><img width="300" height="300" src="http://shokai.org/blog/wp-content/uploads/2010/01/37e3808047553cedb34daa9b1d7ab2a3-300x300.jpg" class="attachment-medium" alt="37e3808047553cedb34daa9b1d7ab2a3.jpg" title="37e3808047553cedb34daa9b1d7ab2a3" /></a></div>
<p>だけど全体的に悪い事ばっかり書いてあったfrom iphone</p>
<div class="photo-end"> </div>
<p><a href="http://shokai.org/blog/wp-content/uploads/2010/01/l_1200_1200_1EC72720-3D4C-4622-84EF-12B7624ABDBF.jpeg"><img src="http://shokai.org/blog/wp-content/uploads/2010/01/l_1200_1200_1EC72720-3D4C-4622-84EF-12B7624ABDBF.jpeg" alt="" width="300" height="300" class="alignnone size-full wp-image-364" /></a></p></p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/4981/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SFCの博士課程に進学する</title>
		<link>http://shokai.org/blog/archives/4979</link>
		<comments>http://shokai.org/blog/archives/4979#comments</comments>
		<pubDate>Fri, 25 Dec 2009 22:44:09 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=4979</guid>
		<description><![CDATA[
3週間ぐらい前に、twitterに合格通知のスクリーンショットを貼り付けて1人喜んだだけで満足して書き忘れてた

今年の4月にできたばかりの増井先生の研究室に行きます

最初はがちがちに古典的なユーザインタフェース(G [...]]]></description>
			<content:encoded><![CDATA[<p>
3週間ぐらい前に、twitterに合格通知のスクリーンショットを貼り付けて1人喜んだだけで満足して書き忘れてた<br />
<br />
今年の4月にできたばかりの<a href="http://pitecan.com/">増井先生</a>の研究室に行きます<br />
<br />
最初はがちがちに古典的なユーザインタフェース(GUI)の先生かと思ってたんだけど、<a href="http://wiredvision.jp/blog/masui/200912/200912161100.html">ユーザ評価の落とし穴</a>の話とかを聞いたりしたり、増井先生が載ってる昔のトラ技とかを見せてもらったりしながら話してるうちに、得る物と新しくできそうな物がかなりあるなと思った。<br />
<br />
俺はこういう意味でのごく普通のUI評価をぜんぜんやらずに、物理的なインタフェースとウェブとを使ったシステムのプロトタイプをとにかく素早く作るのと、コンセプトを作る事だけを鍛えてたので、（どうなるかはわからないが）増井研ならさらに自分を進化させられそうな気がした。<br />
<br />
あと学部生がやばい。ギークすぎる。<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/4979/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenCVで画像のだいたいの色を求めるgearman workerを作って、Rubyから呼び出す</title>
		<link>http://shokai.org/blog/archives/4966</link>
		<comments>http://shokai.org/blog/archives/4966#comments</comments>
		<pubDate>Thu, 24 Dec 2009 12:14:37 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></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=4966</guid>
		<description><![CDATA[
画像のだいたいの色を求めるをgearman worker化した。
画像ファイル名をテキストで投げると

{width: 136, height: 147, r: 249, g: 234, b:230}

という形式で画 [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://shokai.org/blog/archives/4961">画像のだいたいの色を求める</a>をgearman worker化した。<br />
画像ファイル名をテキストで投げると<br />
<pre class="prettyprint">
{width: 136, height: 147, r: 249, g: 234, b:230}<br />
</pre>
という形式で画像のサイズとだいたいの色を返す。<br />
<br />
<br />
Cでworkerを書いてRubyで呼び出す方法は<a href="http://shokai.org/blog/archives/4919">橋本商会 » Cでgearman workerを書いてRubyのclientから呼び出す</a>に書いたとおり。<br />
これでOpenCVの解析をgearman workerとして複数並列に動かしてそれをRubyから使いまくるというのができるワハハ<br />
<br />
<br />
C++なのは<a href="http://d.hatena.ne.jp/shokai/20091219/1261195886">boost::regex_split</a>でも使って引数を受け取ろうかと思ってたんだけど、そもそもファイル名だけしか受け取らなかったから意味がなかった。<br />
<a href="http://shokai.org/projects/gearman-study/index.cgi/file/f306280ee764/imgcolor/imgcolorWorker.cpp">imgcolorWorker.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/regex.hpp&gt;<br />
#include&nbsp;&lt;boost/format.hpp&gt;<br />
#include&nbsp;&lt;libgearman/gearman.h&gt;<br />
<br />
using&nbsp;namespace&nbsp;boost;<br />
using&nbsp;namespace&nbsp;std;<br />
IplImage&nbsp;*img,&nbsp;*img1px,&nbsp;*imgR,&nbsp;*imgG,&nbsp;*imgB;<br />
<br />
void&nbsp;*job_imgcolor(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;img1px&nbsp;=&nbsp;cvCreateImage(cvSize(1,1),&nbsp;IPL_DEPTH_8U,&nbsp;3);<br />
&nbsp;&nbsp;imgR&nbsp;=&nbsp;cvCreateImage(cvSize(1,1),&nbsp;IPL_DEPTH_8U,&nbsp;1);<br />
&nbsp;&nbsp;imgG&nbsp;=&nbsp;cvCreateImage(cvSize(1,1),&nbsp;IPL_DEPTH_8U,&nbsp;1);<br />
&nbsp;&nbsp;imgB&nbsp;=&nbsp;cvCreateImage(cvSize(1,1),&nbsp;IPL_DEPTH_8U,&nbsp;1);<br />
<br />
&nbsp;&nbsp;gearman_worker_st&nbsp;worker;<br />
&nbsp;&nbsp;gearman_worker_create(&amp;worker);<br />
&nbsp;&nbsp;gearman_worker_add_server(&amp;worker,&nbsp;"127.0.0.1",&nbsp;7003);<br />
&nbsp;&nbsp;gearman_worker_add_function(&amp;worker,&nbsp;"img_color",&nbsp;0,&nbsp;job_imgcolor,&nbsp;NULL);<br />
<br />
&nbsp;&nbsp;while(true)&nbsp;gearman_worker_work(&amp;worker);<br />
&nbsp;&nbsp;return&nbsp;0;<br />
}<br />
<br />
void&nbsp;*job_imgcolor(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;"";<br />
&nbsp;&nbsp;IplImage&nbsp;*img&nbsp;=&nbsp;cvLoadImage(fileName.c_str());<br />
&nbsp;&nbsp;if(!img){<br />
&nbsp;&nbsp;&nbsp;&nbsp;result_str&nbsp;+=&nbsp;"{error:&nbsp;image&nbsp;load&nbsp;error}";<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;cvResize(img,&nbsp;img1px,&nbsp;CV_INTER_CUBIC);<br />
&nbsp;&nbsp;&nbsp;&nbsp;cvSplit(img1px,&nbsp;imgB,&nbsp;imgG,&nbsp;imgR,&nbsp;NULL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;result_str&nbsp;+=&nbsp;str(format("{width:&nbsp;%d,&nbsp;height:&nbsp;%d,&nbsp;r:&nbsp;%d,&nbsp;g:&nbsp;%d,&nbsp;b:%d}")	<br />
		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%&nbsp;img-&gt;width&nbsp;%&nbsp;img-&gt;height&nbsp;%<br />
		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(uint)(uchar)imgR-&gt;imageDataOrigin[0]&nbsp;%<br />
		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(uint)(uchar)imgG-&gt;imageDataOrigin[0]&nbsp;%<br />
		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(uint)(uchar)imgB-&gt;imageDataOrigin[0]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;cvReleaseImage(&amp;img);<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;<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>
最後の*result_sizeに返り値のサイズを入れておかないと、client側には壊れた文字列が来る。<br />
boost::formatはprintfのフォーマットと違ってunsigned charを数値としてそのまま使えなかったので2回キャストした。<br />
<br />
<br />
<a href="http://shokai.org/projects/gearman-study/index.cgi/file/f306280ee764/imgcolor/Makefile">Makefile</a><br />
<pre class="prettyprint">
#&nbsp;Mac用Makefile<br />
SRC&nbsp;=&nbsp;imgcolorWorker.cpp<br />
DST&nbsp;=&nbsp;imgcolorWorker<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&nbsp;$(LIBPATH)/libboost_regex-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 />
<br />
gearman client。ワイルドカードで指定して画像ファイルをひとつずつtask登録する<br />
<a href="http://shokai.org/projects/gearman-study/index.cgi/file/f306280ee764/imgcolor/imgcolorClient.rb">imgcolorClient.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;imgcolorClient.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_color",&nbsp;name+"\0")<br />
&nbsp;&nbsp;task.on_complete{|result|<br />
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;"return:&nbsp;#{name}&nbsp;=&gt;&nbsp;#{result}"<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;taskset.add_task(task)<br />
}<br />
taskset.wait(100)&nbsp;#&nbsp;wait&nbsp;100(sec)<br />
</pre>
task登録する時に、argmentの末尾に&#8221;\0&#8243;を付けておかないとworker側で受け取った時におかしくなる事がある。<br />
<br />
<br />
<br />
workerを2つ起動しておいて、画像をいくつか投げてみる<br />
<pre class="prettyprint">
make<br />
./imgcolorWorker&#038;<br />
./imgcolorWorker&#038;<br />
ruby imgcolorClient.rb ~/Pictures/test/*<br />
</pre>
<br />
<br />
workerが2つあるので、結果は順番には返ってこない。<br />
<pre class="prettyprint">
add task /Users/sho/Pictures/test/実装力不全.gif<br />
add task /Users/sho/Pictures/test/そうだ旧都へ行こう.jpg<br />
add task /Users/sho/Pictures/test/zanmai.jpg<br />
add task /Users/sho/Pictures/test/wiring.jpg<br />
return: /Users/sho/Pictures/test/実装力不全.gif => {error: image load error}<br />
add task /Users/sho/Pictures/test/ed93d6de.jpg<br />
add task /Users/sho/Pictures/test/f9286cff.jpg<br />
add task /Users/sho/Pictures/test/fae75abe.jpg<br />
add task /Users/sho/Pictures/test/img278_s201.jpg<br />
add task /Users/sho/Pictures/test/la-metro.jpg<br />
add task /Users/sho/Pictures/test/wiring-s.jpg<br />
add task /Users/sho/Pictures/test/org19361.jpg<br />
add task /Users/sho/Pictures/test/org19364.jpg<br />
add task /Users/sho/Pictures/test/org19375.jpg<br />
add task /Users/sho/Pictures/test/label.png<br />
add task /Users/sho/Pictures/test/246.png<br />
add task /Users/sho/Pictures/test/247.png<br />
add task /Users/sho/Pictures/test/248.png<br />
add task /Users/sho/Pictures/test/249.png<br />
return: /Users/sho/Pictures/test/zanmai.jpg => {width: 1024, height: 768, r: 22, g: 11, b:7}<br />
return: /Users/sho/Pictures/test/そうだ旧都へ行こう.jpg => {width: 1440, height: 1046, r: 21, g: 21, b:20}<br />
return: /Users/sho/Pictures/test/ed93d6de.jpg => {width: 1920, height: 1200, r: 45, g: 33, b:26}<br />
return: /Users/sho/Pictures/test/wiring.jpg => {width: 2106, height: 1584, r: 26, g: 24, b:31}<br />
return: /Users/sho/Pictures/test/f9286cff.jpg => {width: 1920, height: 1200, r: 88, g: 80, b:72}<br />
return: /Users/sho/Pictures/test/fae75abe.jpg => {width: 1920, height: 1200, r: 21, g: 15, b:22}<br />
return: /Users/sho/Pictures/test/img278_s201.jpg => {width: 1024, height: 768, r: 21, g: 92, b:107}<br />
return: /Users/sho/Pictures/test/la-metro.jpg => {width: 1024, height: 768, r: 128, g: 118, b:111}<br />
return: /Users/sho/Pictures/test/wiring-s.jpg => {width: 1024, height: 770, r: 28, g: 24, b:32}<br />
return: /Users/sho/Pictures/test/org19361.jpg => {width: 1280, height: 800, r: 0, g: 0, b:0}<br />
return: /Users/sho/Pictures/test/org19375.jpg => {width: 1024, height: 633, r: 235, g: 235, b:235}<br />
return: /Users/sho/Pictures/test/org19364.jpg => {width: 1024, height: 681, r: 217, g: 217, b:217}<br />
return: /Users/sho/Pictures/test/label.png => {width: 100, height: 80, r: 255, g: 255, b:255}<br />
return: /Users/sho/Pictures/test/247.png => {width: 140, height: 151, r: 246, g: 235, b:233}<br />
return: /Users/sho/Pictures/test/248.png => {width: 138, height: 149, r: 247, g: 234, b:232}<br />
return: /Users/sho/Pictures/test/246.png => {width: 141, height: 153, r: 246, g: 237, b:236}<br />
return: /Users/sho/Pictures/test/249.png => {width: 136, height: 147, r: 249, g: 234, b:230}<br />
</pre>
<br />
<br />
ちなみにCore2 DuoのMacbookProなので、workerを1つよりも2つ起動していた方が1.7倍ぐらい速かった。<br />
<br />
引数を複数渡したい時は、適当に渡してworker側で<a href="http://d.hatena.ne.jp/shokai/20091219/1261195886">boost::regex_split</a>でも使うか、getoptやboost::program_optionsでparseできるようにして渡せばいいかな<br />
client側での受け取りはRubyだからどうにでもできる。<br />
<br />
workerでエラーが起きた時の例外処理の出し方がよくわからない。ret_ptrにGEARMAN_SUCCESS以外を入れて返すべきなのか？<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/4966/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
