-
zlib 라이브러리 - deflate 예제zlib 2022. 10. 22. 15:11
공부를 글로 남기는 습관을 들이려 내용들을 기록하는 중입니다.
체계적이지 않으며, 전문적이지 않습니다.
의식의 흐름으로 기록합니다.강의 주소 : https://youtu.be/YtJVIMGu-2o
참조 http://egloos.zum.com/studyfoss/v/5357297
테스트.bmp
를 압축 해보자.
프로젝트 생성.
zlib 라이브러리 visual studio 연결.
프로젝트와 zlib와 연결을 해주자. zlib 관련 .h 파일들이 있는 폴더를 포함. lib파일이 있는 폴더와 연결 실제 사용하는 파일명을 연결 Debug모드는 파일명이 다르니까 재설정
91song4.tistory.com
파일 입/출력 변수를 생성한다.
zlib를 사용할 때에는 z_stream이라는 스트럭처를 잘 제어해야 한다.
typedef struct z_stream_s { z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: binary or text for deflate, or the decoding state for inflate */ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream;
z_stream 내부에서 zalloc, zfree, opaque는 서로 연관되어 있다.
zalloc : 메모리를 할당하는 함수포인터를 받는다.
Z_NULL값을 받게되면 zlib라이브러리 내부의 기본메모리할당 함수를 사용한다.
zfree : 메모리를 해제하는 함수포인터를 받는다.
Z_NULL값을 받게되면 zlib라이브러리 내부의 기본메모리해제 함수를 사용한다.
opaque : zalloc, zfree에 전달하는 함수포인터에 argument로 전달된다.deflateInit( strm, (compression) level )
#define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ 압축속도<0------------9>압축률 Z_DEFAULT_COMPRESSION == 6
함수 deflateInit을 호출하게 되면,
- zalloc, zfree, opaque가 받아온 함수포인터로 셋팅
- 압축상태변수에 메모리 할당
- 에러가 없을 시 return Z_OK
메모리 할당이 이루어지니 함수deflateInit을 호출하게 되면,
프로그램을 종료하기 전에 함수deflateEnd를 호출해줘야 한다.기본적인 환경을 맞추고 나면 비로소 압축을 하는 코드를 시작할 수 있다.
기본적인 구조는 알고리즘을 넣으면(input) 결과가 나온다(output).
압축 알고리즘을 넣으면(input) 압축된 결과가 나오고(output),
압축해제 알고리즘을 넣으면(input) 압축해제 된 결과가 나온다(output).준비물은
input과, output을 보관할 버퍼가 있어야 한다.const int BUF = n;
인풋 버퍼를 설정한다.
Bytef input[BUF]; //Bytef 는 내부적으로 unsigned char 이다.
인풋버퍼에 파일을 읽어들인다.
fp.read( (char*)input, BUF ) -> fp.read( (char*)input, BUF )
실제 파일의 크기가 BUF보다 작을 경우를 위해 실제 읽어들인 사이즈를 알아낸다.
int readsize = fp.gcount() //최근에 입력 스트림에서 읽은 바이트수(문장의 개수)리턴.
//C4244 : fp.gcount()의 리턴 자료형은 std::streamsize 이고
readsize의 자료형이 int라서 자료를 잃을수 있다는 경고이다.
지금의 경우엔 BUF의 자료형이 const int이니 크게 문제가 되지 않는다.
그렇지 않은 경우에는 잘 고려해서 자료형을 입력하도록 하자.
int readsize = (int)fp.gcount()
스트림에 인풋버퍼를 설정한다.
z_stream.avail_in = readsize; // avail_in : number of bytes available at next_in
avail_in 실제 읽은 사이즈를 넣어준다.
z_stream.next_in = input; // next_in : next input byte
next_in 버퍼의 시작주소를 넘겨준다.
아웃풋 버퍼를 설정한다.
Bytef output[BUF];
z_stream.avail_out = BUF; // avail_out : remaining free space at next_out
avail_out 아웃풋버퍼의 사이즈.
z_stream.next_out = output; // next_out : next output byte will go here
next_out 버퍼의 시작주소를 넘겨준다.deflate(z_streamp strm, int flush)
#define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 #define Z_TREES 6 /* Allowed flush values; see deflate() and inflate() below for details */
컴퓨터는 바이트단위 기록을 한다. 비트단위 압축되는 Huffman 알고리즘은 1바이트를 다 채우지 않을 수 있다.
그러한 바이트를 처리하는 방법을 deflate의 두번째 인수에 전달한다.
Z_NO_FLUSH 는 그러한 바이트의 처리를 보류한다.deflate() 함수가 반환되는 경우는 크게 다음과 같은 네 가지 경우로 볼 수 있다.
- 입력 버퍼가 비어있는 경우: Z_OK를 반환하고 zs.avail_in == 0이다.
- 출력 버퍼가 가득 찬 경우: Z_OK를 반환하고 zs.avail_out == 0이다.
- 모든 데이터를 처리한 경우: Z_STREAM_END를 반환한다.
- 에러가 발생한 경우: 해당하는 에러 코드를 반환한다.
인풋데이터를 압축해서 나오는 결과가 꼭 인풋데이터보다 작으리라고 보장을 못한다.
압축한 데이터가 실제 데이터보다 클 수 있다.
따라서 모든 인풋데이터를 압축할때까지 반복적으로 압축을 해야 한다.
파일을 읽어들일때도 마찬가지로 모든데이터를 읽을때까지(Z_STREAM_END) 반복적으로 읽어야 한다.
Z_STREAM_END는 언제 반환되어지는가?
flush가 Z_FINISH인 상태에서 모든 인풋데이터가 처리완료가 되면 Z_STREAM_END를 반환한다.
Z_FINISH는 언제 되어야 하는가?
파일을 마지막까지 다 읽어들인 상태로 설정한다.
if ( fp.eof() ) flush = Z_FINISH;
아웃풋 버퍼가 얼마나 기록을 했나?
int dsize = BUF - z_stream.avail_out
최대버퍼사이즈에서 남은버퍼사이즈를 빼면 압축한 데이터사이즈가 나온다.
dsize는 어디에 사용하는가?
파일을 기록할때 이용된다.
wp.write( (const char*)output, dsize)test.bmp와 zlib.dll을 가지고 왔다, 실행시켜보자.
문득 궁금한게 Debug모드로 컴파일 했는데,
Release모드로 빌드한 zlib.dll 파일이 소용이 있을까 궁금해서
Debug(zlibd.dll)모드가 아니라 Release(zlib.dll) 모드 dll을 가져와봤다 일단 해보자.안되네 ㅋㅋ Debug모드로 컴파일한 zlibd.dll을 가져와보자.
ㅋㅋㅋㅋ짜잔~~ test.enc로 압축되었다.
압축은 됐는데, 크기가 거의 비슷하다. 파일 용량이 너무 적어서 그런가싶다.
큰파일을 가져와서 해보자.test.hwp -> test.enc 용량이 줄었다.
다음 영상 강의엔 deflate강의가 있다.
잘 배워보도록 하자!'zlib' 카테고리의 다른 글
zlib 라이브러리 - Dictionary 사용하기 (0) 2022.10.23 zlib 라이브러리 - inflate 예제 (0) 2022.10.22 zlib 라이브러리 visual studio 연결. (0) 2022.10.22 zlib 라이브러리 visual studio에 설치하기. (0) 2022.10.22 zlib 다운로드. (0) 2022.10.21