Vollständige Version anzeigen : [C/C++] GZ und BZ2 Kompression (Stream) (updated - 09.04)


terraNova
07.04.2011, 19:20

Heyho

Ich hab für ein Projekt letztens einen GZ-Stream (Mittels zLib (;zlib~net)) gebastelt und vielleicht interessiert den ein oder anderen den Code ja.

comp_streams;h:
#ifndef COMP_STREAMS_H_
#define COMP_STREAMS_H_

#include <zlib;h>
#include <vector>

namespace dman {
namespace comp {
typedef std::vector<unsigned char> ByteArray;

enum eStreamStates {
eSSNone = 0,

/* (DE-)Compress
- Params for stream_state::method()
*/
eSSComp,
eSSDecomp,

/* Clear Buffer
- Param for stream_state::clear()
*/
eSSClear,

/* Level
- Params for stream_state::level()
*/
// ZLIB
eSSGZSpeed = Z_BEST_SPEED,
eSSGZNComp = Z_NO_COMPRESSION,
eSSGZBComp = Z_BEST_COMPRESSION,
eSSGZDComp = Z_DEFAULT_COMPRESSION,

// BZLIB
eSSBZCWorst = 1, // From
eSSBZCBest = 9, // To
};

class stream_state {
protected:
int _method;
int _clear;
int _level;

public:
stream_state( void );
~stream_state( void );

int get_method( void );
int get_clear( void );
int get_level( void );

static
stream_state& method( int method );

static
stream_state& level( int level = Z_BEST_SPEED );

static
stream_state& clear( void );

void apply( stream_state& rhs );
} /* class stream_mode */;

class gzstream {
private:
ByteArray buf;
stream_state state;

public:
gzstream( void );
explicit gzstream( char* buf, size_t count );
~gzstream( void );

void clear( void );
size_t read( char *buf, size_t count );

ByteArray& get( void );

protected:
unsigned
char* compress( const unsigned char *in, size_t *len );

unsigned
char* decompress( const unsigned char *in, size_t *len );

void process( void );

void check_states( void );

public:
gzstream& operator <<( const unsigned char rhs );
gzstream& operator <<( const unsigned char* rhs );
gzstream& operator <<( ByteArray rhs );
gzstream& operator <<( stream_state& rhs );

gzstream& operator >>( ByteArray& rhs );
} /* class gz */;

class bz2stream {
private:
ByteArray buf;
stream_state state;

public:
bz2stream( void );
explicit bz2stream( char* buf, size_t count );
~bz2stream( void );

void clear( void );
size_t read( char *buf, size_t count );

ByteArray& get( void );

protected:
unsigned
char* compress( const unsigned char *in, size_t *len );

unsigned
char* decompress( const unsigned char *in, size_t *len );

void process( void );

void check_states( void );

public:
bz2stream& operator <<( const unsigned char rhs );
bz2stream& operator <<( const unsigned char* rhs );
bz2stream& operator <<( ByteArray rhs );
bz2stream& operator <<( stream_state& rhs );

bz2stream& operator >>( ByteArray& rhs );
} /* class bz */;
} /* ns comp */;
} /* ns dman */;

#endif /* COMP_STREAMS_H_ */


comp_streams;cpp:
#include "comp_streams;h"

namespace dman {
namespace comp {
# define SSApply(x) if(mode;x != eSSNone) x = mode;x;
# define SSGet(x, m) static int sx; sx = x; x = m; return sx;

const size_t c_g_tokLen = 4096;

/* ==================================================================
STREAM_MODE
================================================================== */
stream_state::stream_state( void ) {
_method = eSSNone;
_clear = eSSNone;
_level = eSSGZNComp;
}

stream_state::~stream_state( void ) {

}

int stream_state::get_level( void ) {
SSGet(_level, _level);
}

int stream_state::get_method( void ) {
SSGet(_method, _method);
}

int stream_state::get_clear( void ) {
SSGet(_clear, eSSNone);
}

stream_state& stream_state::level( int level ) {
static stream_state mode;
memset(&mode, 0, sizeof(stream_state));

switch(level) {
case eSSGZSpeed:
case eSSGZDComp:
case eSSGZBComp:
case eSSGZNComp:
break;

default: {
mode;_level = eSSGZNComp;
return mode;
}
}

mode;_level = level;
return mode;
}

stream_state& stream_state::method( int method ) {
static stream_state mode;
memset(&mode, 0, sizeof(stream_state));

mode;_method = method;
return mode;
}

stream_state& stream_state::clear( void ) {
static stream_state mode;
memset(&mode, 0, sizeof(stream_state));

mode;_clear = eSSClear;
return mode;
}

void stream_state::apply( stream_state& mode ) {
SSApply(_method);
SSApply(_clear);
SSApply(_level);
}

/* ==================================================================
GZSTREAM
================================================================== */
gzstream::gzstream( void ) {

}

gzstream::~gzstream( void ) {
buf;clear();
}

gzstream::gzstream( char *buf, size_t count ) {
read(buf, count);
}

void gzstream::clear( void ) {
buf;clear();
}

size_t gzstream::read( char *buf, size_t count ) {
if(buf == nullptr || count <= 0)
return 0;

this->buf;insert(this->buf;end(), buf, buf+count);
return 0;
}

ByteArray& gzstream::get( void ) {
process();

return buf;
}

unsigned char* gzstream::compress( const unsigned char *in, size_t *len ) {
static ByteArray out;
unsigned char buf[c_g_tokLen] = {0};
z_stream iStrm = {0};
size_t done = 0;

out;clear();
memset(&iStrm, Z_NULL, sizeof(z_stream));

int ret = deflateInit(&iStrm, state;get_level());

if(ret != Z_OK)
return 0;

iStrm;avail_in = (*len);
iStrm;next_in = (Bytef*)in;

while(ret != Z_STREAM_END) {
memset(buf, 0, c_g_tokLen);
iStrm;avail_out = c_g_tokLen;
iStrm;next_out = (Bytef*)buf;
ret = deflate(&iStrm, Z_FINISH);
out;insert(out;end(), buf, buf+c_g_tokLen);
}

(*len) = iStrm;total_out;
ret = deflateEnd(&iStrm);

return &out[0];
}

unsigned char* gzstream::decompress( const unsigned char *in, size_t *len ) {
static ByteArray out;
unsigned char buf[c_g_tokLen] = {0};
z_stream iStrm = {0};

memset(buf, 0, c_g_tokLen);
memset(&iStrm, Z_NULL, sizeof(z_stream));

int ret = inflateInit(&iStrm, state;get_level());

if(ret != Z_OK)
return 0;

iStrm;avail_in = *len;
iStrm;next_in = (Bytef*)in;

while(ret != Z_STREAM_END) {
memset(buf, 0, c_g_tokLen);
iStrm;avail_out = c_g_tokLen;
iStrm;next_out = (Bytef*)buf;
ret = inflate(&iStrm, Z_FINISH);
out;insert(out;end(), buf, buf+c_g_tokLen);
}

(*len) = iStrm;total_out;
inflateEnd(&iStrm);

return &out[0];
}

void gzstream::process( void ) {
if(buf;empty() == true)
return;

switch(state;get_method()) {
case eSSComp: {
size_t len = buf;size();
unsigned char *comp = compress(&buf[0], &len);

buf;clear();
buf;assign(comp, comp+len);
} break;

case eSSDecomp: {
size_t len = buf;size();
unsigned char *decomp = decompress(&buf[0], &len);

buf;clear();
buf;assign(decomp, decomp+len);
} break;
}
}

void gzstream::check_states( void ) {
if(state;get_clear()) {
clear();
}
}

gzstream& gzstream::operator <<( const unsigned char rhs ) {
check_states();
buf;insert(buf;end(), rhs);

return (*this);
}

gzstream& gzstream::operator <<( const unsigned char* rhs ) {
check_states();
buf;insert(buf;end(), rhs, rhs+strlen((const char*)rhs));

return (*this);
}

gzstream& gzstream::operator <<( ByteArray rhs ) {
check_states();
buf;insert(buf;end(), rhs;begin(), rhs;end());

return (*this);
}

gzstream& gzstream::operator <<( stream_state& rhs ) {
state;apply(rhs);
return (*this);
}

gzstream& gzstream::operator >>( ByteArray& rhs ) {
check_states();
process();

rhs;assign(buf;begin(), buf;end());
return (*this);
}

/* ==================================================================
BZ2STREAM
================================================================== */
bz2stream::bz2stream( void ) {

}

bz2stream::~bz2stream( void ) {
buf;clear();
}

bz2stream::bz2stream( char *buf, size_t count ) {
read(buf, count);
}

void bz2stream::clear( void ) {
buf;clear();
}

size_t bz2stream::read( char *buf, size_t count ) {
if(buf == nullptr || count <= 0)
return 0;

this->buf;insert(this->buf;end(), buf, buf+count);
}

ByteArray& bz2stream::get( void ) {
process();

return buf;
}

unsigned char* bz2stream::compress( const unsigned char *in, size_t *len ) {
static ByteArray out;
unsigned char buf[c_g_tokLen] = {0};
bz_stream iStrm = {0};
size_t done = 0;
bool ran = false;

out;clear();
memset(&iStrm, 0, sizeof(bz_stream));

int ret = BZ2_bzCompressInit(&iStrm, state;get_level(), 0, 30);

if(ret != BZ_OK)
return 0;

iStrm;avail_in = (*len);
iStrm;next_in = (char*)in;

while(ret != BZ_STREAM_END) {
memset(buf, 0, c_g_tokLen);
iStrm;avail_out = c_g_tokLen;
iStrm;next_out = (char*)buf;

ret = BZ2_bzCompress(&iStrm, (ran?BZ_FINISH:BZ_RUN));

if(ret == BZ_RUN_OK && !ran) {
ran = true;
}

if(ret < 0) {
out;clear();
return 0;
}

if(*buf != 0)
out;insert(out;end(), buf, buf+c_g_tokLen);
}

(*len) = (iStrm;total_out_hi32 << 32)+iStrm;total_out_lo32;
ret = BZ2_bzCompressEnd(&iStrm);

return &out[0];
}

unsigned char* bz2stream::decompress( const unsigned char *in, size_t *len ) {
static ByteArray out;
unsigned char buf[c_g_tokLen] = {0};
bz_stream iStrm = {0};

memset(buf, 0, c_g_tokLen);
memset(&iStrm, Z_NULL, sizeof(bz_stream));

int ret = BZ2_bzDecompressInit(&iStrm, 0, 0);

if(ret != BZ_OK)
return 0;

iStrm;avail_in = *len;
iStrm;next_in = (char*)in;

while(ret != BZ_STREAM_END) {
memset(buf, 0, c_g_tokLen);
iStrm;avail_out = c_g_tokLen;
iStrm;next_out = (char*)buf;

ret = BZ2_bzDecompress(&iStrm);

if(ret < 0) {
out;clear();
return 0;
}

out;insert(out;end(), buf, buf+c_g_tokLen);
}

(*len) = (iStrm;total_out_hi32 << 32)+iStrm;total_out_lo32;
BZ2_bzDecompressEnd(&iStrm);

return &out[0];
}

void bz2stream::process( void ) {
if(buf;empty() == true)
return;

switch(state;get_method()) {
case eSSComp: {
size_t len = buf;size();
unsigned char *comp = compress(&buf[0], &len);

buf;clear();
buf;assign(comp, comp+len);
} break;

case eSSDecomp: {
size_t len = buf;size();
unsigned char *decomp = decompress(&buf[0], &len);

buf;clear();
buf;assign(decomp, decomp+len);
} break;
}
}

void bz2stream::check_states( void ) {
if(state;get_clear()) {
clear();
}
}

bz2stream& bz2stream::operator <<( const unsigned char rhs ) {
check_states();
buf;insert(buf;end(), rhs);

return (*this);
}

bz2stream& bz2stream::operator <<( const unsigned char* rhs ) {
check_states();
buf;insert(buf;end(), rhs, rhs+strlen((const char*)rhs));

return (*this);
}

bz2stream& bz2stream::operator <<( ByteArray rhs ) {
check_states();
buf;insert(buf;end(), rhs;begin(), rhs;end());

return (*this);
}

bz2stream& bz2stream::operator <<( stream_state& rhs ) {
state;apply(rhs);
return (*this);
}

bz2stream& bz2stream::operator >>( ByteArray& rhs ) {
check_states();
process();

rhs;assign(buf;begin(), buf;end());
return (*this);
}
} /* ns comp */;
} /* ns dman */;


Beispielanwendung zur De-/Kompression von Dateien:

main;cpp:

#include <iostream>
#include <fstream>
using namespace std;

#include "comp_streams;h"
using namespace dman::comp;

void compress( const char *src, const char* dest ) {
unsigned char c;
ByteArray comp;

fstream in(src, ios::binary|ios::in),
out(dest, ios::binary|ios::out);

if(!in;is_open() || !out;is_open())
return;

gzstream gz;
gz << stream_state::method(eSSComp) << stream_state::level(eSSGZBComp);

while(!in;eof() && in;good()) {
in;get((char&)c);

if(in;eof())
break;

gz << c;
}

gz >> comp;
out;write((char*)&comp[0], comp;size());

in;close(); out;close();
}

void decompress( const char *src, const char* dest ) {
unsigned char c;
ByteArray comp;

fstream in(src, ios::binary|ios::in),
out(dest, ios::binary|ios::out);

if(!in;is_open() || !out;is_open())
return;

gzstream gz;
gz << stream_state::method(eSSDecomp);

while(!in;eof() && in;good()) {
in;get((char&)c);

if(in;eof())
break;

gz << c;
}

gz >> comp;
out;write((char*)&comp[0], comp;size());

in;close(); out;close();
}

int main( int argc, char **argv ) {
if(argc != 4) {
cout << "prog <-c | -d> <src> <dest>" << endl;
return 0;
}

switch(*(argv[1]+1)) {
case 'c': {
cout << "Komprimiere '" << argv[2] << "' zu '" << argv[3] << "'. ";
compress(argv[2], argv[3]);
} break;

case 'd': {
cout << "Dekomprimiere '" << argv[2] << "' zu '" << argv[3] << "'. ";
decompress(argv[2], argv[3]);
} break;
}

return 0;
}


Um dem gzstream mitzuteilen, was er gerade zu tun hat (De-/Komprimieren, Buffer leeren, Kompressionslevel) hab ich die stream_state Klasse erstellt, die das ganze dann bequem per Stream regelt.

Die Klassen sind nicht optimiert, daher bitte ich hier auf die Funktionsweise einzugehen, sollte Diskussionsbedarf bestehen.

Benötigt wird die Bibliothek zlib die ich oben verlinkt habe (Ebenfalls im Ref;-Thread (Siehe Sig)).

Grüße.


// EDIT:

BZ2 Stream noch hinzugefügt. Benötigt wird die BZip2 (;bzip~org) Lib.
Um den Stream im Beispiel anzuwenden, einfach anstelle von "gz" "bz2" einsetzen.

Hardware Preisvergleich | Amazon Blitzangebote!

Videos zum Thema
Video Loading...
xXsoureXx
09.04.2011, 17:04

nice! :)

Hab vor ca. 2-3 Wochen angefangen mich mal mit der zlib zu beschäftigen,
deshalb nice timing :thumbsup: :D

Bin leider grad nicht zu hause, werd' mir das aber auf jeden Fall mal
genauer anschauen


Ähnliche Themen zu [C/C++] GZ und BZ2 Kompression (Stream) (updated - 09.04)
  • hohe kompression (schwer zum kicken)
    ich habe in meiner "neuen" (bj 97) ktm 360 die ich erst gekauft habe eine sehr hohe kompression im zylinder, ich bring sie kaum zum kicken, mit normalen schuhen kann man sie gar nicht kicken. kann man das auf einfache art ändern? weiss einer rat? thx greetz erli [...]

  • Virtual Dub Audio Kompression!
    Hallo, Ich habn dickes Problem.. hab jetzt meein neues Fragmovie fertig und es klappt was ned.. Nach diesem Tut hab ich jetzt das Video Komprimiert. (;;;movie-odin~de/phpkit/include;php?path=content/download;php&contentid=20&download=go) Dann im 2. Durchlauf rendert man der die oder das [...]

  • Beste Kompression für Videos
    Hallo ich hab ein Sony Ericsson K750i und den Total Video Converter und möchte Video Datein als Handyformat speichern und aufm Handy dann logischerweise anscheuan ;) Jetzt suche ich den besten Qualiäts-Größe Kompromiss als Einstellungen für den Converter. Hoffe hier kann mir jemand helfen [...]

  • Kompression für DVD-->PSP
    Ich hätt ne frage: Ich hab mir die dvd-box von band of brothers gekauft. Weil ich nächste woche wegfahr will ich mir da vill 2 folgen auf der fahrt ansehen. Bring ich die auf ne 2 giga memory-card? Wenn ja wie? MfG LuX88 [...]



raid-rush.ws | Imprint & Contact pr