0

F# を使用して、VTK XML ファイル用の独自のライターを作成しています。VTK ファイルには、バイナリ データの base64 エンコーディングと、こちらで説明されているヘッダーが必要です。

... したがって、バイナリ データは base64 でエンコードする必要があります。さらに、データの先頭にヘッダーが追加されます。これは、データ長 (バイト単位) を含む 32 ビット整数です。このヘッダーは個別にエンコードされます。したがって、疑似コードでは、データ出力は次のようになります (常にスペースや改行なしで!)

私のコードは次のようになります:

let toBase64 (v: int []) =
  use ms = new System.IO.MemoryStream()
  let s = System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
  s.Serialize(ms, v)
  let b = ms.ToArray()
  let len = System.BitConverter.GetBytes b.Length
  System.Convert.ToBase64String len + System.Convert.ToBase64String b

ただし、結果は正しくありません。次の入力の場合:

toBase64 [| 1; 2; 3; 4 |]

ParaView (C++ で作成) は、1 ~ 4 ではなく -256 ~ 511 の範囲を表示します。私のコードに明らかなバグはありますか?

編集: base64 でエンコードされたデータは次のようになります。

ラアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアアル

編集 2 : float の配列を取り、Byte 配列に変換し、Ionic.Zip.dll ZLib を使用して圧縮し、base64 文字列に変換するソリューションを同封します。関数は VTK XML ファイルで正常に動作します。

let toZlib (v: float []) =
  use msSinkCompressed = new System.IO.MemoryStream()
  let zOut = new ZlibStream(msSinkCompressed, CompressionMode.Compress, CompressionLevel.Default, true)
  for i in v do 
    let bytes = System.BitConverter.GetBytes i
    zOut.Write(bytes, 0, bytes.Length)
  zOut.Flush()
  zOut.Close()
  let comprBytes = msSinkCompressed.ToArray()
  let header =
    let blocks = System.BitConverter.GetBytes 1
    let len = System.BitConverter.GetBytes (v.Length * 8)
    let comprLen = System.BitConverter.GetBytes comprBytes.Length
    Array.append(Array.append (Array.append blocks len) len) comprLen
  System.Convert.ToBase64String header + System.Convert.ToBase64String comprBytes
4

2 に答える 2

1

私は VTK 形式について何も知りませんが、その方法が正しいとしたら非常に驚かれることでしょうBinaryFormatter。.NET 型の独自のエンコーディングを生成し、多くの追加情報が含まれていると思います (VTK 形式には含まれていません)。バイナリ .NET シリアル化に基づいていない限り、必要ありません)。

整数値をストリームに直接書き込む方が良いと思います。私が言ったように、フォーマットはわかりませんが、次のようなものが必要なものに近いと思います:

let toBase64 (v: int []) = 
  use ms = new System.IO.MemoryStream() 
  for i in v do 
    let bytes = System.BitConverter.GetBytes i
    ms.Write(bytes, 0, bytes.Length)
  let b = ms.ToArray() 
  let len = System.BitConverter.GetBytes b.Length 
  System.Convert.ToBase64String len + System.Convert.ToBase64String b 
于 2010-11-22T12:36:24.537 に答える
0

Paraview が 1 から 4 を表示するのはなぜですか? .NET 型に関する多くBinaryFormatterの追加メタデータを含む複雑な獣です。これをどのようにエンコードするかを明確にすることができれば、おそらく役立つでしょう。たとえば、1 ~ 4 がバイトの場合、base-64 で直接エンコードできるはずです。それらを整数として扱う場合は、最初にバイトにエンコードする必要があります。

最終的には、詳細なエンコード規則 (エンディアンなどを含む) がなければ、決定的な答えを出すのは困難ですが、BinaryFormatterほぼ確実にそうではありません。

私はカスタム バイナリ エンコーディングに非常に精通しており、より多くのヘルプ/ガイダンスを提供できることをうれしく思いますが、プロトコルが何を期待しているかという点で、より多くの情報が必要です。

たとえば、C# を使用して(申し訳ありませんが、私の F# foo には制限があります)、リトルエンディアンの固定長 32 ビット整数エンコーディングを全体的に想定します。

static void Main() {
    string s = Encode(new int[] { 1, 2, 3, 4 });
}
static string Encode(int[] data) {
    byte[] buffer = new byte[data.Length * 4];
    int offset = 0;
    for(int i = 0 ; i < data.Length ; i++) {
        int value = data[i];
        buffer[offset++] = (byte)value;
        buffer[offset++] = (byte)(value >> 8);
        buffer[offset++] = (byte)(value >> 16);
        buffer[offset++] = (byte)(value >> 24);
    }
    byte[] header = new byte[4];
    int len = buffer.Length;
    header[0] = (byte)len;
    header[1] = (byte)(len >> 8);
    header[2] = (byte)(len >> 16);
    header[3] = (byte)(len >> 24);
    return Convert.ToBase64String(header) + Convert.ToBase64String(buffer);
}
于 2010-11-22T12:34:42.070 に答える