3

現時点では、データの配列を取得する方法として C# 文字列を受け入れている非常に苦痛なライブラリがあります。どうやら、これにより pinvokes のマーシャリングが容易になります。

では、ushort 配列をバイト単位で文字列にするにはどうすればよいでしょうか。私はもう試した:

int i;
String theOutData = "";
ushort[] theImageData = inImageData.DataArray;
 //this is as slow like molasses in January
 for (i = 0; i < theImageData.Length; i++) {
     byte[] theBytes = System.BitConverter.GetBytes(theImageData[i]);
     theOutData += String.Format("{0:d}{1:d}", theBytes[0], theBytes[1]);
 }

私はこのようにそれを行うことができますが、それはまともな時間に近いものではありません.

ここで何をすべきですか?安全ではないですか?ある種の IntPtr 中間体を通過しますか?

C++ の char* である場合、これは非常に簡単になります...

編集:関数呼び出しは

DataElement.SetByteValue(string inArray, VL Length);

ここで、VL は DICOM タイプの「値の長さ」であり、関数自体は SWIG によって C++ ライブラリへのラッパーとして生成されます。マネージド/アンマネージド境界を比較的簡単に越えることができるため、選択された表現は文字列のようですが、プロジェクト (これは GDCM) の C++ コード全体で、char* は単にバイト バッファーとして使用されます。したがって、イメージ バッファー ポインターを設定する場合、C++ ではかなり単純ですが、C# ではこの奇妙な問題に悩まされています。

これはハッキングであり、おそらく最善の方法は SWIG ライブラリを正しく動作させることであることを私は知っています。私は本当にそれを行う方法がわかりません.C#側での簡単な回避策があれば、それを望んでいます。

4

6 に答える 6

7

P/Invoke は、ほとんどの場合、StringBuilder を使用して書き込み可能なバッファーを作成した後、実際に処理できます。たとえば、GetWindowText の pinvoke.net および関連する関数を参照してください。

ただ、それはさておき、データはushortなので、UTF-16LEでエンコードされているものとします。その場合は、Encoding.Unicode.GetString() を使用できますが、ushort 配列ではなくバイト配列が必要になります。ushort をバイトに変換するには、別のバイト配列を割り当てて、次のように Buffer.BlockCopy を使用できます。

ushort[] data = new ushort[10];
for (int i = 0; i < data.Length; ++i)
    data[i] = (char) ('A' + i);

string asString;
byte[] asBytes = new byte[data.Length * sizeof(ushort)];
Buffer.BlockCopy(data, 0, asBytes, 0, asBytes.Length);
asString = Encoding.Unicode.GetString(asBytes);

ただし、安全でないコードが問題ない場合は、別のオプションがあります。配列の先頭を ushort* として取得し、それを char* にハードキャストしてから、次のように文字列コンストラクターに渡します。

string asString;
unsafe
{
    fixed (ushort *dataPtr = &data[0])
        asString = new string((char *) dataPtr, 0, data.Length);
}
于 2008-11-08T02:02:56.980 に答える
1

できることの 1 つは、文字列の使用から stringBuilder に切り替えることです。これにより、パフォーマンスが大幅に向上します。

安全でないコードを使用する場合は、ポインターを使用して、C++ と同じように C# コードを実装できます。または、この機能を実装する小さな c++\cli dll を作成することもできます。

于 2008-11-08T02:02:12.037 に答える
1

Bufferクラスを調べます。

ushort[] theImageData = inImageData.DataArray;

byte[] buf = new byte[Buffer.ByteLength(theImageData)]; // 2 bytes per short
Buffer.BlockCopy(theImageData, 0, buf, 0, Buffer.ByteLength(theImageData));

string theOutData = System.Text.Encoding.ASCII.GetString(buf);
于 2008-11-08T02:16:43.363 に答える
1

参考までに、これは後のリビジョン (gdcm 2.0.10) で修正されています。ここを見て:

http://gdcm.sourceforge.net/

-> http://apps.sourceforge.net/mediawiki/gdcm/index.php?title=GDCM_Release_2.0

于 2008-12-18T13:57:56.860 に答える
0

私はこれがあまり好きではありませんが、次の仮定を考えるとうまくいくようです:

1. 各 ushort は 0 ~ 127 の ASCII 文字です

2. (わかりました、仮定は 1 つだけだと思います)

        ushort[] data = inData; // The ushort array source

        Byte[] bytes = new Byte[data.Length];  // Assumption - only need one byte per ushort

        int i = 0;
        foreach(ushort x in data) {
            byte[] tmp = System.BitConverter.GetBytes(x);
            bytes[i++] = tmp[0];
            // Note: not using tmp[1] as all characters in 0 < x < 127 use one byte.
        }

        String str = Encoding.ASCII.GetString(bytes);

これを行うためのより良い方法があると確信していますが、すぐに思いつくことができるのはそれだけです。

于 2008-11-08T02:14:29.390 に答える