遊戲用得到的壓縮方式

在C目錄中有算法文件,進入Util\LzmaLib目錄,編譯生成LIB庫,導出了以下兩函數,LzmaCompress 爲壓縮函數,LzmaUncompress 爲解壓縮函數。

MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
unsigned char *outProps, size_t *outPropsSize,
int level,
unsigned dictSize,
int lc,
int lp,
int pb,
int fb,
int numThreads
);

MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
const unsigned char *props, size_t propsSize);

導入Types.h 和 Lzmalib.h 到工程中。

代碼如下:

#include "stdafx.h"
#include "LzmaLib.h"

#pragma comment(lib,"lzma.lib")

int _tmain(int argc, _TCHAR* argv[])
{
FILE* pFile = _tfopen(_T("file.dat"), _T("rb"));

if (pFile == NULL)
{
_ftprintf(stderr, _T("Error to Open the file!"));
return - 1;
}

fseek(pFile, 0, SEEK_END);
size_t srcLen = ftell(pFile);
rewind(pFile);
size_t destLen = srcLen * 2;
unsigned char* psrcRead = new unsigned char[srcLen]; //原始文件數據
unsigned char* pDecomress = new unsigned char[srcLen]; //存放解壓縮數據
unsigned char* pLzma = new unsigned char[destLen]; //存放壓縮數據

fread(psrcRead, sizeof(char), srcLen, pFile);

unsigned char prop[5] =
{
0
};
size_t sizeProp = 5;

if (SZ_OK != LzmaCompress(pLzma, &destLen, psrcRead, srcLen, prop,
&sizeProp, 9, (1 << 24), 3, 0, 2, 32, 2))
{
//出錯了
_ftprintf(stderr, _T("壓縮時出錯!"));
delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;
fclose(pFile);
return - 1;
}

FILE* pCompressFile = _tfopen(_T("compress.dat"), _T("wb"));
//寫入壓縮後的數據
if (pCompressFile == NULL)
{
_ftprintf(stderr, _T("創建文件出錯!"));
delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;
fclose(pFile);
return - 1;
}
fwrite(pLzma, sizeof(char), destLen, pCompressFile);
fclose(pCompressFile);

FILE* pDecompressFile = _tfopen(_T("decompress.dat"), _T("wb"));
//寫入解壓縮數據
if (pDecompressFile == NULL)
{
_ftprintf(stderr, _T("寫入數據出錯!"));
delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;
fclose(pFile);
return - 1;
}

//注意:解壓縮時props參數要使用壓縮時生成的outProps,這樣才能正常解壓縮
if (SZ_OK != LzmaUncompress(pDecomress, &srcLen, pLzma, &destLen, prop, 5))
{
delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;

fclose(pDecompressFile);
fclose(pFile);
return - 1;
}

fwrite(pDecomress, sizeof(char), srcLen, pDecompressFile);

delete [] psrcRead;
delete [] pDecomress;
delete [] pLzma;

fclose(pDecompressFile);
fclose(pFile);

return 0;
}


zlib使用:

zlib 是通用的壓縮庫,提供了一套 in-memory 壓縮和解壓函數,並能檢測解壓出來的數據的完整性(integrity)。下面介紹兩個最有用的函數——compress 和 uncompress。

int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);

compress函數將 source 緩衝區中的內容壓縮到 dest 緩衝區。 sourceLen 表示source 緩衝區的大小(以字節計)。注意函數的第二個參數 destLen 是傳址調用。當調用函數時,destLen表示 dest 緩衝區的大小,destLen > (sourceLen + 12)*100.1%。當函數退出後,destLen 表示壓縮後緩衝區的實際大小。此時 destLen / sourceLen 正好是壓縮率。

compress 若成功,則返回 Z_OK;若沒有足夠內存,則返回 Z_MEM_ERROR;若輸出緩衝區不夠大,則返回 Z_BUF_ERROR。

int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);

uncompress 函數將 source 緩衝區的內容解壓縮到 dest 緩衝區。sourceLen 是 source 緩衝區的大小(以字節計)。注意函數的第二個參數 destLen 是傳址調用。當調用函數時,destLen 表示 dest 緩衝區的大小, dest 緩衝區要足以容下解壓後的數據。在進行解壓縮時,需要提前知道被壓縮的數據解壓出來會有多大。這就要求在進行壓縮之前,保存原始數據的大小(也就是解壓後的數據的大小)。這不是 zlib 函數庫的功能,需要我們做額外的工作。當函數退出後, destLen 是解壓出來的數據的實際大小。

uncompress 若成功,則返回 Z_OK ;若沒有足夠內存,則返回 Z_MEM_ERROR;若輸出緩衝區不夠大,則返回 Z_BUF_ERROR。若輸入數據有誤,則返回 Z_DATA_ERROR。

代碼如下:

#include "stdafx.h"
#include <cstring>
#include <cstdlib>
#include <iostream>
#include "zlib.h"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
int err = 0;
Byte compr[200] = {0}, uncompr[200] = {0}; // big enough
uLong comprLen = 0, uncomprLen = 0;

const char* hello = "12345678901234567890123456789012345678901234567890";

uLong len = strlen(hello) + 1;
comprLen = sizeof(compr) / sizeof(compr[0]);

err = compress(compr, &comprLen, (const Bytef*)hello, len);

if (err != Z_OK)
{
cerr << "compess error: " << err << '\n';
exit(1);
}

cout << "orignal size: " << len
<< " , compressed size : " << comprLen << '\n';

strcpy((char*)uncompr, "garbage");

err = uncompress(uncompr, &uncomprLen, compr, comprLen);

if (err != Z_OK)
{
cerr << "uncompess error: " << err << '\n';
exit(1);
}

cout << "orignal size: " << len
<< " , uncompressed size : " << uncomprLen << '\n';

if (strcmp((char*)uncompr, hello))
{
cerr << "BAD uncompress!!!\n";
exit(1);
}
else
{
cout << "uncompress() succeed: \n" << (char*)uncompr;
}
}



發佈了17 篇原創文章 · 獲贊 6 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章