ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • zlib 라이브러리 - Dictionary 사용하기
    zlib 2022. 10. 23. 02:06

    강의 영상 : https://youtu.be/OCidZqJpCw4

    공부를 글로 남기는 습관을 들이려 내용들을 기록하는 중입니다.
    체계적이지 않으며, 전문적이지 않습니다.
    의식의 흐름으로 기록합니다.

    강의 목적
    LZ77 알고리즘에 대해서 살펴보고, dictionary를 고정으로 가져가는 방법을 알아보자.

    LZ77알고리즘은 기본적으로 2개의 버퍼로 나눈다. (search buffer:dictionary, look ahead buffer)

    LZ77 기본 버퍼 구조

    look ahead buffer에서 동일한 데이터가 search buffer 에 있는지 조사해서,
    동일한 부분이 있으면 그 부분을 압축의 대상으로 설정하는 방법이다.

    만약에 input으로 사용되는 데이터가 일정한 규칙을 가지고 있고, 그것을 알고있다고 한다면,
    굳이 버퍼를 크게 할당하여 조사하는 방법보다는
    앞에있는 search buffer를 고정 dictionary로 가져가는 것이 더 효율적이다.
    그러면 look ahead buffer 에서 sliding 하는것이 아니라, 사용되면 사라지는 형태로 만들수 있다.

    프로젝트 Sample3_Dictionary 생성.

    Sample3_Dictionary

     

     

    zlib 라이브러리 visual studio 연결.

    프로젝트와 zlib와 연결을 해주자. zlib 관련 .h 파일들이 있는 폴더를 포함. lib파일이 있는 폴더와 연결 실제 사용하는 파일명을 연결 Debug모드는 파일명이 다르니까 재설정

    91song4.tistory.com

     

    이번에 만들어볼 샘플의 내용은
    search buffer를 동적이 아닌 고정으로 사용해서 look ahead buffer와 비교를 할 것이다.
    search buffer에 사용될 dictionary 데이터를 만들어 보겠다.

    만약에 input으로 사용되는 데이터가 일정한 규칙을 가지고 있고, 그것을 알고있다고 한다면,

    자주사용되는 인풋데이터가 "HELLO" 라고 가정을 해보자.
    const Bytef dic[] = "HELLO";               //Bytef == unsigned char

    ////////////////////////////////////////// DE_FLATE //////////////////////////////////////////

    z_stream 기본 설정을 한다.

    본 과정 중 가장중요한 부분은
    search buffer를 지정한 buffer로 사용하는 것이다.
    그 명령어가 바로 함수 deflateSetDictionary 이다.
    deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt  dictLength)
    2번째 인수로는 지정할 buffer를 전달한다.
    3번째 인수로는 지정한 buffer의 실제길이를 전달한다.( strlen( (const char*)buffer ) )
    search buffer 는 지정한 buffer로 고정 된다.

    샘플 진행을 위해 입력으로 사용될 데이터를 만들어보자.(HELLO가 많이 중복되게)
    Bytef input[] = "HELLOaHELLObHELLOcHELLOdHELLOeHELLOfHELLOaHELLOdHELLOsHELLOoHELLOf"
    압축해제 후 확인을 위해 원본 문자열을 출력한다.

    아웃풋 버퍼는 압축을 해제할때 사용하기 위해서 여유있게 넉넉히 잡아놓는다.
    여유있게 넉넉히라는건 입력될 인풋데이터가 한 번 압축을 할 때 넘지않을 크기이다.
    const int BUF = deflate(인풋데이터) < n ;
    //압축을 한 번 한다고 해서 크기가 무조건 작아지는건 아니다.
    이방법을 사용하는 이유는
    원칙적으론 do-while 구문으로 압축이 될때까지 반복적으로 압축을 해줘야 하는데,
    (내생각)샘플이기때문에 그러한 부분들을 최소화 해서 간단히 보여주기 위함인 듯 하다.

    deflate의 결과를 담을 output을 만든다.
    Bytef deflate_output[BUF] ;

    z_stream input buffer 설정을 해준다.
    z_stream.avail_in = strlen( (const char*)input ) ;
    z_stream.next_in = input ;

    z_stream output buffer 설정을 해준다.
    z_stream.avail_out = BUF ;
    z_stream.next_out = deflate_out ;

    압축을 해준다.
    deflate( z_stream, Z_NO_FLUSH ) ;

    압축이 끝난 후 해야 할 일은 압축이 끝났다는 시그널을 보내줘야 한다.
    deflate( z_stream, Z_FINISH )
    //코드를 최소화 하다보니 이번 샘플에만 맞춤이 되는 느낌이다.
    실로 사용할 때에는 이 코드를 원칙대로 바꿔서 써야할 것 같다.
    실습을 해볼땐 원칙적으로 코드를 적어서 같은 샘플결과를 얻어봐야겠다.
    //실제로 코드를 적어보니 인풋버퍼에 한번에 들어가기 때문에
    반복문을 돌리는건 밥상을 뒤엎는것과 마찬가지이다.

    압축된 사이즈를 알아보기 위해서 변수를 설정하고 사이즈를 알아보자.
    int deflate_size = BUF - z_stream.avail_out ;
    원본 사이즈와 압축된 사이즈를 출력한다.(나중에 비교해보기 위함)

    ////////////////////////////////////////// IN_FLATE //////////////////////////////////////////

    z_stream 기본 설정을 한다.

    z_stream input buffer 설정
    여기서 인풋버퍼로 사용되는 버퍼는 앞서 압축한 데이터가 사용된다.
    z_stream.avail_in = deflate_size ;
    z_stream.next_in = deflate_out ;

    inflate 의 결과를 담을 output을 만든다.
    Bytef inflate_out[BUF] ;

    z_stream output buffer 설정
    z_stream.avail_out = BUF ;
    z_stream.next_out = inflate_out ;

    avail_in이 0가 될 때까지 반복적으로 압축을 해제한다.
    inflate( z_stream, Z_NO_FLUSH ) ;
    함수 inflate는 함수 진행 중 고정 search buffer를 감지한다.
    감지를 하면 Z_NEED_DICT 을 반환한다.
    진행을 위해 search buffer 를 고정버퍼로 셋팅해준다.
    inflateSetDictionary( z_streamp strm, const Bytef *dictionary, uInt  dictLength )
    2번째 인수로는 지정한 고정 buffer를 전달한다.
    3번째 인수로는 지정한 고정 buffer의 실제길이를 전달한다.( strlen( (const char*)buffer ) )
    search buffer 는 지정한 buffer로 고정 된다.

    압축해제한 사이즈를 구한다.
    int inflate_size = BUF - z_stream.avail_out ;
    사이즈를 출력해보고, 원본 데이터와 같은지 확인한다.
    문자열 출력을 위해 실제 데이터 마지막주소 +1에 null값을 넣어준다.
    inflate_out[inflate_size] = NULL ;
    문자열을 출력 한다. 원본 문자열과 같은지 확인한다.

    확인을 위해 화면을 잠시 멈춰둔다
    system("pause") ;

    실행을 해보자.

    압축을 했을 때 사이즈가 더 크다... 음.. 문제가 있는것인지 확인 하는 방법이 있다.
    강의 영상과 똑같은 인풋데이터를 줘보자.

    틀리다. 뭐가 문제일까 다시 영상을 돌려보며 어떤부분이 잘못됐는지 찾아보자.

    영상을 돌려보았고, 비슷하지만 다른부분을 고쳐보았지만 해결되지 않았다.
    구글링을 하던 도중 강의해주시는 선생님이 운영중인듯 하는 사이트를 찾았다.
    http://www.softlab365.com/wordpress/?p=358
    그곳에 나와있는 코드를 복사해서 사용해보자.

     

    고정 Dictionary 기반 압축

    LZ77 알고리즘은 search buffer, lookahead buffer로 구분하고, 뒤에 있는 버퍼가 앞에 있는 버퍼에서 매칭되는 부분을 축약하는 형태의 압축입니다. 결국 뒤 버퍼는 앞 버퍼를 마치 사전처럼 사용합니다.

    www.softlab365.com

    압축이 잘 됐다....
    이제 나의 코드와 어떤점이 다를지 창을 두개 띄워서 비교해보자.
    헉........ 찾았다.

    문제의 그 놈!

    Z_NO_COMPRESSION이 아니라 Z_DEFAULT_COMPRESSION 이어야 한다.
    자동완성 핑계를 바로 떠올렸지만 ,. 우습다.. 분명 확인을 제대로 못한 내 잘못이다.
    앞으로 이런일이 없으려면 코드를 쓸때도 어떤 명령어를 쓰는지 제대로 인지하고 쓰고,
    제대로 들어갔는지 확인하면서 적어야겠다.
    제대로 작동된다.

    원래 하려했던 문자열은 어떻게 되는지 보며 마치겠다.

Designed by Tistory.