2010-12-27 43 views
28

Có một ví dụ sử dụng tại trang web zlib: http://www.zlib.net/zlib_how.htmlLàm thế nào để nén một bộ đệm với zlib?

Tuy nhiên trong ví dụ chúng đang nén tệp. Tôi muốn nén một dữ liệu nhị phân được lưu trữ trong một bộ đệm trong bộ nhớ. Tôi cũng không muốn lưu bộ đệm nén vào đĩa.

Về cơ bản đây là bộ đệm của tôi:

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

Làm thế nào tôi có thể nén nó với zlib?

Tôi sẽ đánh giá cao một số ví dụ về cách thực hiện điều đó.

+0

Có vấn đề gì với ví dụ bạn đã đề cập? Nó nén một bộ đệm trong bộ nhớ, chỉ nó đọc dữ liệu từ một tập tin đầu tiên. Bạn nhận được dữ liệu từ một nơi khác, nhưng phần còn lại là như nhau - tại sao nó sẽ không được? –

Trả lời

28

Đây là ví dụ để đóng gói bộ đệm bằng zlib và lưu nội dung đã nén vào vectơ.

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

Tôi chỉ đọc một cách tiếp cận thú vị có sử dụng một lá cờ để kiểm soát trạng thái tuôn ra và thực hiện nó trong một vòng lặp. Ngoài ra, nó đáng chú ý rằng điều này hoạt động tốt như nhau với std :: string thay cho vector, đó là tốt đẹp cho việc gửi qua dây hoặc chức năng khác. – Robert

+2

Điều này có vẻ rất phức tạp. Tại sao tất cả điều này thay vì chỉ sử dụng chức năng 'compress'? – user673679

+2

Nén yêu cầu bạn phải biết kích thước đầu ra và phân bổ bộ đệm đủ lớn; phương pháp này cho phép bạn realloc() và có bộ đệm mở rộng động. –

3

Đây không phải là câu trả lời trực tiếp cho câu hỏi của bạn về API zlib, nhưng bạn có thể quan tâm đến thư viện boost::iostreams được ghép nối với zlib.

Điều này cho phép sử dụng thuật toán đóng gói bằng cách sử dụng ký hiệu hoạt động "luồng" cơ bản và sau đó dữ liệu của bạn có thể được nén dễ dàng bằng cách mở một số luồng bộ nhớ và thực hiện thao tác << data trên đó.

Trong trường hợp boost::iostreams, điều này sẽ tự động gọi bộ lọc đóng gói tương ứng cho mọi dữ liệu đi qua luồng.

+0

Chỉ là một bình luận, nhưng điều này có nghĩa là bạn phải bao gồm thư viện tăng iostream, tăng thư viện zlib, libz và libzbz2, so với chỉ libz. Vì vậy, nếu gói các thư viện này là một vấn đề kích thước thì tốt nhất là tránh tăng trong trường hợp này. ~ Ben – Ben

10

Bạn có thể dễ dàng điều chỉnh ví dụ bằng cách thay thế các cuộc gọi fread()fwrite() bằng các con trỏ trực tiếp vào dữ liệu của bạn. Đối với nén zlib (gọi tắt là deflate như bạn "đưa ra tất cả không khí của dữ liệu của bạn") bạn phân bổ z_stream cấu trúc, hãy gọi deflateInit() và sau đó:

  1. điền next_in với đoạn tiếp theo của dữ liệu bạn muốn nén
  2. thiết avail_in đến số byte có sẵn trong next_in
  3. thiết next_out đến nơi dữ liệu nén nên được viết mà thường phải là một con trỏ bên trong bộ đệm của bạn mà tiến bộ như bạn đi cùng
  4. thiết avail_out đến số byte có sẵn trong next_out
  5. gọi deflate
  6. lặp lại bước 3-5 cho đến khi avail_out không phải là zero (ví dụ: có chỗ hơn trong bộ đệm đầu ra so với nhu cầu zlib - không có nhiều dữ liệu để viết)
  7. lặp lại bước 1-6 trong khi bạn có dữ liệu để nén

Cuối cùng bạn gọi deflateEnd() và bạn đã hoàn tất.

Về cơ bản, bạn cho ăn khối dữ liệu đầu vào và đầu ra cho đến khi bạn ra khỏi đầu vào và đã hết.

37

zlib.h có tất cả các chức năng bạn cần: compress (hoặc compress2) và uncompress. Xem mã nguồn của zlib để có câu trả lời.

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. Đây là giải pháp EASY chết tiệt nếu bạn muốn tất cả các thiết lập mặc định. Ngay cả khi bạn không muốn cài đặt mặc định, bạn có thể sửa đổi và sử dụng nguồn của các chức năng này. – Hossein

Các vấn đề liên quan