2015年8月4日火曜日

GDCM 覚書

GDCM (Grassroots DICOM) memo memo

c#用wrapperの gdcmの覚書。

gdcm-2.4.4 の作成には cmakeはver2.8.9(cmake-2.8.9-win32-x86.zip), swigはver2.0.12(swigwin-2.0.12.zip)を使用しました。 swin3.0以降は不可のようです。
swigwinは実行ファイルのある場所にpathを切っておきます。

1. MONOCHROME2, シングルフレームのbitmap画像

            
//MONOCHROME2,シングルフレーム Dicom Image
var sw = new System.Diagnostics.Stopwatch(); 
sw.Start();
string fileName = @"chest.dcm";
// 
var ir = new ImageReader();
ir.SetFileName(fileName);
if (!ir.Read()){
    Console.WriteLine("Err: ImageReader "); 
    return;
}
gdcm.File file = ir.GetFile();          
gdcm.DataSet ds = file.GetDataSet();        //DataSetの取得
gdcm.Image image = ir.GetImage();           //Imageの取得
byte[] imgBuf = new byte[(int)image.GetBufferLength()];
image.GetBuffer(imgBuf);                    //Image bufferの取得
uint dims = image.GetNumberOfDimensions();  //ここではマルチフレームは未対応とする
if (dims == 3) { 
    Console.WriteLine("Err: マルチフレーム未対応"); return;
}
//
if (image.GetPhotometricInterpretation().GetType() == gdcm.PhotometricInterpretation.PIType.RGB) { 
    Console.WriteLine("Err: PhotometricInterpretation is RGB"); return;
}
if (image.GetPhotometricInterpretation().GetType() != gdcm.PhotometricInterpretation.PIType.MONOCHROME2)  {
    Console.WriteLine("Err: PhotometricInterpretation is not MONOCHROME2"); return;
}
//8bpp用のpaletteを作成しておく
var b = new System.Drawing.Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
var GrayscalePalette = b.Palette;
for (int i = 0; i < 256; i++)
    GrayscalePalette.Entries[i] = System.Drawing.Color.FromArgb(i, i, i);
//bitmapの作成とpaletteを設定
//
int wc,ww;
if (!ds.FindDataElement(new gdcm.Tag(0x00281050))){
    Console.WriteLine("Err: Window Center値がありません"); return;
}
if (!ds.FindDataElement(new gdcm.Tag(0x00281051))){
    Console.WriteLine("Err: Window Width値がありません"); return;
 }
if (ds.FindDataElement(new gdcm.Tag(0x00281052))){
    Console.WriteLine("Err: RescaleInterception未サポート"); return;
}
wc = Convert.ToInt32(Convert.ToDouble(ds.GetDataElement(new gdcm.Tag(0x00281050)).GetValue().toString()));
ww = Convert.ToInt32(Convert.ToDouble(ds.GetDataElement(new gdcm.Tag(0x00281051)).GetValue().toString()));
int max, min = 0;
double invww = 0d;
max = wc + (int)((double)ww * 0.5d);
min = wc - (int)((double)ww * 0.5d);
ushort max1 = (ushort)max;
ushort min1 = (ushort)min;
invww = 255.0d / (double)ww;
//MONOCHROME2 image
var bitmap = new System.Drawing.Bitmap((int)image.GetColumns(), (int)image.GetRows(), System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
bitmap.Palette = GrayscalePalette;
var bmpData = bitmap.LockBits(new Rectangle(0, 0, (int)image.GetColumns(), (int)image.GetRows()), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
int padding = bmpData.Stride - bmpData.Width;
unsafe
{
    fixed (byte* pBuf = imgBuf)
    {
        byte* pBmpData = (byte*)bmpData.Scan0;
        //PixelRepresentation(0x00280103)=1の場合
    //short* ptr = (short*)pBuf;
        //PixelRepresentation=なし,あるいは0の場合
        ushort* ptr = (ushort*)pBuf;
        int stride = bmpData.Stride;
        int pixel;
        for (int y = 0; y < bmpData.Height; y++)
        {
            for (int x = 0; x < bmpData.Width; x++)
            {
                int xy = *ptr++;
                pixel = xy  = min ? 0 : (xy >= max ? 255 : (int)((xy - min) * invww));  //16bit image to 8bit image
                //MONOCROME1 背景白
                //pixel = xy = min ? 255 : (xy = max ? 0 : 255 - (int)((xy - min) * invWW));  
                *pBmpData = (byte)pixel;
                pBmpData++;
            }
            pBmpData += padding;
        }
            bitmap.UnlockBits(bmpData);
    }
}
if (bitmap != null)
    pictureBox1.Image = bitmap;
sw.Stop(); 
Console.WriteLine(sw.ElapsedMilliseconds +" msec");

2. MONOCHROME2, マルチフレームの場合は次のようになります

uint k = image.GetNumberOfDimensions();
uint frames = 0;
if(k==3)
    frames = image.GetDimension(2);
var bitmaps = new System.Drawing.Bitmap[(int)frames];
unsafe
{
    fixed (byte* src = imgBuf)
    {
        for (uint i = 0; i < frames; i++)
        {
            var bitmap = new System.Drawing.Bitmap((int)image.GetColumns(), (int)image.GetRows(), System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
            bitmap.Palette = GrayscalePalette;
            var bmpData = bitmap.LockBits(new Rectangle(0, 0, (int)image.GetColumns(), (int)image.GetRows()), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
            int padding = bmpData.Stride - bmpData.Width;
            byte* pBmpData = (byte*)bmpData.Scan0;
            ushort* ptr = (ushort*)src;
            int stride = bmpData.Stride;
            int pixel;
            for (int y = 0; y < bmpData.Height; y++)
            {
                for (int x = 0; x < bmpData.Width; x++)
                {
                    int xy = *ptr++;
                    pixel = xy <= min ? 0 : (xy >= max ? 255 : (int)((xy - min) * invww));
                    *pBmpData = (byte)pixel;
                    pBmpData++;
                }
                pBmpData += padding;
            }
            bitmap.UnlockBits(bmpData);
            bitmaps[i] = bitmap;
       }
    }
}

0 件のコメント :

コメントを投稿