HOME > Zlib Basic Function Manual

 

Zlib Basic Function Manual

 

 

 

Introduction

 

기본적으로 Basic Function만을 이용하면 압축과 복원을 할 수 있다.

Zlib library에서 제공하는 그 외의 Function은 단순히 사용자 편의를 위한 것이다.

 

다만 Basic Function에서 제공하는 Deflate 압축 알고리즘과 GZIP을 혼동해서는 안 된다.

GZIP은 Header, Compressed Data, 그리고 Trailer로 구성되어 있다.

Deflate 알고리즘은 이 중 Compressed Data를 생성하기 위한 것이다.

 

주의!!! GZIP 파일 포맷으로 압축 및 복원하기 위해서는 Advanced Function의 도움을 받아야 한다.

특히 Advanced Function 중 deflateInit2inflateInit2함수에 주목하라.

 

 

Function List

 

1. 라이브러리 버전 체크

 

 

A. const char * zlibVersion (void);


 

2. 압축 – 소스 코드 보기

 

 

A. int deflateInit (z_streamp strm, int level);

 

 

B. int deflate (z_streamp strm, int flush);

 

 

C. int deflateEnd (z_streamp strm);


 

3. 복원 – 소스 코드 보기

 

 

A. int inflateInit (z_streamp strm);

 

B. int inflate (z_streamp strm, int flush);

 

C. int inflateEnd (z_streamp strm);

 

 

 

 

Function Description

 

1. 라이브러리 버전 체크

 

 

A. const char * zlibVersion (void);

 

 

The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit.

 

(예제)

 

 

 

 

static const char* myVersion = ZLIB_VERSION;

 

if (zlibVersion()[0] != myVersion[0]) {       

        fprintf(stderr, "incompatible zlib version\n");

        exit(1);

} else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {       

        fprintf(stderr, "warning: different zlib version\n");

}

 

 

 

2. 압축 – 소스 코드 보기

 

 

A. int deflateInit (z_streamp strm, int level);

 

 

deflateInit함수는 압축을 위한 초기화를 할 뿐, 압축 작업을 수행하지는 않는다.

Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions.

 

 

(Error Return)

 

Z_OK if success

Z_MEM_ERROR if there was not enough memory

Z_STREAM_ERROR if level is not a valid compression level

Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION).

 

msg is set to null if there is no error message.

 

(예제)

 

 

 

z_stream stream;

 

/* 모든 메모리 메니지먼트를 라이브러리에 맡긴다 */

// deflateInit()를 호출하기 전에 초기화해야 한다.

stream.zalloc=Z_NULL;

stream.zfree=Z_NULL;

stream.opaque=Z_NULL;

 

//압축을 위한 초기화 과정

int err=deflateInit2(stream, compress Level, Z_DEFLATED,-MAX_WBITS,

         DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);

 

 

 

 

 

 

B. int deflate (z_streamp strm, int flush);

 

 

deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush.

 

The detailed semantics are as follows. deflate performs one or both of the following actions:

l       Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate().

l       Provide more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set.

 

Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly ; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate (). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending.

 

If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary.

 

If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade the compression.

 

If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out).

 

If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space ; if deflate returns with Z_OK, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd.

 

Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least 0.1% larger than avail_in plus 12 bytes. If deflate does not return Z_STREAM_END, then it must be called again as described above.

 

deflate() sets strm-> adler to the adler32 checksum of all input read so far (that is, total_in bytes).

deflate() may update data_type if it can make a good guess about the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner.

 

deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero).

 

 

(예제)

 

 

 

z_ stream z;

/* 모든 메모리 메니지먼트를 라이브러리에 맡긴다 */

    z.zalloc = Z_NULL;

    z.zfree = Z_NULL;

    z.opaque = Z_NULL;

 

    /* Z_DEFAULT_COMPRESSION가 표준이다.*/

    if ( deflateInit(&z, Z_DEFAULT_COMPRESSION) != Z_OK ) {

        fprintf(stderr, "deflateInit: %s\n", (z.msg) ?  z.msg : "???");

        exit(1);

    }

 

    z.avail_in = 0;             /* 입력 버퍼중의 데이터의 바이트수 */

    z.next_out = outbuf;        /* 출력 포인터 */

    z.avail_out = OUTBUFSIZE;    /* 출력 버퍼의 사이즈 */

 

    /* 통상은 deflate()의 제2 인수는 Z_NO_FLUSH 로 해 호출한다 */

    flush = Z_NO_FLUSH;

 

    while (1) {

        if (z.avail_in == 0) {  /* 입력이 다하면 */

            z.next_in = inbuf;  /* 입력 포인터를 입력 버퍼의 선두에 */

            z.avail_in = fread(inbuf, 1, INBUFSIZE, fin); /* 데이터를 읽어 들인다 */

 

            /* 입력이 마지막에 되면(자) deflate()의 제2 인수는 Z_FINISH 로 한다 */

            if (z.avail_in < INBUFSIZE) flush = Z_FINISH;

        }

        status = deflate(&z, flush); /* 압축한다 */

        if (status == Z_STREAM_END) break; /* 완료 */

        if (status != Z_OK) {   /* 에러 */

            fprintf(stderr, "deflate: %s\n", (z.msg) ?  z.msg : "???");

            exit(1);

        }

        if (z.avail_out == 0) { /* 출력 버퍼가 다하면 정리해 써낸다 */

            if (fwrite(outbuf, 1, OUTBUFSIZE, fout) != OUTBUFSIZE) {

                fprintf(stderr, "Write error\n");

                exit(1);

            }

            z.next_out = outbuf; /* 출력 버퍼 잔량을 바탕으로 되돌린다 */

            z.avail_out = OUTBUFSIZE; /* 출력 포인터를 바탕으로 되돌린다 */

        }

    }

 

    /* 나머지를 토해낸다 */

    if ((count = OUTBUFSIZE - z.avail_out) != 0) {

        if (fwrite(outbuf, 1, count, fout) != count) {

            fprintf(stderr, "Write error\n");

            exit(1);

        }

    }

 

    /* 뒤처리 */

    if ( deflateEnd(&z) != Z_OK) {

        fprintf(stderr, "deflateEnd: %s\n", (z.msg) ?  z.msg : "???");

        exit(1);

    }

 

 

 

 

 

 

 

 

 

C. int deflateEnd (z_streamp strm);

 

 

 

All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output.

 

 

(Error Return)

 

 

Z_OK if success

Z_STREAM_ERROR if the stream state was inconsistent

Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded).

 

In the error case, msg may be set but then points to a static string (which must not be deallocated).

 

 

(예제)

 

 

 

if (deflateEnd(&z) != Z_OK) {

        fprintf(stderr, "deflateEnd: %s\n", (z.msg) ?  z.msg : "???");

        exit(1);

}

 

 

 

 

 

 

3. 복원 – 소스 코드 보기

 

 

A. int inflateInit (z_streamp strm);

 

 

 

Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. If next_in is not Z_NULL and avail_in is large enough (the exact value depends on the compression method), inflateInit determines the compression method from the zlib header and allocates all data structures accordingly; otherwise the allocation will be deferred to the first call of inflate.

 

If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions.

 

 

(Error Return)

 

Z_OK if success

Z_MEM_ERROR if there was not enough memory

Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller.

 

msg is set to null if there is no error message.

 

inflateInit does not perform any decompression apart from reading the zlib header if present: this will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unchanged.)

 

 

(예제)

 

 

 

 

z_stream z;

/* 모든 메모리 메니지먼트를 라이브러리에 맡긴다 */

    z.zalloc = Z_NULL;

    z.zfree = Z_NULL;

    z.opaque = Z_NULL;

 

    /* 초기화 */

    z.next_in = Z_NULL;

    z.avail_in = 0;

    if ( inflateInit(&z) != Z_OK) {

        fprintf(stderr, "inflateInit: %s\n", (z.msg) ?  z.msg : "???");

        exit(1);

    }

 

 

 

 

 

 

 

 

B. int inflate (z_streamp strm, int flush);

 

 

 

inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may some introduce some output latency (reading input without producing any output) except when forced to flush.

 

The detailed semantics are as follows. inflate performs one or both of the following actions:

l       Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in is updated and processing will resume at this point for the next call of inflate().

l       Provide more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter).

 

Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending.

 

If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much output as possible to the output buffer. The flushing behavior of inflate is not specified for values of the flush parameter other than Z_SYNC_FLUSH and Z_FINISH, but the current implementation actually flushes as much output as possible anyway.

 

inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed ; avail_out must be large enough to hold all the uncompressed data. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The next operation on this stream must be inflateEnd to deallocate the decompression state. The use of Z_FINISH is never required, but can be used to inform inflate that a faster routine may be used for the single inflate() call.

 

If a preset dictionary is needed at this point (see inflateSetDictionary below), inflate sets strm-adler

 to the adler32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT ; otherwise it sets strm-> adler to the adler32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed adler32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct.

 

inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress is possible or if there was not enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then call inflateSync to look for a good compression block.

 

 

(예제)

 

 

 

 

z_stream z;

/* 모든 메모리 메니지먼트를 라이브러리에 맡긴다 */

    z.zalloc = Z_NULL;

    z.zfree = Z_NULL;

    z.opaque = Z_NULL;

 

    /* 초기화 */

    z.next_in = Z_NULL;

    z.avail_in = 0;

    if ( inflateInit(&z) != Z_OK) {

        fprintf(stderr, "inflateInit: %s\n", (z.msg) ?  z.msg : "???");

        exit(1);

    }

 

    z.next_out = outbuf;        /* 출력 포인터 */

    z.avail_out = OUTBUFSIZE;    /* 출력 버퍼 잔량 */

    status = Z_OK;

 

    while (status != Z_STREAM_END) {

        if (z.avail_in == 0) {  /* 입력 잔량이 제로가 되면 */

            z.next_in = inbuf;  /* 입력 포인터를 바탕으로 되돌린다 */

            z.avail_in = fread(inbuf, 1, INBUFSIZE, fin); /* 데이터를 읽는다 */

        }

        status = inflate(&z, Z_NO_FLUSH); /* 전개 */

        if (status == Z_STREAM_END) break; /* 완료 */

        if (status != Z_OK) {   /* 에러 */

            fprintf(stderr, "inflate: %s\n", (z.msg) ?  z.msg : "???");

            exit(1);

        }

        if (z.avail_out == 0) { /* 출력 버퍼가 다하면 정리해 써낸다 */

            if (fwrite(outbuf, 1, OUTBUFSIZE, fout) != OUTBUFSIZE) {

                fprintf(stderr, "Write error\n");

                exit(1);

            }

            z.next_out = outbuf; /* 출력 포인터를 바탕으로 되돌린다 */

            z.avail_out = OUTBUFSIZE; /* 출력 버퍼 잔량을 바탕으로 되돌린다 */

        }

    }

 

    /* 나머지를 토해낸다 */

    if ((count = OUTBUFSIZE - z.avail_out) != 0) {

        if (fwrite(outbuf, 1, count, fout) != count) {

            fprintf(stderr, "Write error\n");

            exit(1);

        }

    }

 

    /* 뒤처리 */

    if ( inflateEnd(&z) != Z_OK) {

        fprintf(stderr, "inflateEnd: %s\n", (z.msg) ?  z.msg : "???");

        exit(1);

    }

 

 

 

 

 

C. int inflateEnd (z_streamp strm);

 

 

 

All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output.

 

 

(Error Return )

 

 

 

 

Z_OK if success

Z_STREAM_ERROR if the stream state was inconsistent.

 

In the error case, msg may be set but then points to a static string (which must not be deallocated).

 

 

 

 

 

(예제)

 

 

 

 

if ( inflateEnd(&z) != Z_OK ) {

        fprintf(stderr, "inflateEnd: %s\n", (z.msg) ?  z.msg : "???");

        exit(1);

}