読者です 読者をやめる 読者になる 読者になる

画像ビューアを作りたい

Windowsに元から付いてるやつがわりと理想的なんだけど、メニューやボタンが微妙に場所取ってるのが気になる。GIFが動かなくなったのも不便。当然だが自分で機能を追加することもできない。よって、これに代わるものを作りたい。

関連付けに関しては以前調べて、自分でレジストリをいじって希望の動作が得られたけど、やり方を忘れたのであとで調べる。

メニューやボタンは、ないとたぶん不便なんだろうけど、とりあえずなしで。背景色は白、透過付きの画像は白の灰色のアレで。キーボードで前後の画像に移動できる。右クリックすると、エクスプローラと同様のメニューが出る。ホイールで倍率変更。左ドラッグで動かす。手のマウスポインタでと思ったら、この絵はないのか?もにょ。スクロールバーを表示させるか。面倒だなあ。とりあえず普通のマウスポインタで妥協して作るか。全画面表示も欲しいところだが後回しで。

んー、マウスだけで操作できないとさすがに不便すぎるか。画像クリックで次の画像というのは、ちょっと筋が悪い気がする。マウスジェスチャもかったるいだろうな。Web漫画みたいにする?いやあれは相当なデザイン力が要る。まあここは試しながら探っていくことにしよう。

内部的なことで、次の画像を読み込んでおく必要がある。少なくとも前後の画像は読んでおきたい。キャッシュ破棄のタイミングが悩ましい。前後以外は遠慮なく捨ててしまうか。それとも上限メモリ使用量を決めておくか。そもそも、メモリの使用量を取得する方法を知らない。これは気が向いたら調べよう。メモリの上限を定める方法の場合、もっと先までキャッシュしておくことも考えたい。ここでやはり悩ましいのが破棄の順番。遠いものから順に捨てるか。あと、JPEGのデコードはしないけどHDDからは読んでおく、みたいなアイデアもある。これは難しい。流れで決めるしかないだろう。ここは決められない。自分の力のなさを感じる。

表示倍率について。例えば縦長の画像だけど幅もウィンドウよりあるとき、ウィンドウの縦に合わせるのがいわゆる「ウィンドウに合わせる」。で、原寸表示の前に、ウィンドウの横に合わせる倍率も置きたい。ホイールの倍率変化が、その3段階プラス通常の拡大だけってのはダメかな。

基本仕様はこのくらいでいいかな。これができれば、自分で好きな機能を付ける楽しみも出てくる。

書く意味

ここに考えをかくのは、直接的には、今の自分の考えを整理したり、わかっているつもりでわかっていないことを見つけたりするため。しかし実際には、半年後の自分が今と同じ高みに上り直すための手間や敷居の高さを大幅に軽減するのが、主な効果である。

EVAL4

単位は数値リテラル、隣り合った数値リテラルは乗算記号で結ばれている扱いにする。1つの数値を検出したあと、演算子を検出しようと挑戦して、ダメだったら数値に戻る。先頭が[0-9]でないときは単位だろうとして判定する。単位でもなかったらエラー。「[」は次が単位で始まることを示す。いや、ただのカッコか?でもな、「km[4]」ってC言語じゃないんだから。まあ、ただのカッコで実装しても許されるかな。あとで、前が数値でない場合や、中身に単位でない数値があったときにエラー吐く機能を付けてもいい。

数値か演算子を格納するstd::vectorを用意する。これも美しくないなあ。別々に格納すると順番がなあ。順番を示す配列を用意するのもあれだし。問題は単項演算子。優先順位はバケットソートでいいよね。いや、分布数えか。STLでできればそれでいいけど。あかり新しいSTL大好き。

たとえば「-3**2」は優先順位に従って「**」が先に実行され-9になるけど、「3**-2」は「-」が先。これは、**の右側が数値でなかったからだろう。必ず単項演算子だよね。その単項演算子に、お前いますぐやれと言う。単項演算子の相手がまた単項演算子なら同様に。で、これですべての単項演算子が解決されるわけではない。ちゃんと優先順位に従ったのもやる。それでいいか。んー、「3**-2」みたいなのは、カッコのにおいがする。内部で「3**(-2)」としたい。しかし閉じカッコないからダメか。これは**の優先順位も絡むから単純には判定できない。

これでいけるか。いやあ、数値と演算子の管理がダメでしょ。具体的に決めないと。ていうか「この一手」というのが見えない限り決めるなんて無理なんだよ。これは少し寝かせよう。今日はここまで。

EVAL3

まあ続きやりましょうか。1週間に10分しかプログラミングする時間ないの?と言われてしまいそうだが、仮にそうだとすると30年で260時間か。限られたものしか作れないけど、極端に少ないわけでもない。あ、コーディングと言ったほうがよかったか。紙のノートに向かって考える時間はもう少しある。まあそれはいいよ。

カッコについては別のやり方にした。まず、前処理として、式全体をカッコで囲んでおく。「(」を見つけたら再帰呼び出し、「)」を見つけたら式の終端とする。関数の戻り値としては、処理した文字数を返す(エラーなら負の数を返す)。これで、O(n)で行ける?本当かな。自信がない。オーダーが変わるほどの工夫をした覚えがないから不安になる。これで行けるなら、以前の方法でも工夫すれば同等の速度が出せるはず。あー、カッコの深さだけスタックを消費するのがポイントかな。

さて、演算子の検出が必要だ。二項演算子だけではなく、単項演算子もあるというのが厄介。とりあえず、現在の(文字列への)ポインタが演算子で始まっているかどうかを判定。長い演算子からチェックしていく。ここの高速化は、(必要ではないだろうけど)後からでも簡単にできると思うので、とりあえずはバグが出ないことを最優先に書いていい。演算子でなかったら、スペース(の役割をする文字)か数値リテラルということになる。

数値リテラルのデコードが、また嫌らしい。小数点と指数と16進数が必要。まあこれは順次処理していけばいいか。あと、単位(kmとかアンペアとか)も使えるようにしたい。単位を、演算子扱いにするか、数のリテラルに含めるか、新に単位というものを考えるか。これがまた迷う。単位を[km]のように囲うことは許可したい(強制はしたくない)。仮に演算子としたら、優先順位は最高レベルだよね。「4km/h」で、kmとhを別々に持って「/」を通常の演算子とするか、あるいは「km/h」を予め登録しておかなければ使えないようにするか。むずっ。

数値(単位を除く)の検出が終わったときに、演算子でないなら単位とみなす?そもそも、数値のない単位(4*kmとか)は認めるべき?関係ないけど「exp(log(4km))」は計算できたほうがいいだろうか。ねむい。不本意ながら続く。