まだ道は遠い

ようやく絵が出せるようになった DICOM-XA Viewerですが まだまだバグがありそうです
片っ端から、XA fileを開き、またコマを変えたりして見ているのですが 既にこんな異常が見つかりました
次に掲げてあるのが 001013XAというシーンの XA fileです このシーンは短く5コマしかありませんが、その中の 3コマ目、4コマ目、5コマ目を並べると以下のようになったのですが、これはあくまでも僕の Viewerのバグです 問題はバグがどこにあるのか現時点では皆目見当がつかない、ということです それに どうやってバグ潰しをすればいいのか? それも見当がつかないということです
いやもっと大きな問題は自由に思索する時間が無い、ということです 仕事に追われています
frame3
frame4
frame5

深刻な問題

本日深刻な問題を知りました 僕は Macbook-Proを使い、OSX10.8の上に、Parallels Desktopを用いて Windows7を走らせ、普段はその Windows7上で仕事やプログラムを書いています
CD/DVD読み込みの設定が、OSX優先となっていたため、DICOM-CD/DVDを挿入すると、自動的に OSX上の Osirixが立ち上がりファイルを読み込み、Windows7側では読み込めなかったのです
そこで、そうやって OSX上に読み込まれた DICOM-XA fileを Desktopにコピーしました Desktopに関しては両方のOSから普通に読み書きできるからです また読み込んだファイルは XAですから binary dataということになりますので、当然ながら Windows7上の binary editorでも読み込める筈です
ところがところが VisualStudio 2010内臓のbinary editorで開きに行くと開けないのです!!! Binary editorで開けないファイルがこの世に存在するなんて信じられません
ひっょとして、と思い、Google博士に聞いてみました そして、Parallelsを用いても Windows側で CD/DVDを読み込む方法を見つけました、そして Windows側でCD/DVDを開いてファイルを Desktopにコピーしたのです そうするとなんとなんと 今度は普通に Binary Editorで読み込めるのです
これってどういうこと? 同じDesktopに書き込んでいるのですから、少なくとも物理的ファイル・フォーマットの違いの問題ではありません なんかファイル・ヘッダーが違う関係で読み込めないのかなあ?
それぞれのOSの Binary Editorで開いてみて比較すればわかるのでしょうが・・・
こんなに深刻な問題につきあたるなんて想像していませんでした 

実際問題として一度 CD/DVDから Osirixに読み込んでしまえば、それをDICOM-XAで書きだしたとしても、本当に Windows上の DICOM Viewerで読めるのかどうか という深刻な問題を投げかけています 誰か試してみないですか?

成田到着

長ーい長ーい飛行の末に成田に到着しました 長かったです しかもこの間 あまり睡眠とっていません 例の DICOM-XA画像化に興奮し、プログラムばかりしていました やはり日本は暑いですねえ 極寒のサンパウロとはものすごく違います
これから夢は DICOM-XAの動画表示 あるいはインターフェースの実装 あるいはOSXへの移植 色々と課題があります とても楽しみですね

ついに絵が出た

ついについに DICOM-XAの一フレームを画像として出すことができました これまでの少なくとも 2006年から取り掛かってきた自分自身のプロジェクトがようやく実体化しつつあります
「DICOM-XAの Viewerを作ろう」と思い立ったのは、色々な理由がありました

  1. 我々からすれば謎の多い DICOM-XAを我々でも理解できるようにしたい そのためには自分自身でプログラムを書いて、てぎれば皆が理解し易いスクリプトで書き換え、それを公開したい
  2. 自分自身のC++の勉強のための題材としたい
  3. 自分自身何年かがかりの目標を持ちたい
  4. 自らの頭脳の限界に挑戦したい

こんなところでしょうか

それでも何回も何回も挫折したのです 色々な方々にご教授をお願いしました DICOM-XA Viewerを開発しておられるメーカーの方々にも質問を投げかけました しかし、何時も答えは曖昧なものでした そりゃあ彼らも必死で開発し、その心臓部のアルゴリズムは秘密にしたいと思います 仕方ありません

そんな中で ひょんなことで芝浦工業大学の先生方と知り合いとなり、T先生に核心的なヘルプを頂きました 流石に画像処理のプロ、僕が何年もかかっても解決できなかったことが、数日で解決しました でもただ言われるままにしているのではありません 自分で理解し、確認しながらの作業でした そして、サンパウロからドバイへの14時間の飛行機の中でついに絵が出ました 感激の瞬間でした これまでの少なくとも7年間に及ぶ苦労がやっと報われつつあるのです

でも、今後はパラパラ漫画にするために、タイマー割り込みをかけたり、動画とするためには色々な作業があります それがまた楽しみです さらには OSXにも移植したいと思います そして、それらの作業の中で理解を確実なものとして それを そうですねえ Visual Basicか、PHPあたりのスクリプト言語で書き直し、もちろんスピードの点で使い物にはならないでしょうが 公開したいと思います それではできた絵をここで初めて公開します

はじめて画像化できた DICOM-XAのフレーム
はじめて画像化できた DICOM-XAのフレーム

新しいサンパウロ

サンパウロには 1999年の訪問してからもうかれこれ 10回近く訪問しています しかし、今回のサンパウロはこれまでと一味違いました
まずは 酷寒 これには驚きました これまで何時来ても短パンが似合う気候だったのです 本当に驚きました
そして、この一年で急速にレベルの高い和食の店が何店もオープンしていることです これも最近のパリ同様に新鮮でした パリの和食レベルはここ数年で無茶苦茶進化していますが、それに負けないぐらいの進化です
特に、昨年春からの公正競争規約強化を受け、やはり日本のお店は影響を受けているのでしょうか 若い板前さんの中でやる気のある人たちが一念発起して単身サンパウロに渡り、素晴らしい和食の店を開店させているのです
僕が今回訪れたのは 
酒蔵「阿吽」 あうんと呼びます ただ、アルファベット表記は SAKAGURA Al です ここには何と 札幌ススキノにある寿司の名店「さい藤」で 2012/09月まで板前さんをされていた坂本さん、という方が10月から単身渡ってきてここに雇われて素晴らしい仕事をされていました
そして、今朝のライブの後驚いたのは「勘」という開店して丁度一か月のお寿司屋さんです カウンターも8席くらいしかない小さな店ですが、未だ一か月にもかかわらず既に予約がとりにくい状況です ここの板さんも、それまで東京の「勘」で働いていて一念発起し単身サンパウロに渡り、昔からある名店寿司「勇」で一年間働いた後 開店したのです いや素晴らしかったです

本日のライブ

極寒のサンパウロ 毎日凍えそうに過ごしています 何しろ 50年来で初めての寒さ、ということですので、街全体が寒さに対して何の対策も無いのです ホテルの部屋も寒く、暖房がありません レストランに行っても寒く暖房がありません 唯一暖をとれるのが、防弾車の中です 防弾ガラスと防弾ドアで保護された HONDAアコードの中は思い切り暖房をかけて暖かいのです
そんな寒さの中 今朝は 2:00AMに時差ボケで覚醒 フラフラになりながらもその後まったく睡眠できず 仕方ないので 朝までだらだら時間を過ごしていました
6:00AMにホテルを出発し 今回のライブを飛ばす BENEFICENCIA PORTUGUESA DE SAO PAULO (ポルトガル慈善サンパウロ病院)という多分 済生会病院のような感じの病院に行きました この病院にはかつてあの Dr. ARIEが1997年までおられ、ブラジルの心カテを立ち上げられ、その後PCIも始められ数多くのブラジルの医師を教えられた有名な病院です
サンパウロには、もう一つ有名な病院があり それが言わずと知れた DANTE PAZANNEESSE (ダンチ・パツァネーゼ病院)です ここはサンパウロ市立病院ですが、数多くの薬剤溶出性ステントの First-in-Man試験で有名な病院ですね あの CYPHERが初めて植え込まれたのもこの病院であり、そこを率いているのが SAUSA先生と Abizaid先生です 今回は何時も訪れているこのダンチは行きませんでした
ポルトガル慈善病院はサンパウロ最大の超巨大病院であり、昨年改築をしてすっかり綺麗になっていました 実は昨年もここからライブを飛ばしたのです カテ室は何室でしょうか? 多分7部屋ぐらいありそうです 全て Philipsのフラットパネルでした 症例数もサンパウロ断トツの症例数だそうです
6:30AMに病院に到着し、症例のシネを見せて頂きました 症例は 74歳男性であり 左冠動脈前下行枝近位部の慢性完全閉塞、既に左冠動脈回旋枝と右冠動脈にはステントが一年前に入っており、今年の三月にこの慢性完全閉塞に対してトライされましたが不成功でした 中隔枝からの副血行は無く、右室枝から非常に蛇行した心外膜枝を通じて左冠動脈前下行枝心尖部につながり、また#4PD末梢から蛇行した心外膜枝を通じて対角枝に副血行が行っていました
8:30AMからのライブ放映開始に備えて 8:00AMから開始しました 両側大腿動脈より 7Fr sheathsを挿入し、開始しました 到底順行性は不可能に見えましたので、最初から逆行性に開始 ものすごく大変でしたが Corsai + Sion-Blue -> Fielder-FC -> XTRを用いて蛇行屈曲した対角枝への副血行をクロスしました そして、Miracle 3により左冠動脈前下行枝近位部にクロスし、うまいこと順行性ガイドカテの中に入れることができました
ここからが大変でした 順行性ガイドカテの中でアンカーをかけても Corsairが全く通過しません Finecrossに交換してもダメです このため順行性にこのガイドワイヤーを目印に何とかガイドワイヤーをクロスし、ようやく 1.25mm balloonで拡張しましたしかし左冠動脈前下行枝が良く映ってこないのです 仕方なく対角枝向きに 2.5mm balloonで拡張し、ようやく左冠動脈前下行枝が順行性に出てきました しかし、対角枝分岐直後に再び慢性完全閉塞に近い病変があったのです そこも苦労してクロスしたのですが、今度はバルーンが通過できません ようやく5Fr 子カテを用いてクロスに成功し、DES 2.75mm, 2.5mmを植え込んで成功裏に終了しました
合計時間2.5時間の奮闘でした 本当に病変が固く、本当は IVUSとか Rotablator使いたかったのですが、それらは隣の部屋にあり、次のライブのために動かせなかったのです 辛かったです

これからサンパウロ

今 羽田空港国際線ラウンジで 7/24 01:30AM発の EMIRATES航空 Dubai行きを待っています 既に日にちが変わりました

Dubaiで同じ Emirates航空に乗り継いで Sao Pauloに向かうのです このルートが日本とサンパウロを結ぶ最短のルートとなりますが 初めて使います

現地には2泊滞在し、 SOLACIという学会に参加し、色々な役割を終え、日曜日 7/28の夕方には成田空港に帰国することになっています。地球の裏側への往復としては最短の旅程でしょうね

この間、 DICOM-XA Viewerプログラムに大きな進展がありました。いくら考えても自分一人では解決できないので、ついに以前コンタクトさせて頂いたその道のプロの方に相談したのです そして、見事に僕の書いたプログラムの中に幾つかのバグを指摘して頂き、その方はきちんとした画像の生成に成功されたのです

頂いたヒントをこの旅行の往復の飛行機の中で解析し、自分のプログラムをきちんとしたものにするつもりです ようやく大きな目標に近づいてきたのです とてもうれしく思います

やったあ ついにやったあ

月曜日から水曜日にかけてフランスに出かけ、経大動脈的大動脈弁植え込み術の実践トレーニングを受けてきました その怖さと素晴らしさの両極端を実際に体で体験してきました。濃密な素晴らしい体験でした

その合間を縫って、約一年ぶりに DICOM-XA viewerの作成に取り掛かりました とりかかる、と言ってもまずは一年前に仕上げたコードを再確認する作業です 何しろすっかり自分が何を考え、何をしてきたか それらを忘れていたからです 今回は、超強力な援軍がいて下さるのです 画像処理プログラミングのプロです その先生は全てご存じです しかし、先生からコードを頂く訳にはいきません それでは自分で理解できないからです

その一方で深刻な問題につきあたりました 僕自身 Windows上では画面に画像を出力することはできるようになっています これには、実は MFC (Microsoft Foundation Class)という C++のフレームワークを用いてプログラム書いています このフレームワークでは画面出力に Device Context (DC)という概念を用い、そこに書き込むことにより、画面に出力され、またマウス操作なども受け付けるのです これは非常に便利なのです、しかし、では Mac OSXあるいは Linuxに移行する時には問題です そんなフレームワークは無いからです

それで、どうやって OSX上で画像を作るか? それに悩みました 色々と調べ、どうやら X-window上の OpenGLというフレームワーク、さらにそれを使いやすくした GLUTというフレームワークを用いれば僕のようなアマでも何とかなる可能性があることが分かりました

そして、このページを参考にしました このページの通りにやったところ、Mac上にこのような画面が出力されたのです 感激です 超感激です

mac

自分の人生を賭けた戦い

再び自分の人生を賭けた戦いに挑み始めました

去年も挑戦し、挫折したものです それは人生の最近何年も賭けているものです DICOM-XA Viewerプログラミングです

去年は随分といい線まで行ったのです、懸案の Huffman Decodingが作動し始めたのです、しかし、実際に画像を作成しても絵にならなかったのです それで挫折

しかし、今再びその戦いの場に復帰しました これが人生で最後のチャンスかも知れません

そこで、以前のプログラムを出してきました いったいいつからこれをやっているのか? 驚きました何と少なくとも 2006年ベオグラードの時差ボケの中で書いたものがありました

それを掲載します

#ifndef __DIB32_H_
#define __DIB32_H_

// Dib32.h
// This is a DIB class.
// Written by S. Saito on April 14, 2006 in Belgrade.
// This header file actually contains the source code itself also.
// This DIB class must be created in the Constructor of the Document Class.
// Also, it must be deleted in the Destructor of the Document Class.
// A small bug was fixed on September 7th, 2012 (private members were not initialized).
//

class CDib32	//32 bits DIBクラス
{
private:
	LPBYTE lpDIB;			// DIB全体へのPointer
	LPDWORD lpPixel;		// 画像PixelへのPointer
	LPBITMAPINFO lpbiInfo;
	int sizex, sizey;		// 画像Pixelのサイズ
public:
	inline CDib32(void) // Default Constructor
		:lpDIB(NULL), lpPixel(NULL), lpbiInfo(NULL), sizex(0), sizey(0){			
		Resize(0, 0);
	}

	inline CDib32(int x, int y) {
		Resize (x, y);
	}

	inline BOOL SetDib32(int x, int y, COLORREF c) {	// Set Pixel color
		if ((x<0)|(x>sizex)) return FALSE;
		if ((y<0)|(y>sizey)) return FALSE;
		lpPixel[x + y*sizex] = c;
		return TRUE;
	}

	inline BOOL SetDib32Clip(int x, int y, COLORREF c) {	// Set Pixel with already clipping
		lpPixel[x + y*sizex] = c;
		return TRUE;
	}

	inline COLORREF GetDib32(int x, int y) {	// Get Pixel color
		COLORREF c;
		if (x<0) x = 0; if (y<0) y = 0;
		if (x>sizex) x = sizex; if (y>sizey) y = sizey;
		c = lpPixel[x + y*sizex];
		return c;
	}

	inline COLORREF GetDib32Clip(int x, int y) {	// Get Pixel color with already clipping
		return lpPixel[x + y*sizex];
	}

	inline void Dib32Draw(CDC *pDC) {			// Draw to DC
		Dib32Draw(pDC, 0, 0);
	}

	inline void Dib32Draw(CDC *pDC, int x, int y) {	// Draw to DC with offset of (x, y)
		Dib32Draw(pDC, x, y, 1.0);
	}

	inline void Dib32Draw(CDC *pDC, int x, int y, float ratio) {	// Draw to DC with offset of (x, y) 
															// with the enlargement by r times.
		HDC hdc = pDC->GetSafeHdc();
		StretchDIBits(hdc, x, y, static_cast<int>(sizex*ratio), static_cast<int>(sizey*ratio), 
			0, 0, sizex, sizey, lpPixel, lpbiInfo, DIB_RGB_COLORS, SRCCOPY);
	}

	inline void Dib32DrawR(CDC *pDC, int x, int y, float ratio) {	// Draw to DC with reversed image
		HDC hdc = pDC->GetSafeHdc();
		StretchDIBits(hdc, x, y, static_cast<int>(sizex*ratio), static_cast<int>(sizey*ratio), 
			0, 0, sizex, sizey, lpPixel, lpbiInfo, DIB_RGB_COLORS, SRCINVERT);
	}

	inline void Resize(int x, int y) {			// Resize DIB and actually substantiate DIB
		sizex = x; sizey = y;
		if (lpDIB != NULL) {
			HeapFree(GetProcessHeap(), 0, lpDIB);
		} 
		lpDIB = static_cast<LPBYTE>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFO) + x*y*4));
		lpbiInfo = reinterpret_cast<LPBITMAPINFO>(lpDIB);
		lpPixel = reinterpret_cast<LPDWORD>(lpDIB + sizeof(BITMAPINFO));

		lpbiInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
		lpbiInfo->bmiHeader.biWidth = x;
		lpbiInfo->bmiHeader.biHeight = -y;
		lpbiInfo->bmiHeader.biPlanes = 1;
		lpbiInfo->bmiHeader.biBitCount = 32;
		lpbiInfo->bmiHeader.biCompression = BI_RGB;
	}

	inline LPDWORD GetPixelTop(void) {			// get pointer to lpPixel
		return lpPixel;
	}

public:
	~CDib32(void) {
		HeapFree(GetProcessHeap(), 0, lpDIB);
	}
};

#endif