2

compress私は、zlibライブラリ(および関数)を使用して、floatvarsを含む構造体を圧縮する方法を探していました。

私が見たすべての例は、文字列、具体的にはを圧縮する方法を示していますunsigned char*

私の構造体は簡単です:

struct Particle{
    float x;
    float y;
    float z;
};

そして、私は以下のように圧縮関数を呼び出しています:

uLong initSize = sizeof(Particle);
uLongf destSize = initSize * 1.1 + 12;
Bytef *dataOriginal = (Bytef*)malloc( initSize );
Bytef *dataCompressed = (Bytef*)malloc( destSize );

Particle p;
memset( &p, 0, sizeof(Particle) );

p.x = 10.24;
p.y = 23.5;
p.z = 7.4;

memcpy( dataOriginal, &p, sizeof(p) );
compress( dataCompressed, &destSize, dataOriginal, initSize );

しかし、データを解凍して内部の内容を確認しようとすると、最初のfloat値に戻ることができません。

Bytef *decomp = (Bytef*)malloc( initSize );
uncompress( decomp, &initSize, dataCompressed, destSize );

for( int i = 0 ; i < initSize ; i++ ){
    std::cout << (float)decomp[i] << std::endl;
}

誰かがこの問題の解決策を持っているなら、私は今2日からそれを続けています...

4

1 に答える 1

4

最初にコピーしたのと同じように、解凍したデータをパーティクル構造体にコピーして戻す必要があります。(または、コピーの代わりにキャストを使用することもできます)。次に、構造体の元のフロートを復元します。'decomp [i]`で何をしていると思っても、意味がありません。

ただし、これにはいくつかの問題があります。まず、これは、同じマシン、同じコンパイラ、さらには同じバージョンのコンパイラ内でのみ機能することが保証されています。別のコンパイラまたは別のバージョンが構造を別の方法で整列することを選択した場合、圧縮されたデータは2つの間で転送できません。異なるマシン間でフロートの表現が異なる場合、圧縮されたデータは転送できません。

さらに、3つのフロートを圧縮する場合、圧縮は行われません。これは、そのようなパーティクル構造体の大規模な配列を圧縮するための単なる前置きであると思います。それなら多分あなたはこれでどこかに行くでしょう。

最初に浮動小数点数を整数として必要な精度に変換することをお勧めします。アプリケーションの範囲と有用なビット数を知っておく必要があります。compress()これは、フロートあたり32ビットではなく、必要なビット数のみを使用することにより、を使用する前に圧縮されます。次に、これらの整数をシフト操作を使用して一連のバイトに移植可能に変換します。次に、連続するパーティクル(x1-x2、y1-y2、z1-z2など)に差分を適用することもできます。これにより、連続するパーティクル間に相関関係がある場合に圧縮が向上する可能性があります。

ちなみに、の代わりに* 1.1 + 12、を使用する必要がありますcompressBound()。これは、将来のバージョンでzlibライブラリによって保証される方法で必要なことを正確に実行します。

于 2012-11-25T14:59:31.450 に答える