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

MB-SystemのMBIOの構造

お久しぶりです。

研究関連でMB-Systemのソースコードをよんで修正する機会がありましたので、その時にキーワードとなったMBIOのしくみについてまとめます。

はじめに

MB-Systemとは「MB-System is an open source software package for the processing and display of bathymetry and backscatter imagery data derived from multibeam, interferometry, and sidescan sonars. This software is distributed freely (and for free) in the form of source code for Unix platforms. 」で要するに海底地形データの処理に使用するソフトウェアです。ということでかなりマニアックな領域、情報系とはおよそ関係ない領域のことなので書いてもあんまりじゅようないかなーと思いつつ、私自身どこかにまとめとかないと忘れそうなのでまとめておきます。

MBIOとは

一口に測深データといってもベンダ・機関・機器・versionによって使用しているフォーマットが大きくことなります。 そこでMB-Systemでは測深データを読み込んだ後MB-System独自のデータ形式に変換し統一的に扱えるようにしています。 そのデータ形式(構造体)と操作(関数)を提供するのがMBIOです。ライブラリ化されているので外部からも使えます。 MBIOを使うことで元のデータ形式に依存しない操作ができるようになるわけです。 もちろん各フォーマットへのエクスポートもサポートしています。

MBIOに新フォーマットを対応させる際の作法

今回わたしがやったのは修正ですので、新フォーマットに対応させるということはしていませんが、 調べる途中でだいたい見えてきたのでかいておきます。もしかしたら抜けがあるかもしれません。

src/mbio/配下にmbr.cというファイルを作り(は任意。フォーマット名にするといいかもしれません)、 対応させたいフォーマットからMBIOに変換するための関数を実装します。慣習的に下記のようにmbr_register*という名前になっているようです。

int mbr_register_*(int verbose, void *mbio_ptr,
                int *error);

ここでverboseは出力のレベル、mbio_ptrはMBIOの構造体へのディスクリプタerrorはエラーが起こった時の書き込み先のポインタが渡されます。 基本的にmbio_ptrに、がしがしデータとそれらを扱う関数をセットしていけばおkです。 他のフォーマットの実装を参考にしつつ実装すると楽かと思います。 また、実装しない関数はNULLを入れておくのが作法なようです(ある関数が使えるかどうかの判定が多くの場合NULLかどうかでされている)

つぎにmb_format.hを編集してフォーマットIDを割り当てます。 1000番台の値を割り当てとけばまず、衝突することはないでしょう。 mb_format.hに追記します。

#define MBF_* ID

これと先ほど作成したbr_register_*を紐付ける処理を書きます。 mb_format.cのmb_format_register関数の中に下記のようなelse ifの羅列があるので、そこに追記しましょう。

        else if (*format == MBF_*)
                {
                status = mbr_register_*(verbose, mbio_ptr, error);
                }

また同じくmb_format.cにmb_get_format関数というフォーマットを取得し返す関数があります。 これに新しく追加したフォーマットの判別処理を書きましょう。 例えば独自フォーマットの拡張子が.fooとすると下記のようになります。

        if (found == MB_NO)
            {
            if (strlen(filename) >= 5)
                i = strlen(filename) - 4;
            else
                i = 0;
            if ((suffix = strstr(&filename[i],".foo")) != NULL)
                suffix_len = 4;
            else if ((suffix = strstr(&filename[i],".FOO")) != NULL)
                suffix_len = 4;
            else
                suffix_len = 0;
            if (suffix_len == 4)
                {
                if (fileroot != NULL)
                    {
                    strncpy(fileroot, filename, strlen(filename)-suffix_len);
                    fileroot[strlen(filename)-suffix_len] = '\0';
                    }
                *format = MBF_*;
                found = MB_YES;
                }
            }

基本的に

            if ((suffix = strstr(&filename[i],".foo")) != NULL)

            else if ((suffix = strstr(&filename[i],".FOO")) != NULL)

                *format = MBF_*;

の部分を書き換えればよさ気な雰囲気です(基本的に拡張子しかみてないんですね...

以上をするとフォーマットを自動判別して適切な変換関数を呼び出しあとはよしなに扱ってくれます。