以前、win32 を使用していたときは、ビット深度が 8 ビットを超えるビットマップを読み込んで保存するためにFreeImageを使用していました。私は医用画像処理を行っているので、これが私が扱うすべての画像です。誰かが何かを言う前に、私と私の顧客は、11 ビットまたは 12 ビットのダイナミック レンジを備えた高輝度、高コントラストのモニターに多額の費用を費やしてきました。 . 実際、興味がある方のために説明すると、マンモグラフィを実行するための ACR の要件には、少なくとも 10 ビットのダイナミック レンジを備えたモニターが含まれています。
メモリのオーバーヘッドと、すべての開発を 1 つのプラットフォームとコンパイル モードで行うために、x64 に切り替えました。私は win32 に戻りたくありません。私の顧客は私と一緒にいます (実際に変更を強制しています)。FreeImage は 64 ビット Windows ではコンパイルできません。コンパイラが処理できないコードに _asm ディレクティブがあります。
Microsoft クラスでネイティブ .NET サポートを試してみようと思いました。簡単に言うと、それらは機能せず、非常に限られたエラー メッセージで失敗します。Microsoft がまだ Format16bppGrayScale クラスをサポートしていないためだと思います。
私のコードに問題があるのかもしれません。書くための私のコードは次のとおりです。
Bitmap theBitmap = new Bitmap(inImage.XSize, inImage.YSize, PixelFormat.Format16bppGrayScale);
//have to go with lockbits
Rectangle rect = new Rectangle(0, 0, theBitmap.Width, theBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData =
theBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
PixelFormat.Format16bppGrayScale);
IntPtr ptr = bmpData.Scan0;
int theByteSize = theBitmap.Width * theBitmap.Height *2;
byte[] theByteBuffer = new byte[theByteSize];
System.Buffer.BlockCopy(inImage.Data, 0, theByteBuffer, 0, theByteSize);
System.Runtime.InteropServices.Marshal.Copy(theByteBuffer, 0, ptr, theByteSize);
theBitmap.UnlockBits(bmpData);
theBitmap.Save(inDirectory + "\\" + inName);
theBitmap.Dispose();
このコードは、プログラムをクラッシュさせます
An unhandled exception of type
'System.Runtime.InteropServices.ExternalException' occurred in
System.Drawing.dll
Additional information: A generic error occurred in GDI+.
特に、この画像をこのように画面に描画したくないので (それはいいことですが!)、保存/読み込み機能を使用したいだけなので、興味深いです。イメージは (プログラムがクラッシュしても) ディスクに書き込まれ、次の読み取りコードもプログラムをクラッシュさせます。
Bitmap theBitmap = new Bitmap(theCompleteName, false);
ushort[] theData = new ushort[theBitmap.Width * theBitmap.Height];
int x, y;
switch (theBitmap.PixelFormat)
{
case PixelFormat.Format16bppGrayScale:
//have to go with lockbits
{
Rectangle rect = new Rectangle(0, 0, theBitmap.Width, theBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData =
theBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly,
PixelFormat.Format16bppGrayScale);
IntPtr ptr = bmpData.Scan0;//scanline approach left over from FreeImage
for (y = 0; y < theBitmap.Height; ++y){
byte[] scanline = new byte[theBitmap.Width*2];
System.Runtime.InteropServices.Marshal.Copy(ptr, scanline, y * theBitmap.Width * 2, theBitmap.Width * 2);
System.Buffer.BlockCopy(scanline, 0, theData, y * theBitmap.Width * 2, theBitmap.Width * 2);
}
theBitmap.UnlockBits(bmpData);
}
break;
//for colors, just take the red and call it a day
case PixelFormat.Format24bppRgb:
case PixelFormat.Format32bppArgb://really stupid reading code, always works
for (y = 0; y < theBitmap.Height; ++y) {
for (x = 0; x < theBitmap.Width; ++x) {
theData[y * theBitmap.Width + x] = (byte)(theBitmap.GetPixel(x, y).R);
}
}
break;
}
theNewImage = new ImageContainer(theData, theBitmap.Width, theBitmap.Height, inName, inAssessmentID);
theBitmap.Dispose();//not needed, anymore
このコードは、次のエラーでプログラムをクラッシュさせます。
An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
Additional information: Parameter is not valid.
これらの結果は、Microsoft がまだ PixelFormat 列挙の Format16bppGrayScale 部分を修正していないことを示しています。残念です。
では、.NET を使用して x64 で 16 ビット グレースケール イメージを読み込んで保存するには、何を使用すればよいでしょうか?
(編集: DICOM 画像を保存することはできますが、患者以外のデータで実験を実行して、アルゴリズムが健全であることなどを確認する必要があることを付け加えておきます。DICOM には、一連の UID とその他の必要なフィールドが必要です。私が必要としているのは、現時点では患者のデータではなく、画像だけです)。