一般家庭のプリンタから巨大な紙わき出す

準備終わらない…
明日、朝から準備が結構残ってます。
スムーズに進めれば終わると思いますけどね。
PCの一般開放用ユーザに管理者権限を与えるのは問題だが、
制限だとうまく動かん。はて、どうしたものか。ちょっと研究してみよう。


さて、今日は巨大な印刷物の製作をしました。
具体的な方法は、まず巨大な印刷物をPDFプリンタに出力する。
実はAdobe Acrobat入ってるんですよ。だからDistillerでPDFに変換すればいい。
けどこれの動作がすごく遅い。だから大切な文書以外では使わない。
普段使ってるのは、CutePDF Writerです。
一瞬で書き出せるので便利です。
これでPDFに出したあと、Adobe Acrobatで開きます。
Readerではできないのですが、ここで印刷で、ページの拡大縮小で「大きなページを分割」を選ぶ。
ちなみにReaderでも、「1枚に複数ページを印刷」は使えたはず。
ここで、倍率100%だと、なんか変な感じになるので、倍率99%にします。
これでA2の文書ならA4で4分割される。
これをさらにPDFに出力。というのも印刷するマシンはReaderしかないから。
これを印刷するマシンに持参して、「大きなページを縮小」を選んで適当に印刷してもらう。
この設定だとプリンタの印刷限界に合わせて選んでくれると思います。


これでA4何枚かになるので、これを接合すると。
ところであらかじめ、A4の区切りの部分に極力文字がかからないようにしておいた。
A4の紙をまず上下それぞれで2枚接合する。
ここで、片方の紙の端をカッターで切り取って、もう1枚に乗りかかるように貼る。
裏からセロテープ(だったはず)で止めた。
その上下も同様に端をカッターで切り取って乗りかかるように貼る。
こんな調子でひたすら手作業です。
これが一番大変。
完成した状態で、折り曲げて持って行きます。


まぁなんともめんどくさいのですが、仕上がりはかなりいいですね。
以前、A41枚をA2のサイズまで拡大したかったときは、
これを半分に切って、コピー機で200%拡大の処理をそれぞれに施して、
これを接合してたが、印刷ずれるしうまくいかない。
しかしインクジェットプリンタでPCから指令する分には非常に精度がいい。
ぴったり接合できて驚いたものだ。
いやいや便利ですね。

準備を重ねてきまして、明日準備の集大成が

作業の合間に書いてるのだが、IE6だとすごいスタイル崩れるねぇ。
IE6は挙動が意味不明なので、解析する気が起きんので放置してたのだが・・・
さて、最近非常に忙しい。
学園祭のようなものがあるのだが、
それで部で展示するものを作っていろいろやってて非常に大変。
しかも、それで少し遅くまで学校にいて、帰ってこようとおもったら、
人身事故やらなんやら言うて、電車の運行がガタガタになってて、
えらいことでした。


やることはいくつかある。
プログラムの製作がまず1つ、これははじめに取り組んだ。
ただ、3つもプログラムを開発する必要があって非常に大変だった。
全部一人でやってるのだが、まぁ大変ですね。
変な事情で一部IronPythonを使ってやってたのですが、
作成、テスト、改良、テスト、改良、テスト、改良、OK
ということを、繰り返すペースが早くできるのは便利。
欠点はライブラリの情報をWebのMSDNで調べる必要があったりすること。
作成はTeraPadでやってました。このおかげで.NETのライブラリをかなり覚えてしまった。


それともう1つが印刷物の製作。
自分の展示について、印刷物を作らないといけないと。
これが結構めんどくさくて、いろいろあって今日完成したつもりです。
大きなポスター貼りたいなというのがあって、それを作ってたのよね。
A4を4枚くっつけて1枚にするという作業をしてました。
本当に難しい。文字ばっかりだからある程度ごまかし利きますけど。


あと、部だけに留まらんのだが、LEDの点灯回路の設計なんかもやってました。
たいした問題ではないんですけどね。
しかし、後で考えてみれば、LEDに20mAとかちょっと流しすぎだよなぁ・・・
10mAでも多いぐらいなのに。
でも今ある抵抗で作らなきゃいけなかったから仕方ないですね。
部の分は自分で製作までしました。
いろいろ変な設計で、はんだ付け大変だったな。
まぁこれはとっくに過ぎ去ったことなのですが・・・


いろいろやってきましたが、明日が準備日。
土曜日、日曜日で本番です。
本番でうまくいくとよいのですが、結構難しいことをやるのでどうなるかというのはあるね。
それにしても、僕は時間的にはまだ余裕があるほうです。
ほかの人では、かなり遅れが出ていて、えらいこっちゃとかありますからね。
準備日には完成していてほしいのですが、実際のところどうなるのでしょうか。
多少気になってはいるのですが、最終的にはうまくいくものだと思っています。
さて、明日は午後から準備に励みましょう。

タダなら作ってもいいかなとか思うカード?

「住民基本台帳カードの交付手数料が11月から無料に」
というのが市のOHPに載ってる。
まぁ字の通りです。
住民基本台帳カードは、まぁ住民登録証みたいなもんです。
だから、住民基本台帳カードということだな。なるほど。
使い道は基本的に3つあって、
1つ目は、住民票の広域交付を受けるために使う。
カードがあれば、どこの市町村の窓口でも一部省略の住民票を受け取れる。
2つ目は、公的個人認証機能の鍵セットを埋め込むことが出来る。
これは確定申告などをインターネットから行うのに必要ですよと。
鍵の手数料は500円で、ICカードリーダーはいるけど、超安価な電子認証サービスだということ。
3つ目は、特に理由がなくても発行できる公的な身分証明書ということ。
運転免許証は少なくとも原付の免許を取れないと持ってるわけがない。
保険証はしょぼい。パスポートは手数料高いし、漢字での名前とか住所が手書き。
今まででも500円という超安価で作れたけど、これから当分はタダですよ。


とはいうものの、確かにこれだけだとあまりうれしくない。
公的個人認証機能は必要な人に取ってはすごくうれしいけど、
大部分の人は使わない。というかICカードリーダーそれなりに高い。
公的な身分証明書の件は、多くの場合健康保険証で用が足りる。
写真付きの証明書が必要でも、運転免許証持ってる人多いし。
ところで、市町村によっては、印鑑登録証を磁気カード化して、
それで証明書自動発行機を使えるようにしているところがあるらしい。
実はこの機能を住民基本台帳カードに埋め込むことができる。
その加減があって、「住民基本台帳カードの交付手数料が11月から無料に」というのを大々的に宣伝してるの。
それなりの金を出して、自動発行機を市が買ったのよね。
これだと、ほぼ年中無休で、夜の9時まで発行できる。
会社休む気にならない人とかには便利な話です。
それで、カードの発行枚数は増えたらしい。
そのうえ、国が発行1枚ごとにさらに500円あげると言うのだから、
市民にたくさん持っていただければ、窓口の負担が軽減されますねと。
そう思っての無料化でしょう。


しかし、実際これでも利用する人は限られるでしょうが。
そもそも、住民基本台帳ネットワークが始まってから、
住民票を役所から要求されることはかなり減ったんですよ。
以前は結構多かったらしいけど。
まぁそれはそうなんだが、意外とめんどくさい写真付きの身分証明書を簡単に作れるのは利点ですね。
ただ、写真付きの証明書がない場合は、郵便で送られてきた確認書をまた持って行く必要がある。
さすがにその程度はしなきゃいかんらしい。
まぁそりゃそうですよね。
便利だなと思うのなら作るのもいいかもしれません。
まぁ残念ながら、僕はあんまり便利に使えそうにはないかなと。

Python式オブジェクト指向は便利

最近IronPythonでものづくりに励んでるわけだが、
まぁこういうのやってるとLLにおける、オブジェクト指向がわかってくる。
LLというのは、軽量プログラミング言語の意味ね。
ただ値の束がほしければ、リストとかタプルとか辞書とか使えばOKなのよね。
けど、大量の値の束ばっかりあっても困るときがあると。
そういうとき便利ですねということです。
Perlではあんまりオブジェクト指向使いやすくないから使ってなかったが、
Pythonはすごく簡単。だから大量生産したくなる。


IronPythonでWindowsフォームの開発をしてるのだが、
AというボタンのクリックイベントにBというウインドウを開く、
CというボタンのクリックイベントにDというウインドウを開く…
というのを延々を定義するのは無理。
これには2つ考えがあって、ボタンに開くウインドウのオブジェクトを登録しておいて、
そのボタンのクリックについて、全部に登録されたウインドウを開くとしておく。
もう1つはウインドウのオブジェクトを作って、それを開くという動作を1つ1つ登録する。
こうすればさっきのようなとんでもないことにならなくて済む。
まぁこれしようとすると、ボタンかウインドウのクラスを継承せないかんからめんどくさいけどね。
しかしPythonではその程度なら数行で書ける。

class opentest(System.Windows.Forms.Form):
def __init__(self,id):
self.Text="ID:%d"%id
def open(self,sender,e):
self.ShowDialog()

まぁ実際のは、コンストラクタである__init__でフォームの形状とか詳しく定義してるけど、
さっきいいたかったことはこれで実現できてますね。
ところで、何も継承しないでクラス作るときはどうするでしょうか。
答えは class foo(object): と書く。詳しく知らんのだがobjectがないと意味が変わってくるらしい。
これで、こういう風にすればいいと。

myrnd=System.Random()
for x in range(10):
for y in range(10):
button=System.Windows.Forms.Button()
button.Size=System.Drawing.Size(20,20)
button.Location=System.Drawing.Point(20*x,20*y)
button.Click+=opentest(myrnd.Next(100)).open
form.Controls.Add(button)

本当はPythonのrandomでやりたかったが、うまくいかんので.NETので。
こんなシンプルなコードでいけるんですね。


まぁいろいろな使い道があるだろうが、
なかなか慣れないので、そこまで活用できてるわけでもない。
考える暇があれば、ベタ書きでもソース書くからね。
そこから発見するものもあると。
まずは、WIndowsフォームのイベント周辺で活用してみてます。
こいつはさっき言った事情でベタ書きがほとんど通用しないので…
そうやってやっていくと、これは便利そうだと思えてきたものです。
まぁ騙されたと思ってやってみればよろしいということです。

柔軟なPerlのリスト、堅物のPythonのリスト

以前C#でプログラムを書いてたとき、doubleを用いて0で割れば無限大になってた。
これは結構すごいことですよね。もちろんintでは0除算はDivideByZeroExceptionの例外をスローする。
僕は、この取り扱い自体は正しいと思う。
というのも浮動小数点というのは、まぁぴったりの値にならんことが多いのよね。
例えば、1.00005-1.00004の計算結果は1.00000000001e-005となった。
さらにこの結果より1e-5を引くと、6.55112222065e-017という全く意味のない数字が出てくる。
そういうことを考えれば、等しいはずの数でも==で比較すれば違うと言うかもしれないし、
ひょっとすると0に近いけど0ではない数字が0になってしまうかもしれない。
まぁそういう数字で割るとき、不正な行為である0除算か、正当な0にきわめて近い数字での除算か
わからないならと、無限大を返すと。そう思いますけど。
同様のことはPerl、Pythonでは通用しませんよ。RubyではC#同様。
IronPythonでは一般的なPython同様例外が出るので、
0の場合は動作を変えて解決した。


Perlでこんな不気味なことができる。

my $arr=[];
$arr->[5]=100;
print "$_ : $arr->[$_]\n" foreach(0..$#$arr);

まぁリファレンスなのはあんまり気にしないでください。
初め長さ0の@$arrに急に5番の値を代入されたら、どうなるかということです。
少なくとも長さ6ないとだめなので、長さ0から6まで伸ばしますよと。
その伸ばした分は全部undefが入ってますよと。
まぁ不気味な仕組みではありますが、ものぐさな人にはありがたいことです。

my $obj1;
$obj1->[1]=20;
$obj1->[0]=10;
print join ',',@$obj1;

上の動作はかなり不気味。スカラーをリストのリファレンスのように取り扱うだけで、
勝手にリストのリファレンスになってると。ハッシュも同様。
ここまでくると何が何なのかわからん。きちんとmy使う分には便利かも。


さて、同様のことをPythonでやろうなんて考えちゃだめです。
当然です。Perlが変なだけです。
Pythonでは、リストの添字が範囲外とか、辞書のキーがないとか、そんなのでも例外。

mylist=[]
mylist[0]=10 # IndexError: index out of range: 0
mylist={}
mydict['tom']=20
print mydict['ken'] # KeyError: ken

以上の通りです。
Perlなら範囲外だろうがundef出すだけなんですよね。
けどundefという値をリスト、ハッシュの値に入れることはできる。
そうなると、exists関数で調べないと区別がつかん。
その点Pythonの取り扱いは適当だと思います。


まぁしかしPerlだと非常にいい加減な取り扱いでも便利に動くのに、困った。
上の mylist[0]=10 はどう書けばいいのかというのは少し考えた。
まぁ、こういうのは mylist.append(10) とするのがよさそうです。
ただ、欠番とかには対応できないよね。

while len(mylist)<=10:
mylist.append(None)
mylist[10]=20

これはどうなんだろ。確かに欠番対策にはなったけど。
結論から言えば、欠番作らないようにして、appendで後ろに後ろに連ねていくと。
どうもそうするのがよさそうです。
ちなみにRubyはPerlとかなり類似した取り扱い。さすがに勝手に配列になったりはないけど。


上のような事情でかなり苦労させられた。
初め、mylist[0]=10のような記述のどこが悪いのかと思った。
len(mylist)が0だと、0番の領域すら存在しないのね。
Perlやってると、pushというのは便利なものという印象だが、
Pythonにおいてはappendは必須である、と言えるような気がする。
さすが、いろいろやり方があるPerlですねとか、そうも思いますよ。

アクセスの多い記事はすごく多いよ

カウンタの記録を読んでたら、アクセスするページにかなり偏りがあるのに気付いた。
それで分析してみた。
CSVを読み込めて、きちんと計算できるプログラミング…
というわけでWindows PowerShellを使いました。
なんでやねんというのはあるかと思うが、実はかなりいけてる。
あらかじめ1行目に項目名を書いておく。これを使う。

PS> (ipcsv "in.csv"|group Page|select count,Name|sort count -Descending)[0..20]

一番の理由はipcsvでCSVファイルを読み込めることですけどね。
あとはLINQを連ねて、最後にこれを全部()でくくって配列をスライスすると。
PerlでやろうにもCSVの読み込みがめんどくさい。
まぁText::CSV_XSを使えばCSVの読み込みはできるみたいだけどね。
これと、ハッシュを組み合わせればできないことはないか。
しかしLINQは便利だ。同様の意味になりそうなSQLはこんなのか?

select count(*),Name from csvfile group by Name order by count(*) desc limit 10

だと思うけどね。
limitについてはMySQL的な書き方みたい。
Oracleではrownum擬似列の値を利用するとかあるけど。


さて、この分析結果を貼ろうと思った。
まぁそれにしても古い記事の内容は初めになんやらメモしてあるが、何の事やらわからん。
日記という都合、本題に関係ないことが書いてあることってのが結構あるんだよね。
それで全く意味のわからんことになってしまったのもあると。
まぁそういうのは読み飛ばしていただいて本題について注目していただきたい。
ほとんどがGoogleからの来訪者ですし。


アクセスが多かったの10記事挙げます。
「携帯動画変換君であるべき、Avisynthの使い方」
「FLVの新形態、On2 VP6を見る、DirectShowで」
昔は動画の圧縮、携帯電話での視聴をやってましたね。
どっちもDirectShow便利ですねという話です。この2つと次のがとにかく多い。
「Microsoftの作ったC++で使う.NET Framework」
C++/CLIは情報少ないからね。混沌としてるのであまり好きじゃない。
「Simcityでする都市計画のこと」
NAMのGLRはなんか使ってみたいと感じさせるけど、フリーズ多すぎ。仕方ないか…
「Bashの上で便利なコマンドたち」
たいしたこと書いてない記事なんだが、すごくアクセスが多い。なぜ?
「高画質な携帯動画変換君、ただしビットレート低め」
これはPC用動画の変換オプションだな。そういう研究をしてた時期もありました。
「動的に固定IPを割り当てる技」
DHCPの固定IP機能は便利ですよ。中央で統制取れますからね。重複とか防げるよ。
「相互インダクタンスは厄介なのは確か」
相互インダクタンスはなかなか慣れない。まぁこの記事は確かに参考になる。
「大改造の裏の小改造」
これはInternet ExplorerにおけるエラーコードC00CE56Eについての記述に釣られてきたのか。
「できた!TTC2TTF on .NET!!」
使ってる人いるのかな? 多分 .NET Frameworkで動くttc2ttfはうちだけだと思います。


まぁ新旧入り交じってますが、こんな感じ。
相互インダクタンスの記事がアクセス多いのは意外だが、ありがたい話だ。
結構変な話題を掘り下げて書くことがおおいので、
そういう方向から発見されるのも多いですね。
多くの記事は、単なる僕の道楽で終わってる気はするが、
一部の記事は、多くの人の役に立ってるかも知れない。知らんけど。
いつのまにか、このページのPageRankが1になってた。
PageRankなし、0、1と来ましたか。えらいことですね。
多くの方に来ていただいて、注目するぐらいヒットしてくれればなぁと思いますよ。

IEはdataに対応してないというので

おとといの記事において、dataスキームを使えば画像をHTMLの中にかけますよ。と大々的に言いました。
まぁMathMLの記事のときは、「さて、見えるか。多分ほとんどの人は見えない。」と書いた通り、
標準規格ながら、対応するブラウザがMozilla FirefoxとOperaだけ。
しかもOperaはかなりガタガタな対応で最近だいぶよくなってきたけど…という状態。
だから実質Mozilla Firefoxだけ対応というかなり悲惨な状態でした。
ただ、dataスキームは多くのブラウザで対応してるという認識でした。
Mozilla Firefox、Opera、あとiPodのSafariで使ってるの見たから、Safari全体対応だろう。
というか、Acid2はdataスキームで目玉の画像を貼ってるわけで、
対応しないとAcid2の変なテストに合格する見込みはない。合格しても何もないが…
ところがInternet Explorerでは7でも非対応、8より対応することになったらしい。


まさかこんなこととは思わなかった。
IE6では対応してなくてもIE7なら対応してると思ってた。
ちなみに現在のIE8はBata 2ということで、まだ完成ではありません。
しかしそれなりに使えるので、入れておくのも悪くない。
入れてみたら見事OK。これでいろいろできますね。
IE8になってさらに実用的なWebブラウザになっているのでね。
まぁもしかしたら問題があるかも知れんけど。Bataだし。


dataスキームの作り方についてだが、自作しろと言えばそこまでか…
しかし前に紹介した例は.NET Frameworkを使う例だからちょっと敷居が高い。
なので、Perlでやる方法を書こう。
Perlなら敷居がかなり低い…ですよね?

use strict;
use warnings;
use MIME::Base64;
open IF,'<',$ARGV[0] or die;
binmode IF;
my $buf;
while(read(IF,$buf,768)){
print encode_base64($buf,'');
}
close IF;

これでperl tobase64.pl foo.pngとかすればBase64に変換できる。
非常に簡単。使い慣れないソフトウエアよりよっぽど使いやすいはず。
これも結果が長くなるだろうから、リダイレクトで受けるか、Terapadにパイプで渡すなりしてください。
余談だが、ファイル名をソース中で指定を行うときはuse utf8;するとまずいらしい。
Windowsの場合、use utf8;やその類のことを書かずにやる必要があると。
付けずにShift_JISで書きましょうと言うことです。
まぁ@ARGVから取ってくる分には関係ないことですが。

難解だがgzipの圧縮展開である

微分方程式難しいねぇ…そりゃそうですか。
未知関数の微分積分を含む方程式ということで、
基本的には関数当てゲームというわけで、そりゃ難しい。
式を変形して積分して解くんですけどね。
一階線形微分方程式の解の公式なんてのがあって、まぁ覚えればいいと思うのだが、
とんでもない式だし、うまく積分できないならその方程式は解けんぞと。
しかし、自然界のいろいろを表す式って微分方程式も多いそうだ。
例えばだけど、RLC直列回路に直流電圧をかけたら、正弦波交流電流が流れることとか。
L(di/dt)+Ri+(1/C)∫idt=E、という方程式を解けばわかるんだよね。
まぁいろいろあるんですよということです。


最近3つのソフトウエアを同時に設計・開発してる。
1つはほとんど完成してるのだが、残り2つが大変。
プロトタイプを作って、機能を実装して…ということを繰り返してる。
まぁ小規模なプログラムだからできることですよね。
それで、Rich Text Formatを取り扱おうかなとか思って調べてた。
RTFなんだが、これが非常に冗長。圧縮するとすごい容量が減る。
というわけで圧縮したものをBase64に変換しておこうと。
IronPythonで開発してるが、try~finallyだらけで読みにくいので、C#で書こう。
どうもPython 2.5からwith構文というのがあるそうだが、残念ながらIronPythonでは実装されてない。
まずファイルを開き、圧縮したものをBase64に変換してコンソールに出力する件。

using( System.IO.FileStream fst=new System.IO.FileStream(fname,System.IO.FileMode.Open) ){
byte[] buf=new byte[fst.Length];
fst.Read(buf,0,buf.Length);
using(System.IO.MemoryStream mst=new System.IO.MemoryStream()){
using(System.IO.Compression.GZipStream gzst=
new System.IO.Compression.GZipStream(mst,System.IO.Compression.CompressionMode.Compress)){
gzst.Write(buf,0,buf.Length);
}
byte[] gzbuf=mst.ToArray();
Console.WriteLine( System.Convert.ToBase64String(gzbuf) );
}
}

using構文でC#ですら目が痛いが、IronPythonでは全部try~finallyで書いてるのでさらに目が痛い。
System.IO.Compression.GZipStreamにおいては、
書き込まれたら圧縮処理して、コンストラクタで指定されたストリームに書き出すストリームを提供、
コンストラクタで指定されたストリームから展開処理したものを、読み込むことができるストリームを提供、
のどっちかをできる。
しかし使いにくい仕様なんですよ。
圧縮時、あらかじめ、System.IO.MemoryStreamで圧縮結果を受けるストリームを作っておく、
コンストラクタで、このストリームと、System.IO.Compression.CompressionMode.Compressで圧縮モードだとする。
それで、GZipStreamのに、Writeで書き込む。
そして、GZipStreamを閉じたら、圧縮処理完了。受けるストリームには完全な結果が入ってる。


展開処理だが、これは明らかにめんどくさい。
Base64をバイト列に変換して、MemoryStreamのストリームに書き込んでおく。
GZipStreamのこのストリームを展開するストリームを作る。
このストリームを直接使えればいいのだが、Seek不可なので困ることがある。
System.Windows.Forms.RichTextBoxのLoadFileメソッドでRTFのストリームを渡したかったのだが、
Seekできんみたいな例外を投げるので、無理なんだなと。
そうなるとMemoryStreamのストリームにGZipStreamのストリームからReadしたのをWriteすると…
こんな作業をしないといけない。これがかなりめんどくさい。
以上の処理をするもの。

byte[] gzbuf=System.Convert.FromBase64String(gzb64)
using(System.IO.MemoryStream rtfst=new System.IO.MemoryStream()){
using(System.IO.MemoryStream gzmst=new System.IO.MemoryStream()){
gzmst.Write(gzbuf,0,gzbuf.Length);
gzmst.Position=0;
using(System.IO.Compression.GZipStream gzst=
new System.IO.Compression.GZipStream(gzmst,System.IO.Compression.CompressionMode.Decompress)){
byte[] buf=new byte[1024];
while(true){
int readlen=gzst.Read(buf,0,buf.Length);
if(readlen==0) break;
rtfst.Write(buf,0,buf.Length);
}
}
}
rtfst.Position=0;
rtfboxLoadFile(rtfst,System.Windows.Forms.RichTextBoxStreamType.RichText);
}

これはひどい。上で説明したとおりのことが書いてあります。
gzmst.Position=0; rtfst.Position=0;
はいずれもMemoryStreamにWriteした後、改めてスタート地点に戻って、
ここからReadしていただくという意味です。
ToArrayで配列に変換する分にはあまり気にしないけど、Readで読むときは重要。
あと、GZipStreamを読み取るのに、1024Bytesのバッファを用意して、
ループ回して、読み取り成功分だけMemoryStreamに書いていく。
Readの返り値は読み取り成功のバイト数だが、読めなくなれば0になるのでこれで抜けてる。
さっきのFileStreamでは、Lengthプロパティがあったけど、GZipStreamでは使えない。
だからこういう、まぁ正攻法でやらんといかんと。


これの使い道だが、TCPとかで通信するときデータを圧縮すると。
そのとき、データをGZipStreamのにWriteして、受けるMemoryStreamの中身を送信すると。
受信してMemoryStreamに投げ込んだら、これをGZipStreamで受けてReadしてMemoryStreamにWrite、
最後にMemoryStreamの中身を確認すれば本当に送りたかったデータがあると。
まぁこういう使い道が多そうです。
ちなみに。System.IO.Compression.DeflateStreamという類似したクラスがあります。
DeflateはgzipやZIPの原理です。Deflateを使ってgzipを実現してるのね。
今回のは別にgzipでなくてもDeflateでもよかった気はするが、gzipの方がデバッグに便利だしいいや。
こんな手間をかけてやるかは知らんが、有用なライブラリなので使うといいと思う。

Base64を使うと場合によっては幸せ

Base64というと、バイナリデータをテキストデータに変換するもっとも有名な方法ですね。
3Bytesを4文字に変換すると。だからファイルサイズは普通1.33倍に増える。
まぁ仕組みもさほど難しくないし、1.33倍で済むならそれでいいかという具合です。
もっとも多い使い道は電子メールの添付ファイルとか。
日本では本文は7bitコードであるISO-2022-JPでエンコーディングして送ることが多いけど、
韓国ではEUC-KR、台湾ではBig5とかいう8bitコードだから、本文もBase64に変換する。
最近ではUTF-8で電子メールを送ることあるけど、まぁこれも同様。
まぁSMTPの仕組み上8bitコードはうまく送れないから7bitに変換するのにも使われると。


このBase64だが、画像ファイルをテキストで表すのに結構使われる。
dataスキームというやつで時々使われてる。
data:image/png;base64,iVBORw0KG….
と非常に長いURI表記だが、これがPNGの画像を表してる。
「イ」の字が見えればOK
これを使うとHTMLの中に画像を埋め込んでしまったりということができる。
けどあまり大きな画像で使うと長い長いBase64の文字列ばっかりで困る。
しかしこういう使い道もあるんだということは知っておくと何かといい。


さて、IronPythonでいろいろ書いてたのだが、画像ファイルを相対パスで表すのが難しいと。
それにファイルを何個もコピーするのめんどくさいと。
その前にプログラムの設定ファイルについてはスクリプト内部に仕込んだ。
IronPythonの利用法の中に、データ、動作の設定ファイルとして使うというのがある。
C#からIronPythonを解釈することもできるんですよ。
今回はIronPython自体でプログラムを作成していたが、
末尾に固めて、設定について直接書いている。
C#でプログラム内部に設定を書くと、変更するたびに再コンパイルが必要だが、
IronPythonならばテキストエディタでスクリプトをすこし変更すれば問題ない。
その中にPNGファイルをBase64に変換したものを入れればいいと。
非常に長い文字列なので、非常に醜いものがあるが、1つのファイルで済みます。
PNGファイルの中身まではわからないけど、PNGファイルがあるなぁとはわかるのでいいですね。


まずファイルのBase64への変換。
IronPythonで書いたが、ここではわかりやすいようにC#で書く。

using( System.IO.FileStream fst=new System.IO.FileStream(fname,System.IO.FileMode.Open) ){
byte[] buf=new byte[fst.Length];
fst.Read(buf,0,buf.Length);
Console.WriteLine( System.Convert.ToBase64String(buf) );
}

これでfnameのファイル名のファイルについてBase64に変換できる。
あまりに長いので、ファイルにリダイレクトするとか、TeraPadにパイプで渡すとかするべきですね。
逆に、Base64の文字列から、System.Drawing.Bitmapに変換するのはこう。

System.IO.MemoryStream imgst=new System.IO.MemoryStream();
byte[] imgbuf=System.Convert.FromBase64String(base64);
imgst.Write(imgbuf,0,imgbuf.Length);
System.Drawing.Bitmap img=new System.Drawing.Bitmap(imgst);

System.IO.MemoryStreamクラスについては以前取り上げたことあるな。
Writeでバイト列を書き込んでいって、最後にToArray()で結合されたバイト列を得ると。
メモリにデータを書き込んだり、読み込んだりできる空間を作ると。
そういう風にとらえればいいと思う。
MemoryStreamの名前から予想がつくように、System.IO.Streamの実装の1つです。
そういうわけで、これを使ってBitmapを読み込むと。
まず、文字列をバイト列に変換して、これをMemoryStreamに投げ込んで、これを読んでいただいてBitmapを構成すると。
ちなみに、System.Drawing.Bitmapでは作成に使ったStreamは閉じてはいけない。
System.Drawing.BitmapはIDisposableを継承してるから、using構文使った方がいいのかな?


まぁこんな具合です。
ファイル名を指定してやるのに比べると手間は多いかなと。
まぁだけど単一ファイルで済むのはメリットか。
あと、Base64は1.33倍にファイル容量が増えるので少し考え物。
小さなPNGファイルなどについて適用するべきものでしょう。
こうやってXMLとかに画像やらバイナリを表すといいことあるかもしれませんよ。

Just in Timeが売りなのに事前コンパイル?

プログラムを開発中。
まぁいろいろやってるのだが、こういうしょうもないクラスは意外と便利。
IronPythonだが、C#でも同様のことだろう。

class clicklunch(object):
def __init__(self,lunch,option=''):
self.lunch=lunch
self.option=option
def click(self,sender,e):
p=System.Diagnostics.Process.Start(self.lunch,self.option)
sender.Parent.Visible=0
p.WaitForExit()
sender.Parent.Visible=1

ボタンのClickのイベントにこのクラスのインスタンスのclickメソッドを追加して使います。
静的メソッドでは、起動するプログラム名などを保持することができない。
だからそのプログラム名などと、クリック時の動作内容を束ねたクラスを作ると。
まぁほかにもやり方がありそうなもんだが、シンプルで便利な方法かなと。


最近IronPythonでプログラムを書くことが多い。
プログラム作成・実行を繰り返すのには便利。
C#のコンパイルにかかる時間ぐらいで、実行まで終わると。
ところが、実際に使うとなるとちょっと遅い。
コマンドプロンプトでipyと実行して、5秒ぐらいたってから動作が始まる。
初期化にしては長すぎるなぁと思わないこともない。
.NET Frameworkで動くプログラムは中間コードで書かれている。ILですね。
このILをはじめにコンパイルしつつ動作を開始することになるのだが、
これがちょっとはじめ遅い原因。


ところでよくつかうDLL類はコンパイルした状態でも保持されている。
速く動作させるためですよね。
このコンパイルした状態で保持するためのツールがありますよと。
.NET R-Tune
まぁこれをダウンロードしてインストール。
起動して、Changeで使う.NET Frameworkのバージョンを選ぶ。
.NET Framework 3.0、3.5も広い意味では2.0ですよ。
そしてipy.exe、ipyw.exeをドラッグ・アンド・ドロップ。すれば高速化されると。
まぁこの要領でよく使う.NET Framework上で動くソフトウエアを投げ込むといいと。


この結果かなり速くなった。プロンプトがでてくるまで2秒ぐらいに短縮された。
微々たる差だが、これだけでも快適度はかなり違いますね。
pyファイルをipyw.exeに関連付けしてみた。
ipyw.exeはコマンドプロンプトを立ち上げないIronPythonの実行環境で、
Windowsアプリケーションを動作させるには便利。
ただ、デバッグするには不向きかな。エラーとかが表示されないときがあるから。
デバッグするときとかは、cmdからipy foo.pyとか実行するのがおすすめ。
けど実用的に使うときは、IronPythonのプログラムをダブルクリックするだけで動作するから便利かな?