2010-12-27 23 views
28

Hay un ejemplo de uso en el sitio web de zlib: http://www.zlib.net/zlib_how.htmlCómo comprimir un búfer con zlib?

Sin embargo, en el ejemplo están comprimiendo un archivo. Me gustaría comprimir una información binaria almacenada en un búfer en la memoria. Tampoco quiero guardar el búfer comprimido en el disco.

Básicamente aquí es mi memoria intermedia:

fIplImageHeader->imageData = (char*)imageIn->getFrame(); 

¿Cómo puedo comprimir con zlib?

Agradecería un ejemplo de código de cómo hacerlo.

+0

¿Qué pasa con el ejemplo que mencionó? Comprime un búfer en la memoria, solo lee datos de un archivo primero. Obtienes datos de otro lado, pero el resto es el mismo: ¿por qué no sería? –

Respuesta

28

Este es un ejemplo para empaquetar un búfer con zlib y guardar el contenido comprimido en un vector.

void compress_memory(void *in_data, size_t in_data_size, std::vector<uint8_t> &out_data) 
{ 
std::vector<uint8_t> buffer; 

const size_t BUFSIZE = 128 * 1024; 
uint8_t temp_buffer[BUFSIZE]; 

z_stream strm; 
strm.zalloc = 0; 
strm.zfree = 0; 
strm.next_in = reinterpret_cast<uint8_t *>(in_data); 
strm.avail_in = in_data_size; 
strm.next_out = temp_buffer; 
strm.avail_out = BUFSIZE; 

deflateInit(&strm, Z_BEST_COMPRESSION); 

while (strm.avail_in != 0) 
{ 
    int res = deflate(&strm, Z_NO_FLUSH); 
    assert(res == Z_OK); 
    if (strm.avail_out == 0) 
    { 
    buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE); 
    strm.next_out = temp_buffer; 
    strm.avail_out = BUFSIZE; 
    } 
} 

int deflate_res = Z_OK; 
while (deflate_res == Z_OK) 
{ 
    if (strm.avail_out == 0) 
    { 
    buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE); 
    strm.next_out = temp_buffer; 
    strm.avail_out = BUFSIZE; 
    } 
    deflate_res = deflate(&strm, Z_FINISH); 
} 

assert(deflate_res == Z_STREAM_END); 
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE - strm.avail_out); 
deflateEnd(&strm); 

out_data.swap(buffer); 
} 
+0

Acabo de leer un enfoque interesante que utiliza una bandera para controlar el estado de descarga y lo hace en un ciclo. Además, vale la pena señalar que esto funciona igual de bien con std :: string en lugar del vector, lo cual es bueno para enviar por cable o para otra función. – Robert

+2

Esto parece muy complicado. ¿Por qué hacer todo esto en lugar de simplemente usar la función 'compress'? – user673679

+2

Compress requiere que conozca el tamaño de salida y asigne un buffer suficientemente grande; este método te permite realloc() y tener un buffer de expansión dinámica. –

3

Esta no es una respuesta directa a su pregunta sobre la API de zlib, pero puede estar interesado en boost::iostreams biblioteca emparejada con zlib.

Esto permite utilizar algoritmos de embalaje zlib impulsada por el uso de la notación básica operaciones "corriente" y, a continuación sus datos podrían ser comprimido fácilmente abriendo alguna secuencia de memoria y haciendo la operación << data en él.

En el caso de boost::iostreams esto invocaría automáticamente el filtro de empaque correspondiente para cada dato que pasa a través de la secuencia.

+0

Solo un comentario, pero esto significa que debe incluir la biblioteca boost iostreams, impulsar la biblioteca zlib, libz y libzbz2, en comparación con solo libz. Entonces, si agrupar estas bibliotecas es un problema de tamaño, entonces lo mejor es evitar el impulso en este caso. ~ Ben – Ben

10

Puede adaptar fácilmente el ejemplo reemplazando las llamadas fread() y fwrite() con punteros directos a sus datos. Para la compresión zlib (referido como desinflar como "sacar todo el aire de sus datos") se puede asignar z_stream estructura, llame deflateInit() y luego:

  1. llenar next_in con el siguiente fragmento de datos que desea Comprimir
  2. conjunto avail_in al número de bytes disponibles en next_in
  3. establece next_out a donde los datos comprimidos deben ser escritos que debería ser normalmente un puntero dentro de la memoria intermedia que avanza a medida que avanza
  4. conjunto avail_out al número de bytes disponibles en next_out
  5. llamada deflate
  6. repita los pasos 3-5 hasta avail_out no es cero (es decir, hay más espacio en el buffer de salida de las necesidades zlib - hay más datos para escribir)
  7. repita los pasos 1-6, mientras que tiene datos para comprimir

el tiempo te llaman deflateEnd() y ya está.

Básicamente lo está alimentando en trozos de entrada y salida hasta que se agote la entrada y se quede sin salida.

37

zlib.h tiene todas las funciones que necesita: compress (o compress2) y uncompress. Consulte el código fuente de zlib para obtener una respuesta.

ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); 
/* 
     Compresses the source buffer into the destination buffer. sourceLen is 
    the byte length of the source buffer. Upon entry, destLen is the total size 
    of the destination buffer, which must be at least the value returned by 
    compressBound(sourceLen). Upon exit, destLen is the actual size of the 
    compressed buffer. 

     compress returns Z_OK if success, Z_MEM_ERROR if there was not 
    enough memory, Z_BUF_ERROR if there was not enough room in the output 
    buffer. 
*/ 

ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); 
/* 
     Decompresses the source buffer into the destination buffer. sourceLen is 
    the byte length of the source buffer. Upon entry, destLen is the total size 
    of the destination buffer, which must be large enough to hold the entire 
    uncompressed data. (The size of the uncompressed data must have been saved 
    previously by the compressor and transmitted to the decompressor by some 
    mechanism outside the scope of this compression library.) Upon exit, destLen 
    is the actual size of the uncompressed buffer. 

     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not 
    enough memory, Z_BUF_ERROR if there was not enough room in the output 
    buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In 
    the case where there is not enough room, uncompress() will fill the output 
    buffer with the uncompressed data up to that point. 
*/ 
+3

+1. Esta es la maldita solución EASY si quieres todas las configuraciones predeterminadas. Incluso si no desea la configuración predeterminada, puede modificar y usar el origen de estas funciones. – Hossein

Cuestiones relacionadas