binary_compressedされたPCDファイルを自前プログラムで読めるようにしたいと思い、libLZFの使い方を調べてみました。例によって日本語の説明は見つからなかったのですが、試してみたらとても簡単で、ヘッダファイルに書かれていた情報だけで実装できました。
- libLZFのページ
- 旧libLZFのページ(オリジナル作者のMarc Lehmann氏のもの?)
- Githubリポジトリ
テストコードは次のようなのです。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <errno.h>
#include <liblzf/lzf.h>
#define DEFAULT_SIZE 10000
int main(int argc, char *argv[])
{
uint8_t *data_org;
uint8_t *data_comp;
uint8_t *data_decomp;
size_t size_org, size_comp, size_decomp;
int i;
bool result = true;
size_org = argc > 1 ? atoi( argv[1] ) : DEFAULT_SIZE;
data_org = malloc( sizeof(uint8_t) * size_org );
data_comp = malloc( sizeof(uint8_t) * size_org - 1 );
data_decomp = malloc( sizeof(uint8_t) * size_org );
for( i=0; i<size_org; i++ )
data_org[i] = rand() % 0x10;
size_comp = lzf_compress( data_org, size_org, data_comp, size_org - 1 );
if( size_comp == 0 ){
fprintf( stderr, "compression error\n" );
result = false;
} else{
size_decomp = lzf_decompress( data_comp, size_comp, data_decomp, size_org );
if( size_decomp == 0 ){
fprintf( stderr, "decompression error\n" );
result = false;
} else{
printf( "original size = %lu\n", size_org );
printf( "compressed size = %lu\n", size_comp );
printf( "decompressed size = %lu\n", size_decomp );
for( i=0; i<size_org; i++ )
if( data_org[i] != data_decomp[i] ) result = false;
}
}
printf( "%s\n", result ? "Success" : "Failure" );
free( data_org );
free( data_comp );
free( data_decomp );
return 0;
}
エラーチェックを真面目にしていませんが、ご容赦下さい。
圧縮する関数
actual_size_comp = lzf_compress( data_org, size_org, data_comp, size_comp );
と解凍する関数
actual_size_org = lzf_decompress( data_org, size_org, data_decomp, size_decomp );
がほぼ全てです。
前者はサイズsize_org
である元データ(メモリ上先頭アドレスdata_org
)を、アドレスdata_comp
以降の領域にサイズsize_comp
以下になるように圧縮したい、という意味で、返り値actual_size_comp
は実際に作成された圧縮データのサイズです。
圧縮に失敗した(サイズをsize_comp
以下に出来なかった)場合は、返り値は0となります。
後者はその逆で、size_decomp
である圧縮データ(メモリ上先頭アドレスdata_decomp
)を、アドレスdata_org
以降の領域に解凍したい(サイズはsize_org
であることを期待する)、という意味で、返り値actual_size_org
は実際に作成された解凍データのサイズです。
解凍に失敗した(サイズがsize_org
以下でなかった)場合は、返り値は0となります。
どちらも、圧縮/解凍サイズを前もってある程度予想出来ないと使えません。例えば圧縮時は、少なくとも元サイズsize_org
よりは小さくなることを期待するので、ワースト値size_org - 1
としておけば良いように思いますが、元サイズがそもそもあまり大きくない(100バイト程度とか)場合は高確率で失敗するようです。解凍時も同様です。
PCDでは解凍後のサイズをヘッダに書く決まりがあるので、その点は問題ありません。Zeoのzeo_vec3d_pcd.cにPCDファイルread/write処理を実装しています。