トップ 最新 追記

AOISAKURA 日記

2003|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|04|05|06|07|08|09|12|
2013|02|03|05|06|08|09|10|11|
2015|11|
2016|12|
2017|03|08|
2018|01|03|06|
2019|05|07|09|10|
2020|01|02|03|
2021|03|07|
2022|06|
2023|11|

pixiv / twitter

bluesky / misskey / pawoo

※発信する情報は、個人の見解・意見であり、所属する会社の見解・意見ではありません。


2005-11-02 描き描き [長年日記]

_ [book] 読了 - Project SEVEN

Hackに関する描写がいろんな意味でとてもおもしろかった、それに会話の雰囲気もあぁもぅHackerくせぇみたいな良い雰囲気だった。話しの展開もテンポ良く進むので、ぐいぐい読んでいける、ちょっと冗長かなぁと思う部分もあったけど、余裕で許容範囲内だった。話しの背景の時代設定とか、コンピュータのデティールは結構ベタベタかなぁと思ったけど、現代と離れすぎず、無駄な情報を与えないでかつ近未来な描写する上では適していたとも思える。

話しの筋に関してはいくつか、うーんと首をひねる部分もあるけれどこの本で重要なのは、"Hack"だろうから、それを十分に生かした話しとなっているのでおーけーおーけー。読むのにかかった時間は3時間弱かしら。

_ [work][life] ストレスを無くす仕事術、googlerの仕事の仕方

_ [media] 楽しいインターフェース

flashでシームレスに縮尺を操作しながら宇宙の広さを見ていけるコンテンツ。単純な画面だけど、とてもわかりやすい。その意外な遠さに気づけるところがおもしろかった。


2005-11-03 すすめるぜー [長年日記]

_ [life] life hack

2日前にリンクしたけど、内容がとてもおもしろいのでこの中で出てくるlife hackについてグーグル先生に聞いた中でおもしろかったのもをメモ。life hackという言葉の響きは、タイムマネージメントとかよりももっとエキサイティングに聞こえてくるので良い言葉だなぁと思った。life hackを知ったのはそれより少し前のradium softwareの記事から。

ここでは、4時間ごとに30分の睡眠をとることで、睡眠時間を削りながらも作業効率の低下を抑えられたという実験が紹介されている(長期的に見るとリスクもあるが)。

以下はlife hackというキーワードでヒントになりそうなリンク。

自分自身、wikiでプライベートな作業報告をつけていますが、やっぱり色々システム側で工夫するべきことが多い。

自分自身をhackする、と言うとすごい挑戦的かつ前向きな生活改善だなぁと思った。


2005-11-05 あたまいてぇ [長年日記]

_ [web] web2.0とamazonの新サービス

amazonのサービスはかなり欲しい機能だ。

_ [media][interface] google desktopとアラン・ケイ

最近やっとGoogle Desktopをチェックし出した。とはいっても、Google desktop searchがどんなもんか調べてみたいというだけなんですが。自前でDB構築してホーム領域のテキストファイルやらをインクリメンタルサーチとかできると楽かなぁとやっと思い出した。

昨日アラン・ケイの講演があったのか...orz。以前は京都でいけねーじゃんとか思ってたけど今回は未来科学館だったのかよ。もっとアンテナ広く持っておかないとなぁ。

_ [developerworks] Javaにまつわる都市伝説

こういうネタはJava Worldでも定期的に出てくるねー。

_ [book][comic] 買ったのは漫画と作画本

朝からZガンダムを見に行った帰りに、とらのあなで買い物。多分一番楽しみにしてたのはキョウハクDOG's、電撃帝王で読んでからもう一年以上たっての単行本化、細かいところも好き。

華麗なる食卓を突然買い出したのは、数日前の帰りの電車の中で隣のおっちゃんがヤンジャン読んでて、それを横から読んでて(ぉ、気になったから買ってみた。正直週刊誌の漫画は買いだすと巻数がえらいことになるのであんまり買いたくなかったんだけどなぁ...。まぁいいや。

漫画キャラ向けのデッサンの本、技術書でもそうなんだけども買っただけで軽く満足してしまうことが多い人間なのでちゃんと読み進めて実践していかないと意味が無い!

結局またカードで本の買い物、マジで財布の感覚が無くなってしまうので気をつけて使わないとなー、今月はもう何も買わない!


2005-11-06 あーうー [長年日記]

_ [life] 冬コミ落選

昨日よるずーっと待ってたけど、メール来ず。起きたらメールが来てた。「抽選漏れ」...というわけで落選でした(泣。

まぁこれでやりたかったことが早くできるようになったと思えば、まぁいいや。去年作ったプロットをやっと漫画の形にできたのは冬コミという目標があったからだし、この漫画に関しては近いうちにアップする予定です。

今後は、夏コミまでにコミティア辺りのイベントにでたかったんですが、引っ越しとか、仕事の方が本格的に忙しくなる関係で無理気、夏は受かりたいなぁ。

というわけで夏コミに向けて、もっとうまくなりたい、ネタもちゃんと用意したい。落選したのはもっと練習しろって事だと勝手に受け止めて精進しよう。

とはいえ、今日の午前中はふて寝します(泣。手伝ってくれるっていったnozomさん、こんな結果になってごめんなさいー。

_ [life] とりあえず掃除

ふて寝しようと思ったら、当落通知を待つ間に断続的に寝てたせいで全然寝られず。結局、掃除したり、録り貯めた番組を消化したり、linuxクライアントを久しぶりにいじったりして過ごす。でも未だに虚無感みたいなモノが消えない。まぁ途中になったままのfirefoxたんのネームとか、maxtorたんの完成原稿の行き先を決めてないからなんだろうけども、マジどうしたもんかのぅ。今からデジタルへ移行する材料に使ってみるか。

他にはPCの開発環境の再構築をしたり、調べモノしながら一日を過ごした。虚無感はあったけどもこんなにまったりした休日は久しぶりだった。明日から新しいサイクルを始めるけど、今日までの反省をちゃんと生かそう。あ、まずは大反省大会をしないとなぁ。

_ [mozilla] thunderbirdソース解析環境 その2

eclipse上でthunderbirdのソースを喰わせ直したら、eclipseがヒープ領域が足りませんといってエラーを返してきた、なので以下のようなコマンドオプションをつけて起動。-Xmsメモリ量でデフォルトメモリ量を指定し、-Xmxメモリ量で最大メモリ量を決められるらしい。(参考リンク:Programming Notes)

eclipse -vmargs -Xms512M -Xmx1024M

それでもインデキシングが100%になってしばらくたつとeclipseが落ちた。まぁでも検索ワーキングセットの検索とかは動いているっぽいのでまぁいいや。とか思ってたけどソースからビルドできない、これじゃIDLファイルからコード生成できねーし、そのうえいじってもどう動くのか確認できないじゃん。

うーん、色々ダルいなぁ

まずタイムスタンプが現在時刻より先になっていたのはNFSサーバの時計がクライアントより早いせいだったのでサーバ/クライアント両方でntpdateかけて時刻修正。libIDL/IDL.hが無いよーってエラーは、以下のように修正したらうまくいった。

libIDL-2.0/libIDL/IDL.h

...要するに、/usr/include以下のディレクトリ構成と不整合を起こしていたために、IDL.hが見えなかったようだ。うーん、C/C++のincludeに関する構造の対応についてイマイチちゃんと理解できていないなぁ、勉強しなおさんと。

と思ったら、今度はnetwork/resource/なんとか/content.rdf(だっけ?)が無いとかいってエラーが起きた。これってfirefoxのビルドの時にも起きたよなぁ...、どうしたもんか、ぎぎぎ。

_ [programming] GNU GLOBAL

ノートでもコード解析環境を整えたかったが、うちのノート(ThinkPad X21)ではeclipseを動かすにはメモリがどだい足りないので、Meadowでコードを読むことに。しかし、当然Meadowだけじゃコードが追えないので、GNU GLOBALを導入してみた。まだタギング中なので評価はこれから。etagsはタギングがおかしかったので没。


2005-11-07 むむむ [長年日記]

_ [comic] 買った漫画 ...え?

一昨日の日記で今月は漫画を買わないと書いていたのをあっさりを破る、まぁいいや。「ことのは」はys-22さんから勧められた漫画、「Swing Out Sisters」は放蕩オペラハウスでレビューしていて気になってた漫画。

「ことのは」の作者麻生みことは名前は知っていたけど読んだことは無かった。花夢らしい漫画だった、2話目がちょっと微妙で、期待しすぎたかなぁと思ったけど3、4話目と巻末の詩人の害が素晴らしくて買ってよかった。

漫画の内容とはあんまり関係ないけども、この漫画を読んでて、漫画の中の文字(言葉)で語ることと絵で語ることのバランスに今までと違う見方を見付けた気がして少し涙が出た、電車の中で。

で、ことのはをまったりしながら電車の中で読んでたら網棚の上に置いてた「Swing Out Sisters(18禁)」が降ってきてあやうく満員電車の中でぶちまけるところだった。この漫画を買った理由は只一つ、ツヤベタが綺麗だったから、以上。や中身はとってもいいでつよ。

_ [gimp] スクリーントーン処理

トーン処理したアフィリたん

デジタルで原稿を進めるのに必要なスクリーントーンのデジタル処理をやってみた。やりかたは、TEMPORARY DEPOTさんのところのDigitalScreenToneをそのまま実行。自分でもやりかたを考えていたけど、はるかにスマートで簡単なやり方だったので感動した。

できて喜んではいるけど、実は画像自体は元々350dpiなのに、トーンパターンの基準解像度は600dpiで解像度がちぐはぐになってる。なので日を改めて解像度を考慮してやり直そう。IRCでも師匠からいろいろ教えてもらったので、それを考えて〜。


2005-11-08 仕事でセミナー、ツマンネ [長年日記]

_ [link][web] web 2.0

_ [link][computer] オープンソース - XaraとTrolltech

Xaraのエンジンはcairoより早いらしいからcairoにマージしたらおもしろいことになるんかなぁ、とか考えたり。

_ [developerworks] クラスタリングの基礎とXML文書の語数

一つ目のクラスタリングの基本は、クラスタリングの概要として全体をわかりやすくコンパクトにまとめていて、導入文書のお手本のような記事だと思う。ふたつ目の記事は読んでも結局有用性がよくわからんかった。

_ [computer][gimp] Photoshopのメモリ節約技術を推測する (4) - ミニマップ、タイル

うーん、結局てきとうな縮尺に合わせて画像を用意しておくという方法になるのか。気になるのが、タイル化っていうのは単に画像をまとめて置くこととどう違うんだろう、訳して2P以降放置しているwriting gimp plug-inでもタイルと言う言葉が出てくる。うーん、ちゃんと調べないと。


2005-11-09 スムーズな集中へ [長年日記]

_ [link][network][life] @IT - 28歳から挑戦するITアーキテクト(4)とPoundで作るロードバランサとSSLラッパ

_ [gnome][gimp] FootNotes - GNOME etc

_ [life] 始めるを繰り返す

仕事で全然集中できていなくて、しかも理由が仕事とは全然関係ないすごい瑣末な事にとらわれているせいというなんとも非生産的な状態。とか言ってたら知合いから、「作業を中断させたらとにかくまた始めるようにする」と意外と集中できていくというアドバイスをもらった。頻繁に始めるを繰り返す。

確かにそうすると単純に考えても作業時間は増える、断続的にではあるが作業は継続していけるから作業量としてはいい感じになりそうだ。明日から実践してみよう。


2005-11-11 家帰ると眠すぎる [長年日記]

_ [gimp] タイルキャッシュについて


2005-11-12 のびのびした休日 [長年日記]

_ [gimp] how to write a GIMP plug-in 勝手和訳 2P目

1Pの私的和訳に引き続き、How to write a GIMP plug-in 2Pも和訳してみた。訳出の意図、注意は前回同様です。

前回別ページを作ると書きましたが、やっぱり日記に直接埋め込む形に、また今回はコードと画像も一緒に載せています。コードの中でコメントの無いコメント行がありますが、これはtdiary上での制約ですので無視してください。

この和訳文書はcreative commons : 帰属 - 非営利 - 同一条件許諾 2.5でライセンスされてます。

_ GIMPプラグインの書き方 How to write a GIMP plug-in 2P目

原著者: Dave Neary(mailto:bolsh@NOSPAM.gimp.org)

この章では、GIMPのプラグインインターフェイスを構築する為に基礎的な要素を示す。そこで、プラグイン中で利用できる単純だが役立つアルゴリズムを作成する。

_ はじめに

これから実装するアルゴリズムは単純なblur(ぼかし)である。GIMPには"Filters->Blur->Blur"で初期値と共に含まれている。

アルゴリズムは非常にシンプルです。画像の各ピクセル(画素)を近隣のピクセル達との平均値で置き換える。例えば、一番単純なケースである隣接する 3x3(図1参照)ピクセルを考えてみると、この場合5で中央の値として置き換えられる、これは9つのピクセルの平均値である。

_ Imageの構造

前回何の役にも立たないrun()関数を書いたが、再度以下のrun()関数のプロトタイプを見てみよう。

static void run (const gchar     *name,
                      gint             nparams,
                      const GimpParam *param,
                      gint            *nreturn_vals,
                      GimpParam      **return_vals);

これはフィルター処理で見ることができる(例えば画像修正をするプラグイン)。最初の3つ引数は、それぞれrun-modeであり、次はImageの識別子であり、もう一つはアクティブなDrawableを示すものである(レイヤーかマスク)。

GIMPのImageは次のものを含む構造をしている、大きなものではガイド、レイヤー、レイヤーマスク、そのほかImageと関連したデータ。 "drawable"という単語はGIMPの内部構造にはよく出てくる。"drawable"とは、われわれが取得したり、修正したりできる生のデータであるオブジェクトのことである。したがって、レイヤー、レイヤーマスク、選択領域は全て"drawable"である。

Drawableデータ構造

_ データアクセス

GimpDrawable を識別子(以下のコードの"drawable_id")から取得するためには、gimp_drawable_get()関数を必要とする。

GimpDrawable *gimp_drawable_get(gint32 drawable_id);

この構造体からさらにGimpPixelRgn構造体を通してdrawableデータへアクセスする。さらに、drawableデータの形式(RGB, Gray)を確認することもできる。GimpDrawableで利用可能な関数全てのリストはAPIリストの中にある。

plug-inにとってとても重要な関数が二つあり、それはgimp_drawable_mask_bounds()と gimp_pixel_rgn_init()である。一つ目の関数はdrawableデータ内で選択できる領域を与えてくれる、二つ目の関数は、データへのアクセスに使うGimpPixelRgnを初期化する。

ちゃんと初期化されたGimpPixelRgnを取得したならすぐに、いくつかの異なった方法でimageデータにアクセスできる。それはピクセル単位だったり、矩形単位だったり、行または列単位にできる。どの方法が良いかは選択したアルゴリズムに依存するだろう。加えて、GIMPはタイルキャッシュ機構を持っている、これによりロード/アンロードといったコストの高い処理を必要な時以外は行わないようにしている。

タイル

imageデータの取得、配置を行う主な関数は以下の通りである。

void gimp_pixel_rgn_get_pixel (GimpPixelRgn *pr, guchar *buf, gint x, gint y);
void gimp_pixel_rgn_get_row (GimpPixelRgn *pr, guchar *buf, gint x, gint y, gint width);
void gimp_pixel_rgn_get_col (GimpPixelRgn *pr, guchar *buf, gint x, gint y, gint height);
void gimp_pixel_rgn_get_rect (GimpPixelRgn *pr, guchar *buf, gint x, gint y, gint width, gint height);
void gimp_pixel_rgn_set_pixel (GimpPixelRgn *pr, const guchar *buf, gint x, gint y);
void gimp_pixel_rgn_set_row (GimpPixelRgn *pr, const guchar *buf, gint x, gint y, gint width);
void gimp_pixel_rgn_set_col (GimpPixelRgn *pr, const guchar *buf, gint x, gint y, gint height);
void gimp_pixel_rgn_set_rect (GimpPixelRgn *pr, const guchar *buf, gint x, gint y, gint width, gint height);

imageデータへのアクセス方法は他にもある(しかも頻繁に使われる)。その方法はタイルキャッシュレベルのデータ管理を行うことができる、これについては後ほど詳しく述べる。

_ 画像の更新

最後に、drawableデータを修正したプラグインはコアへデータを送るためにflushしなければいけない、またアプリケーションに対して表示を更新する旨を伝えなければならない。これは次の関数を利用する。

gimp_displays_flush ();
gimp_drawable_detach (drawable);

_ blur()の実装

いくつかのやり方の異なる手法を試すべく、blur()関数に処理を委譲させるようにする。run()関数は以下の通りである。

      static void run (const gchar      *name,
                       gint              nparams,
                       const GimpParam  *param,
                       gint             *nreturn_vals,
                       GimpParam       **return_vals)
      {
           static GimpParam values[1];
           GimpPDBStatusType status = GIMP_PDB_SUCCESS;
           GimpRunMode run_mode;
           GimpDrawable *drawable;
           //
           /* Setting mandatory output values */
           *nreturn_vals = 1;
           *return_vals = values;
           //
           values[0].type = GIMP_PDB_STATUS;
           values[0].data.d_status = status;
           //
           /* Getting run_mode - we won't display a dialog if 
            * we are in NONINTERACTIVE mode */
           run_mode = param[0].data.d_int32;
           //
           /*  Get the specified drawable  */
           drawable = gimp_drawable_get (param[2].data.d_drawable);
           //
           gimp_progress_init ("My Blur...");
           //
           /* Let's time blur - don't forget to include time.h */
           /* {
            *   time_t before = time(NULL);
            */
           blur (drawable);
           /*   printf("Blur() took %ld seconds.\n", time(NULL) - before); 
            * } */
           //
           gimp_displays_flush ();
           gimp_drawable_detach (drawable);
           //
           return;
      }

ここで説明するべき部分は少ししか無い。gimp_progress_init()の呼び出しはプラグインの進歩計測の初期化を行う。後の処理で、 gimp_progress_update(double percent)を呼び出した場合、入力引数として与えられたパーセンテージを視覚的に表現する。run_modeを確認すれば、グラフィカルインターフェイスを表示するかどうかがわかる。run_modeがとりうる値はGIMP_RUN_INTERACTIVE, GIMP_RUN_NONINTERACTIVEまたはGIMP_RUN_WITH_LAST_VALSである。 GIMP_RUN_WITH_LAST_VALSはGIMP上か、scriptか、フィルタの最適用をを実行することを表す。

最初のバージョンではblurアルゴリズムにgimp_pixel_rgn_(get|set)_pixel()を使う。このバージョンは以下に挙げる。詳細については後述する。

gimp_drawable_mask_bounds()はフィルタ効果の計算に制限を与える、これは有効な選択範囲内の領域以外を取り除くことで制限とする。この方法で処理を制限するのは、パフォーマンス改善のために重要なことである。

gimp_pixel_rgn_init()で入力引数としてdrawableや処理範囲、GimpPixelRgnの生成物の挙動を変更する二つの真偽値を扱う。一つめの真偽値は、"set"のオペレーションがshadowタイル上で行われる必要があることを示す。これは、変更された全てのデータがまとめられる時、gimp_drawable_merge_shadow()が呼び出されるまではオリジナルのデータをそのままにしておくためである。二つ目の真偽値は、まとめるためにコアに送られる時に変更したタイルに"dirty"タグをつけることを示す。たいていの場合、データ読み込みの場合、二つの入力引数には"FALSE"と"FALSE"を使い、データ書き込みの場合には、"TRUE"と"TRUE"を使う。それ以外の組合せはめったに使われない。

      static void blur(GimpDrawable *drawable)
      {
           gint i, j, k, channels;
           gint x1, y1, x2, y2;
           GimpPixelRgn rgn_in, rgn_out;
           guchar output[4];
           //
           /* Gets upper left and lower right coordinates,
            * and layers number in the image */
           gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
           channels = gimp_drawable_bpp(drawable->drawable_id);
           //
           /* Initialises two PixelRgns, one to read original data,
            * and the other to write output data. That second one will
            * be merged at the end by the call to
            * gimp_drawable_merge_shadow() */
           gimp_pixel_rgn_init (&rgn_in, drawable, x1, y1, (x2 - x1), (y2 - y1), 
                                FALSE, FALSE);
           gimp_pixel_rgn_init (&rgn_out, drawable, x1, y1, (x2 - x1), (y2 - y1), 
                                TRUE, TRUE);
           //
           for (i = x1; i < x2; i++)
           {
                for (j = y1; j < y2; j++)
                {
                     guchar pixel[9][4];
                     //
                     /* Get nine pixels */
                     gimp_pixel_rgn_get_pixel(&rgn_in, pixel[0], MAX(i-1,x1), 
                                              MAX(j-1, y1));
                     gimp_pixel_rgn_get_pixel(&rgn_in, pixel[1], MAX(i-1,x1), j);
                     gimp_pixel_rgn_get_pixel(&rgn_in, pixel[2], MAX(i-1,x1), 
                                              MIN(j+1,y2-1));
                     //
                     gimp_pixel_rgn_get_pixel(&rgn_in, pixel[3], i, MAX(j-1,y1));
                     gimp_pixel_rgn_get_pixel(&rgn_in, pixel[4], i, j);
                     gimp_pixel_rgn_get_pixel(&rgn_in, pixel[5], i, MIN(j+1,y2-1));
                     //
                     gimp_pixel_rgn_get_pixel(&rgn_in, pixel[6], MIN(i+1,x2-1), 
                                              MAX(j-1,y1));
                     gimp_pixel_rgn_get_pixel(&rgn_in, pixel[7], MIN(i+1,x2-1), j);
                     gimp_pixel_rgn_get_pixel(&rgn_in, pixel[8], MIN(i+1,x2-1), 
                                              MIN(j+1,y2-1));
                     //
                     /* For each layer, compute the average of the
                      * nine */
                     for (k = 0; k < channels; k++)
                     {
                          int tmp, sum = 0;
                          for (tmp = 0; tmp < 9; tmp ++)
                          {
                               sum += pixel[tmp][k];
                          }
                          output[k] = sum / 9;
                     }
                     //
                     gimp_pixel_rgn_set_pixel(&rgn_out, output, i, j);
                }
                //
                if (i%10 == 0)
                    gimp_progress_update ((gdouble) (i - x1) / (gdouble) (x2 - x1));
           }
           //
           /*  Update the modified region */
           gimp_drawable_flush (drawable);
           gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
           gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), 
                                 (y2 - y1));
      }

_ 列処理

作成した関数にはパフォーマンス上不利なバグがある。300x300の範囲上で、時間計測処理を有効にさせると、K6-2 350MHzのPC上で12分かかっている。比較のために、同じ範囲に対してガウシアンblurをかけたら3秒かかった。

作成した関数を、gimp_pixel_rgn_(get|set)_row()を使って修正すれば結果は良くなるだろう。先ほど760秒かかっていた処理が、6秒になった。コードは以下の通りである。

      static void blur(GimpDrawable *drawable)
      {
           gint i, j, k, channels;
           gint x1, y1, x2, y2;
           GimpPixelRgn rgn_in, rgn_out;
           guchar *row1, *row2, *row3;
           guchar *outrow;
           //
           gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
           channels = gimp_drawable_bpp(drawable->drawable_id);
           //
           gimp_pixel_rgn_init (&rgn_in, drawable, x1, y1, (x2 - x1), (y2 - y1), 
                                FALSE, FALSE);
           gimp_pixel_rgn_init (&rgn_out, drawable, x1, y1, (x2 - x1), (y2 - y1), 
                                TRUE, TRUE);
           //
           /* Initialise enough memory for row1, row2, row3, outrow */
           row1 = malloc (channels * (x2 - x1) * sizeof *row1);
           row2 = malloc (channels * (x2 - x1) * sizeof *row2);
           row3 = malloc (channels * (x2 - x1) * sizeof *row3);
           outrow = malloc (channels * (x2 - x1) * sizeof *outrow);
           //
           for (i = y1; i < y2; i++)
           {
                /* Get row i-1, i, i+1 */
                gimp_pixel_rgn_get_row (&rgn_in, row1, x1, MAX(y1, i-1), (x2 - x1));
                gimp_pixel_rgn_get_row (&rgn_in, row2, x1, i, (x2 - x1));
                gimp_pixel_rgn_get_row (&rgn_in, row3, x1, MIN(y2-1, i+1), (x2 - x1));
                //
                for (j = x1; j < x2; j++)
                {
               /* For each layer, compute the average of the nine
                * pixels */
                     for (k = 0; k < channels; k++)
                     {
                          int sum = 0;
                          sum =  row1[channels * MAX((j - 1 - x1), 0) + k]
                               + row1[channels * (j - x1) + k]
                               + row1[channels * MIN((j + 1 - x1), x2 - x1 - 1) + k]
                               + row2[channels * MAX((j - 1 - x1), 0) + k]
                               + row2[channels * (j - x1) + k]
                               + row2[channels * MIN((j + 1 - x1), x2 - x1 - 1) + k]
                               + row3[channels * MAX((j - 1 - x1), 0) + k]
                               + row3[channels * (j - x1) + k]
                               + row3[channels * MIN((j + 1 - x1), x2 - x1 - 1) + k];
                          outrow[channels * (j - x1) + k] = sum / 9;
                     }
                     //
                }
                //
                gimp_pixel_rgn_set_row(&rgn_out, outrow, x1, i, (x2 - x1));
                //
                if (i%10 == 0)
                     gimp_progress_update ((gdouble) (i - y1) / (gdouble) (y2 - y1));
           }
           //
           free (row1);
           free (row2);
           free (row3);
           free (outrow);
           //
           gimp_drawable_flush (drawable);
           gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
           gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), 
                                 (y2 - y1));
      }

_ 次回予告

次回は、タイル毎に処理する方法を示す。また、入力引数を扱うようにしアルゴリズムを変更することで、パフォーマンスにも注目する。

_ やっぱり倍になったか

コードも入れたら量が倍になった、しかも画像の入れ方が微妙になっちまった。これで日記を読むレスポンスに影響してたら考えよう。見にくいんじゃゴルァとかあったら教えていただけると幸いです。3P目は近いうちにやる予定です。

う、他のエントリをつっこむと日記構造の意味的におかしくなってしまうなぁ。やっぱりまとめるか...。

_ [game] 「HALO」「HALO2」がXbox360で遊ぶとパワーアップ

実はXBOXを買おうか迷っていたんですが、俄然XBOX360の購入意欲が沸いてきました。問題は普通のテレビが無いからアップスキャンコンバータでも買わないとあかんかも、D-SubかDVIで接続できんのかなぁ...>360

_ [java] JavaOne3日目 - フリーソフトとプロプラエタリソフトのEnterpriseシステム比較

Linux+Apache+Tomcat+Jboss+PostgresとHP-UX+WebLogic+Oracleの比較の項が興味深かった。パフォーマンスうんぬんではなく、それぞれの挙動についてとかそういう視点で見るのかと思えておもしろい。PDFかなんかで手に入らないかなぁ...。

_ [linux] TOMOYO linux with SAKURA linux, SYAORAN and CERUBERUS

さりあんさんのとこのエントリで知ったけど、NTTおかしいよ!(褒め言葉)

それぞれの略称が無理くりすぎるとか、ケロちゃんの綴りが「CERBERUS」なあたりがKerberosと混同しないようにしようとしてる(やることも似てるしね)ところとかがおもしろすぎる。

sourceforge.netから持ってこれるのはkernel patchとutility toolのようだ。テスト機使ってつっこんで見ようかしらね。


2005-11-15 そろそろ忙しい...のか [長年日記]

_ [mozilla] thunderbirdのビルド

結局、thunderbird-1.0.7はソースからビルドすると、以前と同じところでビルドがこけるのであきらめ。そこでモノはためしと1.5-rc1のソースを持ってきてビルドしたらあっさりビルドできた。.mozconfigは次の通り

. $topsrcdir/mail/config/mozconfig
ac_add_options --disable-debug
ac_add_options --enable-default-toolkit=gtk2
ac_add_options --enable-optimize=-O2

で、あとは「gmake -f client.mk build」でビルド。というわけでdebugを有効にして再ビルドしてみよう。

む、ついでにxftとpangoを有効にしたら起動しなくなった...。さてどっちが悪いんだろう...。

_ [linux][drawing] Fedora logoの作成過程

Fedoraのロゴを作成する過程でどのようにイメージをまとめ、それをロゴの形に結実させたのかがよくわかるスライド。すごいおもしろい。

_ [web][python] PythonによるRuby on Railsの対抗馬?「TurboGears」

最近はWeb絡みの事を考えると、ajaxやってみたいっていう方にしか行かない、つってもたいして考えてないけども、実際にscript書いてるわけでもないし。そのうえ、JavaScriptをいじるのは正直ダルいなぁと思っていたら、pythonからアクセスできるフレームワークがあるらしい。

rNoteを触って、日記以外のコンテンツも統一的なUIで扱わせたいなぁと考えてて、でもCMSは正直でかすぎるような気がする。というわけで、これ使ってまね事をやってみる予定。まずはDBとコンテンツのやりとりをさせないと。

ぉ、pythonのSQLObjectはPostgreSQLも扱えるのか。


2005-11-16 いろいろ思案中 [長年日記]

_ [work] IT Pro - お客様だからこそ,あえて言わせていただきます

納得できる部分があるとはいえ、自分達も動かないと状況は是正されないんだろうなぁ。自分に何ができるんだろう。

_ [work][programming] ITMedia - ベンダーが触れたくないSOAの課題

結構仰々しいタイトルの割りに言ってることは普通のこと、セマンティックギャップなんて別にSOAに限った話じゃない。って本文中でも書いてるし、何が言いたいのかよくわからん記事だ。

_ [link][java] Java SE 6 Mustang じゃじゃ馬ならし

Mustangの特徴的な部分をちょうど良い分量の記事で紹介している。


2005-11-17 さくさくpython [長年日記]

_ [mozilla] thunderbirdのビルド環境の肥大化

無事ビルドもできるようになったので、eclipse上でthunderbirdのコーディング環境を作っていたら、ディスクがあっぷあっぷ言い出した。duで見てみたら、workspaceのサイズが3GBを越えてしかもまだ足りてなさげ...。

...
3061    ./.workspace
1484    ./cvs
441     ./share
1013    ./tmp
...

これ普段thunderbirdの開発してる人って一体どうやって開発やってるんだ?もっと大きいHDDつけろってのか?

...障害対策用のHDD降ろそうかなぁ。よし、給料入ったらもう一本HDD買おう。

_ [mozilla] thunderbird 1.5rc1のベイジアンフィルタの日本語処理

というわけで、emacs上でソースを見ていたら(gtag実行中)、nsBayesianFilter.cppに日本語の処理が入ってた。まだ詳しくはおいかけていないけど、かなりおもしろそう。て、実は1.0.7の時からあったりしたのかな...どうなんだろ、まぁいいや。今は保留、やる気でるまで保留(ぅぁ


2005-11-19 書き書き [長年日記]

_ [python] TurboGears install error

サーバ環境ではインストールできたのに、開発用クライアントでインストールしようとするとcElementTreeのインストールで以下のようなエラーが出てインストールができなかった。

Traceback (most recent call last):
  File "ez_setup.py", line 208, in ?
    main(sys.argv[1:])
...
  File "/usr/lib/python2.4/distutils/command/build_ext.py", line 442, in build_extension
    sources = self.swig_sources(sources, ext)
TypeError: swig_sources() takes exactly 2 arguments (3 given)

何が悪いのかなぁとsetup.pyを見ていたけど、google先生に聞いたらそのものズバリがあった。

というわけで、Pyrexをアンインストールしたら普通にインストールできた。

...始めから調べりゃよかった。1日無駄にしちゃったなぁ、もぅ。

_ [emacs][python] emacsが固まる

pythonのプログラム編集中にリフォーカスさせたときとかsemantic.cacheを作ってるときになぜか固まる。でもウィンドウの描画はされるので多分emacs自体は生きてる。こういうときって原因どうやって特定するんだろう...。

とりあえず設定のJDE(多分CEDETの設定)を全部コメントアウトしたら普通に使えるようになった。

_ [python] psycopgを使うにはmxDateTimeが必要

TurboGearsのmodel.pyで定義したモデルをDBに作成しようとしたら以下のエラーが出た。

ImportError: No module named DateTime

ん?"datetime"ならpythonデフォルトで入ってるじゃないか...と思ったらそうではなく"DateTime"、DとTは大文字でpsycopg(python用postgreSQLのO/Rマッパー)が使うらしい。で、またgoogle先生に聞いたらどうやらmxDateTimeというモジュールが必要くさい。

というわけでmxDateTimeのサイトからsourceコードをダウンロードしてビルド・インストール。問題なく終わり、対話モードでpsycopgをimportしたらImportErrorを吐かずに正常に処理できた。でもって無事本来のテーブルも作れた。

mxDateTime、名前まぎらわしすぎっていうかpsycopgをインストールするときにエラーぐらい出してくれよ、しかもサイトもダラダラ長くて見にくいし。

_ [python] TurboGears - Getting Started と The 20 Minute Wiki消化

一日かかって一通り終わり、英語きつい。書いてあることはともかく書いてないことで調べなきゃいけないことがいっぱいになってきた。

とはいえ、あとは認証とか権限の処理どうするかを調べて管理者モードの作り方がわかれば一通りのものが作れそうな予感。がんばろう。


2005-11-20 引き続きpython [長年日記]

_ [python] FunctionDecorator = 関数"修飾"子

python 2.4からFunctionDecoratorという機能が追加されていたみたいです。関数宣言の一行前に"@"を頭にして宣言します。柔軟なのはいいが記号を使われるのは微妙。

で問題は、DeveloperWorksのCherryPyのドキュメントを読んでいたら「@cpg.expose」を"装飾子"と読んでいたので混乱してしまった。

おかげで最初、装飾子って何だよ、全然見付からないーとかなっちゃって、どうも"装飾子"なんて訳しかたしてるのはこの記事だけだということに気がついた。

というわけで、一般的な訳しかたは「Decorator = "修飾"子」っぽい。

_ [python] CherryPyで認証をかける

Basic認証のコードをそのままコピってTurboGears上で動いたけど特定のページにのみかける方法がわからないので現在模索中。


2005-11-21 創立記念日...はほんとは昨日 [長年日記]

_ [anime] ぱにぽに

作業が手に着かないぐらい新OPにどっはまり。先週見られなかったしのぅ

_ [python] CherryPy - 特定のURLに対してのみBasic認証をかける

モノはBasic Authorization(CherryPy)のbasicauthfilter.2.py(以下basicauthfilter2.pyと名前変更しています)と同じです。違うのはRootクラスでは無いということで、やったことを以下に挙げます。

basicauthfilter2.pyのRootクラスを任意のクラス名に変更します(ここではAuthTest)。次にこの変更したクラスをcontrollers.pyのRootクラスで生成します。このとき変数名は「auth」とします。なのでcontrollers.pyには以下の記述を追加します。

from basicauthfilter2 import AuthTest
...
class Root:
    auth = AuthTest()
...

そして、AuthTestの_cpFilterListの生成部分でBasicAuthFilterの引数をつっこむところのunauthorizedPathを以下のようにRootに足した変数名を付け足します。

    _cpFilterList = [ BasicAuthFilter(cppasswordPath='.cppassword',
                                      realm='localhost',
                                      unauthorizedPath='/auth/unauthorized') ]

あとは***start.pyと同じディレクトリにに平文で「ユーザ名:パスワード」が書かれたファイル.cppasswordを生成します。そうしてhttp://localhost:8080/authにアクセスすれば認証のダイアログが開きます。これでauth以下(つまりAuthTestで定義したページ)に対しては認証がかかりますが、auth以外のページには認証無しでアクセスできます。

BasicAuthFilterの引数にダイレクトで"auth"とか書くのは正直まずいので修正する必要があります。まぁ後回し...(泣

_ [programming] DBのテーブルとカラムが増えていく

日記コンテンツをDBにつっこむべくDB設計をしてるけどどんどん増えていく...。SQLObjectでORマップするとはいえ属性としてのテーブルは考えないと当然いけないわけですが、うーん破綻しそう。まぁいきなり全部つっこもうとするのが間違いなのかも。大体できたくさいからこっからSQLObjectのモデルを作る。その過程でボロがでそう。

今月いっぱいはこんなこと続けてます。はてさて何ができるやら。


2005-11-23 さくさく進もう [長年日記]

_ [drawing] 久しぶりに

まゆらラフ画

冬コミ原稿やってるときはもういっぱいいっぱいだったのでサボってたけど、その分を取り返すべく練習再開。

ひさしぶりにまゆらを描いてみる。んが、全然幼くならない...、まぁ原因は顔の描き方矯正中なんで昔の癖を思い返してしまうことを恐れているせいなんだけども。

まぁとりあえずこれで線画にして色塗るか。

gimpがなぜか途中から急激に重くなる。ヒストリがスワップしたのかと思ったけど、CVSでも起きてるし、共通の問題か?

_ [python] SQLObject - 一気に複数のDBとの繋がりは作成できない?

TurboGearsで複数のDBを扱うためにmodel.pyに以下のような記述をした(実際はもっとカラム多いけど)。

class A(SQLObject):
    b = MultipleJoin('B')
    c = RelatedJoin('C')
class B(SQLObject):
    a = ForeignKey('A')
class C(SQLObject):
    a = RelatedJoin('A')

上の例で「%tg-admin sql create」したらBのテーブルを作るときに「relation "A" does not exist」みたいなエラーを吐かれた。で、記述の間違いななさそうなのになぁと思って、Cのテーブルの定義をコメントアウトして、Aの中のCの定義をコメントアウトしたらなぜかうまくいった。で、コメントアウトしたのを戻してもう一回sql createしたら全部できた。...なぜだ?

気になるのは多対多のリレーション(SQLObject0.7日本語マニュアル)で、多対多のテーブルを作ると中間テーブルが作られると書かれているのにそれが直接テーブルの一覧を見ても見付からないということ。まぁ動かしてうまくいかなければそのとき調べよう(ぇ

全然うまくいってなかった。既に作ったテーブルに対して新しくカラムを追加するには、別の手段でカラムを追加しないといけない。ってSQLObject 日本語マニュアルにも書いてあるじゃん。

ぬぅ、しかもDB作りなおしたら中間テーブル作られてるし、やっぱりおいらのmode.pyの書き方が悪かったのかorz。


2005-11-24 休み [長年日記]

_ [life] 体調悪い

というわけで布団の中からもそもそ。ノート万歳

_ [python] SQLObject - データの取得

SQLObject 0.7では複数のカラムで主キーを構成することはできない。ただ、"alternateID"を使ってid以外にキーとなるカラムを指定するとby***というメソッドでアクセスできるようになる。それ以外の方法は、複数オブジェクトの選択に書いてある方法で取得、"q"を忘れない!


2005-11-25 ふっかーつ [長年日記]

_ [book][comic] 買った漫画、雑誌

後、C Magazine 12月号を今更購入。C Magazineは特集がマルチスレッドプログラミングだったので中身を大して確認せずに購入、そしたら扱ってる環境はwin32とJavaだったのでpthreadを期待してた自分はしょんぼり。って買う前に確認しろよって感じやね。あぁもぅいきなりやっちまった。と嘆いてもしょうがないので、一昨年大学院で受けた講義資料と突き合わせながら復習に使おう、mutexに関しては理解が怪しかったし。

NHKにようこそはなんだか同じ事を繰り返してる感じだなぁ...。しかもあんまり救いようが無い主人公なんでストレスが溜るまま解消されない。というわけで次で最終巻とかいうわけでなければ次巻以降は買わない。

STUDYは高須賀由枝らしい漫画、丘あり溝あり(ぇぐらいの勢い、まぁ雰囲気を楽しむ漫画です。シュガーポッド復活は素直に嬉しい。

V・B・ローズは相変わらずたまらん。とはいえ巳艶がいたたまれなくなっているみたいに、余りに二人の展開が悪すぎる〜、それが良いといえばそれまでだけども。ナガレの頑張りに期待したい所存。


2005-11-26 アニオタ的池袋買いもの [長年日記]

_ [book][comic] 池袋で買った本

給料日直後なのに既にお金無い。うぅ貯金してるのがやっぱり辛いのぅ。ほんとはPostgreSQLの本を買っていくつもりだったけど、改訂版シーラカンス本は内容的にこれを買う必要をあまり感じなくなっていた。それはそうと池袋のジュンク堂にPostgreSQL CEの本無かったんだけどどこに売ってんだ?

後は今作ってるWebツールの為の本、サイバーテロの技法はPHPだけどもWebクラッキングの手法がまとまって具体的に載ってる情報としてはこれぐらいしか無いので買った、まぁPHPを読むの自体は大して難しくないし。

AQUA2巻、うぅやっぱり気持ち良いなぁ、ちょうど今週やってた話もあって満足。

コミッカーズは年二回になって一回目、装丁が豪華になって高くなったけど薄くなったのが微妙、でも読みたい記事も多かったしいいか。

_ [anime] 買ったCD

乙女〜は二曲めも結構良かった。

ぱにぽにだっしゅのCDは二人目は常に歌いかたが微妙なのか、上手くないのか、一人目の印象が強いせいなのかにんとも微妙だ。六号さん好きなのに。

_ [anime] 借りたDVD

相変わらずスカっとするアニメーション、とはいえ初代ほどのカタルシスを感じないのはなんなんだろうなぁ。でも好き、細かい描写が特に。

_ [akiba] 金スマ - 話題の秋葉原SP

全ては安住アナを眺めるため...嘘、ちょうど点けたらやってたから頑張ってみてみた。で、出てきたメイド喫茶が@home cafe、...ぷらっとホームの上じゃねぇかorz。こんな形でテレビに出てくるロゴがなぜか痛々しい(泣


2005-11-27 昼まで寝た [長年日記]

_ [python] turbogears(cherrypy) - DBに格納した画像を表示する

以下の方法で画像を単独で表示させることはできたけど、文章内に画像を表示させるのは一時的にキャッシュファイルにした方がいいのかなぁ。SQL Object FAQにもあったようにDBに突っ込む前にbase64でエンコード。でもぶっちゃけこれであってる確信全然無い、挙動把握できてないし。しかもtubogears(cherrypy)経由で画像の保存ができてないし。(tg-admin shellからやった)→解決

# ===== mode.py =====
class Image(SQLObject):
    data = StringCol()
    height = IntCol()
    width = IntCol()
    def _set_data(self, value):
        self._SO_set_data(value.encode('base64'))
    def _get_data(self):
        return self._SO_get_data().decode('base64')
#
#
# ===== controller.py =====
class Root(Controllers.Root):
    @turbogears.expose()
    def getFile(self):
        image = Image.select(orderBy=Image.q.id)[0]
        cherrypy.response.headerMap['Content-Type'] = 'image/jpeg'
        return image.data

で、cherryPyで作業ディレクトリのファイルを直接見せようとしてもうまくいかない、ガッデム。っていうかドキュメントどころかTipsすらまともに見付からない、生産性悪い気がしてきたしruby on railsに乗り換えようかなぁ。ぇ、ソース読まないならOSSに手を出すなって?ごもっとも...orz。

pythonでも@やら*やら使われてきたんじゃ自分がpythonを使っている理由「特殊記号が無い」が成り立たないし、くそー、とりあえずもう少し調べよう。

_ [python] よくよく考えれば直接見えるわけないじゃん

というわけでまぁ解決、っていうかそもそもの前提が間違えていた。「http://localhost:8080/test.jpg」みたいなURLで画像に大してアクセスできないか試していたけど、これじゃ"test.jpg"ってページを見に行ってるんだから見れなくて当り前じゃないか...、何考えていたんだろう自分(泣。

というわけで、引数を渡して任意の画像を指定するメソッドを作ってそのメソッドから画像データを投げさせるようにした。文章中に画像を張り付けたいときは、imgタグのsrcでそのメソッドを指定させれば画像は表示できた。

なんだか最初から最後まで考えれば当然の事なのにやってる最中はムキになって全然ちゃんと見ようとしていなかったorz。なんていうか全く無駄な事に馬力使ってしまった。まぁこれで問題も解決したし、今度からはもっと落ち着こう。

あ、作業ディレクトリはパスを直接書き出させた結果、プロジェクトのルート、つまり***-start.pyがあるディレクトリだった。

_ [python] turbogears(cherrypy) - uploader CGIからDBへ画像を格納する

アップローダからのデータの受け取りは一つ目のリンクのコードをコピー、でImageオブジェクトを生成する際に以下のように生成した。

@turbogears.expose()
def postFile(self):
    ...
    file = dataDict['myFile']
    hub.begin()
    # heightとwidthの値は適当、参照されていないけどとりあえずつっこんでるだけ
    image = Image(data=file.value, height=100, width=100)
    hub.commit()
    hub.end()
    ...

何を渡すべきかはFieldStorageのドキュメントを読んで確認した。pythonでは他にもcgiへのアクセス方法はあるけど、CherryPyのドキュメントではFieldStorageを使うことを勧めていたのでこれに則ってコーディングする。

やっとpythonがわかってきた感じ(遅、そもそも動的に型が決まるっていうのはまだ慣れないなぁ。基本がJavaなせいかも。

_ [python] yieldキーワード

やっと意味がわかったぞyield、イテレータに使われるジェネレータを作る為に(言葉の定義正しいのかしら...)使うのね。

以下の結果、「0 2 4 6 8」と出力される。役割がわかればすっきり、確かにこの方が自然ね、わかれば。

def myRange():
    index = 0
    while (index < 5):
        yield index*2
        index+=1
if __name__ == "__main__":
    for x in myRange():
        print x,

2005-11-28 おしごとおしごと〜 [長年日記]

_ [python] debug用のメモ

オブジェクト"a"のクラス名を知りたいときは「a.__name__」

ディクショナリ"b"のキーリストが欲しいときは「b.keys()」。値のリストが欲しいときは「b.values()」

(2006.1.14追記)上記のクラス名の確認方法は間違い。詳しくはエイリアスとインスタンスでクラス名の確認の仕方が異なる

_ [anime][comic] LaLa1月号とホスト部アニメ化

LaLa1月号でアニメ化の宣伝がありました、桜蘭高校ホスト部アニメ化。脚本榎戸洋司はおぉーっと思ったけど、演出五十嵐卓哉でちょっと不安が...、ナージャの印象が強くてちょっと微妙なんよねぇ。

そういやホスト部のドラマCDのキャストがどうだったかを調べようと思ってgoogle先生に聞いたら、出てくるでてくる、IPアドレスのネットワーク部とホスト部の説明が(ぉ

ドラマCDではハルヒが久川さん、環が緑川光、ハニー先輩が大谷育江でしたがアニメではどうなることやら。

で、LaLa本誌の話、橘裕が前後編で描いてた、この人のマンガは学園モノとして安定しておもしろいのが良い、雰囲気も好きだしね。でもって来月はなんだか眼鏡祭の悪寒。


2005-11-29 25時帰宅 [長年日記]

_ [python] Nufox - Python + XUL, Python for PSP

XUL開発においてJavaScriptを書くのは最小限にしてpythonでXULアプリを書くためのライブラリがNufox、Webアプリのエディッタをこれで作ればけっこうおもしろいんじゃないかと思ってる、今の分が終わったらこれで拡張を試みる予定。

_ [python] Kid - XML based templateの日本語ドキュメントとCherryPy内のwikiでの言及

TurbogearsのHTMLテンプレートとして使われているKid、CherryPyのwikiでも書かれているけど、ZPTという記述方法が使える。さらに、これは上のリンク先にもあるけど、XMLタグの属性としてpythonのロジックを埋め込むことで、単体としてvalidなXML,HTMLドキュメントとなることができる。そのため、ロジックとデザインの切り分けが容易というメリットがある。で、ZPTっていうはZopeで使われている記述方法なのね。

あ、後上の二件は日本語で数少ないKid templeteに言及した記事(ぇ。Cheetahはそこそこ見るんやけどなぁ。

_ [python][web] People's Bureau of Media Consumption - MochiKit tutorial, CrackAJAX

CrackAJAXいいなぁ、NufoxといいこうやってJavaScriptを書く手間をどんどん省いていってくれるライブラリやツールはほんとに嬉しい。

_ [python] pythonに関するポッドキャスティングとすべての漢字を取り出す正規表現

_ [python] A Rails-like App in Python with CherryPy

Ruby on RailsとPythonのライブラリを用いたアプローチの違いを解説してるのかな、Railsとの差異を説明するのに役立ちそうな気がする。

_ [python] TRIVAL TECHNOLOGIES 2.0 - PINGサーバによるBlog判別と__slots__による検索の効率化

Blogタイプ判別による取り込み記事の選択はおもしろそうな機能だと思う。

二つ目の記事が興味深い。python 2.2から導入された__slots__のようなnew style classはパフォーマンス的に効果があるという話。この記事ではSQLObjectでの応用について触れているので、実装してみるとけっこう使えそう。