ラベル c# の投稿を表示しています。 すべての投稿を表示
ラベル c# の投稿を表示しています。 すべての投稿を表示

2017年2月19日日曜日

C#で直接印刷

C#で直接印刷

C#の直接印刷で手こずっていましたが、ghostscript.net で解決。

つかうもの。itextsharp, ghostscript.net そして、Adobe Illustrator cs2です。
itextsharp,ghostscript.net はそれぞれ NuGet にあるのでインストールしておきます。

1 Illustratorでテンプレートを作成


Adobe Illustratorで下地となるテンプレートを作成。
単位、座標をitextsharpと一致させます。
単位:ポイント
座標:左下 (「定規」を表示して左下に座標設定)
    Illustratorなのでかなり意匠の凝った印刷物が作成可。
    レイヤーでプログラムに使う座標なども作成しておくと便利。
最後に不必要なレイヤーを非表示にして「複製を保存」でpdfファイルを作成。

2 itextsharp


作成されたpdfファイルにコンテンツを追加していきます。
文字もグリッド用の線もすべて PdfContentByte で位置固定。

サンプル

using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

{

string filePaht="";
var template1 = new PdfReader(filePath);
var doc = new Document(PageSize.A4.Rotate());
FileStream fs = null;
fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
var writer = PdfWriter.GetInstance(doc, fs);
doc.Open();

//row.Count枚数の印刷物
foreach(DataRow row in table)

{
var page1 = writer.GetImportedPage(template1, 1);
doc.NewPage();
var pcd1 = writer.DirectContent;
pcd1.AddTemplate(page1, 0, 0);
AddContents(writer, row);
}
doc.Close();
fs.Close();
template1.Close();
}

//DataRowのコンテンツを追加します

private void AddContents(PdfWriter writer, DataRow row)
{
var cb = writer.DirectContent;
var bf = BaseFont.CreateFont(@"c:\windows\fonts\msgothic.ttc,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//
float x0=***f,y0=***f;
float w0=***f,h0=***f;
DrawTextAligned(cb, bf, 11f, row.Field<string>(1), new PointF(x0, y0), Element.ALIGN_LEFT);
//
DrawTextCell(cb, bf, 10f, r1[2].ToString(), new PointF(x0,y0), new SizeF(w0, h0), Element.ALIGN_LEFT);
//直線
DrawLine(cb, new PointF(x0, y0), new SizeF(w0, 0.0f), 0.5f, Color.Black.ToArgb());
}
//文字列一行
private static void DrawTextAligned(PdfContentByte cb, BaseFont bf, float fSize, string s, PointF xy, int alignment = Element.ALIGN_LEFT, int argb = -16777216)
{
if (s == "") return;
cb.BeginText();
BaseColor bc = new BaseColor(argb);
cb.SetColorFill(bc);
cb.SetFontAndSize(bf, fSize);
cb.ShowTextAligned(alignment, s, xy.X, xy.Y,0.0f);
cb.EndText();
}

//文字列 複数行
private static void DrawTextCell(PdfContentByte cb, BaseFont bf, float fontSize, string s, PointF xy, SizeF wh, int alignment = Element.ALIGN_LEFT,int arb=-16777216)
{
ColumnText col = new ColumnText(cb);
var font = new iTextSharp.text.Font(bf, fontSize);
Color color = Color.FromArgb(argb);
font.SetColor(color.R, color.G, color.B);
col.SetSimpleColumn(new Phrase(s, font), xy.X, xy.Y, xy.X + wh.Width, xy.Y + wh.Height, fontSize, alignment);
col.Go();
}
//直線
private static void DrawLine(PdfContentByte cb, PointF xy, SizeF wh, float lineWidth = 0.5f, int argb = -16777216)
{
BaseColor bc = new BaseColor(argb);
cb.MoveTo(xy.X, xy.Y);
cb.LineTo(xy.X + wh.Width, xy.Y+ wh.Height);
cb.SetLineWidth(lineWidth);
cb.SetColorStroke(bc);
cb.ClosePathStroke();
}
//塗りつぶし矩形
private static void DrawFillRect(PdfContentByte cb, PointF xy,SizeF wh, int argb)
{
BaseColor c=new BaseColor(argb);
cb.SetColorFill(c);
cb.Rectangle( xy.X, xy.Y,wh.Width,wh.Height);
cb.Fill();
}

ライン、文字列の関数はすべて ( x=左 y=下 w=幅, h=高さ )を変数に作成してありますが、これはIllastrator の「ウィンドウ> 変形」のXYWHと一致させるためです。Illastratorの「変形」の値を参照しながら位置を設定していきます。もし、Illastratorのオブジェクトの名前と位置をテキストにエクスポート出来ることができれば、もっと簡便に設定できるのですが。。

また、Illastrator「変形」の基準ポイント(9点)の 左、中央、右はitextsharpのElement.ALIGN_LEFT,Element.ALIGN_CENTER,Element.ALIGN_RIGHTに相当します。たとえば、Element.ALIGN_RIGHTだと xは右側が基準です。同様にElement.ALIGN_CENTERの場合は中央が基準です。

3 ghostscript.net


ghostscript.netで直接印刷します。
ghostscript.netにはプレビュー用のフォームのサンプルもあるのでビュアーも作成可能。 Acrobat Readerよりはずっと早い。

サンプルコード

using Ghostscript.NET;
using Ghostscript.NET.Viewer;
using Ghostscript.NET.Processor;

var pd = new System.Drawing.Printing.PrintDocument();
string printerName = pd.PrinterSettings.PrinterName;
string inputFile = ””;

using (GhostscriptProcessor processor = new GhostscriptProcessor())
{
List<string> switches = new List<string>();
switches.Add("-empty");
switches.Add("-dPrinted");
switches.Add("-dBATCH");
switches.Add("-dNOPAUSE");
switches.Add("-dNOSAFER");
switches.Add("-dNumCopies=1"); //部数
switches.Add("-sDEVICE=mswinpr2");
switches.Add("-sPAPERSIZE=a4");
//横指定A4
//switches.Add("-dDEVICEWIDTHPOINTS=842");
//switches.Add("-dDEVICEHEIGHTPOINTS=595");
//両面印刷
//switches.Add("-dDuplex");//TrueON,false=off
//switches.Add("-dTumble=true");//True=短辺綴じ false=長辺綴じ
switches.Add("-sOutputFile=%printer%" + printerName);
switches.Add("-f");
switches.Add(inputFile);
processor.StartProcessing(switches.ToArray(), null);
}

いままで印刷は、PrintDocumentクラスを使用したり、xpsを用いたりと四苦八苦していたのですが、Ghostscriptで簡単に行けそうです。あぁ無料。



2015年9月2日水曜日

GDCM memo

Move Scu

1) Study >> Series move
2) Study >> image move

1) Study からSeriesを抽出。series単位で move

var scp = new gdcm.ServiceClassUser();
ushort port = 11112;
ushort portScp = 104;
string aetcalled = "DCM4CHEE";
string aetcalling = "any";
string host = "192.168.0.100";
//
string patId = "12345";
//sendmove
var scu = new gdcm.ServiceClassUser();
//scu.SetHostname("192.168.17.13"); scu.SetAETitle("any");
scu.SetHostname(host);
scu.SetAETitle(aetcalling);//
scu.SetPort(port);
scu.SetTimeout(1d);
scu.SetCalledAETitle(aetcalled);
// InitializeConnection
if (!scu.InitializeConnection())
{ Console.WriteLine("Err :Init"); return; }
var generator = new PresentationContextGenerator();
var retDatasets = new DataSetArrayType();
// Find SCU
var theTagPair = new gdcm.KeyValuePairArrayType();
theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0010, 0x0020), patId));
theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), "*"));    //StudyInstanceUID
var findquery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eStudy, theTagPair);
if (!generator.GenerateFromUID(findquery.GetAbstractSyntaxUID()))
{ Console.WriteLine("Err :VerificationSOPClass"); return; }
scu.SetPresentationContexts(generator.GetPresentationContexts());
string studyInstanceUid = string.Empty;
string seriesInstanceUid = string.Empty;
           
if (!scu.StartAssociation())
{ Console.WriteLine("Err :StartAssociation"); return; }
if (scu.SendFind(findquery, retDatasets))
{
    if (retDatasets.Count > 0)
    {
        foreach (gdcm.DataSet d in retDatasets)
            Console.WriteLine("StudyInstanceUID :" + d.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).toString());
        // Find Last StudyInstancUID to SeriesInstanceUID
        theTagPair = new KeyValuePairArrayType();
        studyInstanceUid=retDatasets[retDatasets.Count - 1].GetDataElement(new gdcm.Tag(0x0020, 0x000D)).GetValue().toString();
        Console.WriteLine(studyInstanceUid);
        theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), studyInstanceUid));
        theTagPair.Add(new gdcm.KeyValuePairType(new gdcm.Tag(0x0020, 0x000E), "*"));
        findquery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eSeries, theTagPair);
        if (!generator.GenerateFromUID(findquery.GetAbstractSyntaxUID()))
        { Console.WriteLine("Err :VerificationSOPClass"); return; }
        scu.SetPresentationContexts(generator.GetPresentationContexts());
        retDatasets=new DataSetArrayType();
        if (scu.SendFind(findquery, retDatasets))
        {
            Console.WriteLine(retDatasets.Count);
            if (retDatasets.Count > 0)
            {
                foreach (gdcm.DataSet d in retDatasets)
                    Console.WriteLine("SeriesInstanceUID :" + d.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).toString());
            }
        }
    }
}
if (!scu.StopAssociation())
{ Console.WriteLine("Err :scu StopAssociation"); return; }
//
if (retDatasets.Count == 0)
    return;
var moveds = new gdcm.DataSet();
// Last SeriesInstanceUID
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000D)));
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000E)));
//
var movequery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eImage, moveds, true);
//
if (!generator.GenerateFromUID(movequery.GetAbstractSyntaxUID()))
{ Console.WriteLine("Err :VerificationSOPClass"); return; }
scu.SetPresentationContexts(generator.GetPresentationContexts());
scu.SetPortSCP(portScp);    //PortSCU
if (!scu.StartAssociation())
{ Console.WriteLine("Err :scu StartAssociation"); return; }
var data = new gdcm.DataSetArrayType();
if (!scu.SendMove(movequery, data))
    Console.WriteLine("Err : SendMove");
if (!scu.StopAssociation())
{ Console.WriteLine("Err :scu StopAssociation"); return; }
foreach (gdcm.DataSet d in data)
{
    // represent Photmetric Interpretation
    if(d.FindDataElement(new gdcm.Tag(0x0028,0004)))
        Console.WriteLine(d.GetDataElement(new gdcm.Tag(0x0028,0004)).GetValue().toString());

}
Console.WriteLine("...End");

2)  Study から imageごとに move

var scp = new gdcm.ServiceClassUser();
ushort port = 11112;
ushort portScp = 104;
string aetcalled = "DCM4CHEE";
string aetcalling = "any";
string host = "192.168.0.100";
//
string patId = "12345";
//sendmove
var scu = new gdcm.ServiceClassUser();
//scu.SetHostname("192.168.17.13"); scu.SetAETitle("any");
scu.SetHostname(host);
scu.SetAETitle(aetcalling);//
scu.SetPort(port);
scu.SetTimeout(1d);
scu.SetCalledAETitle(aetcalled);
// InitializeConnection
if (!scu.InitializeConnection())
{ Console.WriteLine("Err :Init"); return; }
var generator = new PresentationContextGenerator();
var retDatasets = new DataSetArrayType();
// Find SCU
var theTagPair = new gdcm.KeyValuePairArrayType();
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0020), patId));
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0018), "*"));//SOPInstanceUID
var findquery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eImage, theTagPair);
if (!generator.GenerateFromUID(findquery.GetAbstractSyntaxUID()))
{ Console.WriteLine("Err :VerificationSOPClass"); return; }
scu.SetPresentationContexts(generator.GetPresentationContexts());
if (!scu.StartAssociation())
{ Console.WriteLine("Err :StartAssociation"); return; }
if (!scu.SendFind(findquery, retDatasets))
{ Console.WriteLine("Err :SendFind"); return; }
if (!scu.StopAssociation())
{ Console.WriteLine("Err :scu StopAssociation"); return; }
//
if (retDatasets.Count == 0)
    return;

var moveds = new gdcm.DataSet();
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0010, 0x0020)));
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000D)));
moveds.Insert(retDatasets[0].GetDataElement(new gdcm.Tag(0x0020, 0x000E)));
//
var movequery = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType, gdcm.EQueryLevel.eImage, moveds, true);
//
if (!generator.GenerateFromUID(movequery.GetAbstractSyntaxUID()))
{ Console.WriteLine("Err :VerificationSOPClass"); return; }
scu.SetPresentationContexts(generator.GetPresentationContexts());
scu.SetPortSCP(portScp);

if (!scu.StartAssociation())
{ Console.WriteLine("Err :scu StartAssociation"); return; }
            
for (int i = 0; i < retDatasets.Count; i++)
{
    var queryds = movequery.GetQueryDataSet();

    var instanceuid = retDatasets[i].GetDataElement(new gdcm.Tag(0x0008, 0x0018));
    Console.WriteLine(instanceuid.toString());
    queryds.Replace(instanceuid);
    var data = new gdcm.DataSetArrayType();
    if (!scu.SendMove(movequery, data))
    { Console.WriteLine("Err : SendMove"); break; }
    var d = data[0];
    // represent Photmetric Interpretation
    if (d.FindDataElement(new gdcm.Tag(0x0028, 0004)))
        Console.WriteLine(d.GetDataElement(new gdcm.Tag(0x0028, 0004)).GetValue().toString());


}
if (!scu.StopAssociation())
{ Console.WriteLine("Err :scu StopAssociation"); return; }
Console.WriteLine("End");

2015年8月28日金曜日

GDCM memo

Find Scu

PatID>>StudyInstansUID>>SeriesInstanceUID>>SOPInstanceUID
患者番号からSOPInstanceUIDを抽出

ushort port = 11112;
string aetcalled = "DCM4CHEE";
string aetcalling = "any";
string host = "192.168.0.1";
//Patient Number
string patId="123";
//Study Level
gdcm.PresentationContextGenerator generator = new PresentationContextGenerator();
gdcm.KeyValuePairArrayType theTagPair = new KeyValuePairArrayType();
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0020), patId));
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0010), "*"));    //Name
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0030), "*"));    //Birthday
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0010, 0x0040), "*"));    //Sex
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), "*"));    //StudyInstanceUID
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0050), "*"));    //AccessionNumber
var query = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.ePatientRootType,
    gdcm.EQueryLevel.eStudy, theTagPair);
var ret = new DataSetArrayType();
bool b = gdcm.CompositeNetworkFunctions.CFind(host, port, query, ret, aetcalling, aetcalled);
List studyInsUidList = new List();
for (int i = 0; i < ret.Count; i++)
{
    var ds = ret[i];
    Console.WriteLine("StudyInsUid:" + ds.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).GetValue().toString());
    studyInsUidList.Add(ds.GetDataElement(new gdcm.Tag(0x0020, 0x000D)).GetValue().toString());
}
//Series Level
string studyInsUid = studyInsUidList[0].Trim(); //Select First Series                 
theTagPair = new KeyValuePairArrayType();
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000D), studyInsUid));    //StudyInstanceUID
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000E), "*"));            //SeriesInstanceUID
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0060), "*"));            //Modality
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x0011), "*"));            //SeriesNumber
query = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType,
    gdcm.EQueryLevel.eSeries, theTagPair);
ret = new DataSetArrayType();
gdcm.CompositeNetworkFunctions.CFind(host, port, query, ret, aetcalling, aetcalled);
List seriesInsUidList = new List();
for (int i = 0; i < ret.Count; i++)
{
    var ds = ret[i];
    Console.WriteLine("SeriesInsUid:" + ds.GetDataElement(new gdcm.Tag(0x0020, 0x000E)).GetValue().toString());
    seriesInsUidList.Add(ds.GetDataElement(new gdcm.Tag(0x0020, 0x000E)).GetValue().toString());
}
//Image Level
string seriesInsUid = seriesInsUidList[0].Trim(); //Select First Series                 
theTagPair = new KeyValuePairArrayType();
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x000E), seriesInsUid));   //SeriesInstanceUID
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0020, 0x0013), "*"));            //InstanceNumber
theTagPair.Add(new KeyValuePairType(new gdcm.Tag(0x0008, 0x0018), "*"));            //SOPInstanceUID
query = gdcm.CompositeNetworkFunctions.ConstructQuery(gdcm.ERootType.eStudyRootType,
    gdcm.EQueryLevel.eImage, theTagPair);
ret = new DataSetArrayType();
gdcm.CompositeNetworkFunctions.CFind(host, port, query, ret, aetcalling, aetcalled);

for (int i = 0; i < ret.Count; i++)
{
    var ds = ret[i];
    Console.WriteLine("SopInsUid:" + ds.GetDataElement(new gdcm.Tag(0x0008, 0x0018)).GetValue().toString());
}

2015年8月22日土曜日

GDCM memo / send scu

 
var dir = new System.IO.DirectoryInfo(@"c:\dicom");
var filesInfo = dir.GetFiles("*.dcm");
//
var scu = new gdcm.ServiceClassUser();
scu.SetHostname("host");
scu.SetPort((ushort)11112);
scu.SetCalledAETitle("DCM4CHEE");
scu.SetAETitle("any");
scu.SetTimeout(2000);
if (!scu.InitializeConnection())
{ Console.WriteLine("Err :suc initialize connection"); return; }
var ft = new gdcm.FilenamesType();
foreach (FileInfo fi in filesInfo)
    ft.Add(fi.FullName);
var g = new gdcm.PresentationContextGenerator();
g.GenerateFromFilenames(ft);
scu.SetPresentationContexts(g.GetPresentationContexts());
if (!scu.StartAssociation())
{ Console.WriteLine(": suc Start Association"); return; }
foreach (FileInfo fi in filesInfo)
{
    if (!scu.SendStore(fi.FullName))
    { 
        Console.WriteLine("Err: Send scu[" +  fi.FullName +"]");
        break;
    }
                
}
if (!scu.StopAssociation())
{ Console.WriteLine("\r\nErr: suc Stop Association\n"); return; }
Console.WriteLine("\r\nEnd");
scu.Dispose();
g.Dispose();
ft.Dispose();

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;
       }
    }
}