ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • zlib 라이브러리 - block 관련 샘플
    zlib 2022. 10. 23. 14:13

    강의 주소 : https://youtu.be/LvLfhQEX9lA

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

    • block에 대해서 배운다
    • block을 사용하는 샘플 만들기
    block이란 무엇인가?

    하나의 압축파일은 한개 이상의 block으로 구성되어 있다.
    각 block은 고유한 압축방식과 압축레벨을 지정할 수 있다.
    deflate가 적용되는 영역이 block단위이다.
    blcok을 형성할 때에는 기본적으로 압축방식이나 레벨을 변경하면
    자동적으로 block이 형성되어진다.

    압축파일의 구조

    샘플에선 2개의 block을 만들어보고 다시 풀어서 확인해보는 과정을 가진다.

    프로젝트 생성을 한다.

     

    zlib 라이브러리 visual studio 연결.

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

    91song4.tistory.com

     

    샘플에서 사용할 각 block에 들어갈 입력데이터를 설정한다.

    Bytef m1[] = "TEST01" ;			// block 1 에 들어갈 데이터
    Bytef m2[] = "TEST02" ;			// block 2 에 들어갈 데이터


    압축코딩

    z_stream의 기본설정을 한다.

    do{
        z_stream stream;
        stream.zalloc = Z_NULL;
        stream.zfree = Z_NULL;
        stream.opaque = Z_NULL;
    
        int z_status = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
        if(z_status != Z_OK) break;
        
        deflateEnd(&stream);
    }while(false);

    block은 압축방법과, 압축레벨이 결정이 되면 block이 하나 생성된다.
    함수 deflateInit 호출 시 block(block 1)이 하나 생성된다.

    압축된 데이터를 담을 버퍼, 데이터의 사이즈를 담을 변수를 생성한다.

    const int BUF = 4096;
    Bytef deflate_out[BUF];
    int deflate_size;

    stream 출력 버퍼 할당

    stream.avail_out = BUF;
    stream.next_out = deflate_out;
    함수 deflateParams(z_streamp strm, int level, int strategy)
    deflateParams 은 사용할 압축레벨과 압축방법을 인수로 주고,
    전달받은 인자로 압축방식을 지정한다.
    기존에 input buffer에 데이터가 있으면(입력 돼 있는 버퍼가 있으면)
    거기 까지는 이전방식의 압축방법으로 압축을 하고,
    새로 할당된 버퍼부터 새로운 압축방법을 적용한다.


    input buffer을 비워준다.
    압축레벨로 Z_BEST_COMPRESSION, 압축방법은 Z_HUFFMAN_ONLY을 전달한다.

    stream.avail_in = 0;
    
    delfateParams(&stream, Z_BEST_COMPRESSION, Z_HUFFMAN_ONLY);	// block 2

    stream 입력 버퍼 할당

    stream.avail_in = strlen((const char*)m1);
    stream.next_in = m1;

    압축 함수 호출

    do{
    	deflate(&stream, Z_NO_FLUSH);
    }while(0 != stream.avail_in);


    두번째 block(blcok 2)에 압축이 끝나게 되고 입력 버퍼가 비워지게 된다.
    세번째 block(block 3)에 압축방식을 지정한다 (Z_BEST_SPEED, Z_RLE)
    //RLE 문자열에 동일한 문자가 있으면 aaaaa -> a5 으로 압축하는 방식이다.
    //일반적인 문자열에 사용하기엔 비적합하지만 이미지와 같은 데이터를 압축할때 효과적인 압축방식이다.

    deflate(&stream, Z_BEST_SPEED, Z_RLE);	//block 3

    stream 인풋 버퍼 할당, 압축 함수 호출

    stream.avail_in = strlen((const char*)m2);
    stream.next_in = m2;
    
    do{
    	deflate(&stream, Z_NO_FLUSH);
    }while(0 != stream.avail_in);

    전체 데이터의 압축이 끝났다면 신호를 보내준다.

    deflate(&stream, Z_FINISH);	//block (4)
    //Z_FINISH를 건네주면 내부 데이터 마지막에 4~6byte가 기록이 된다.
    //block 다음에 기록이 되기 때문에 이부분도 고유한 block으로 볼 수 있다.
    //그러나 zlib내부에서는 block으로 보지 않는 듯 하다.

    압축 사이즈 출력

    delfate = BUF - stream.avail_out;
    std::cout << "Deflate Size: " << deflate_size << std::endl;

    압축해제 코딩

    압축해제된 데이터를 담을 버퍼, 데이터의 사이즈를 담을 변수를 생성한다.

    Bytef inflate_out[BUF];
    int inflate_size;

    z_stream 기본 설정을 한다.

    do{
        z_stream stream;
    
        stream.zalloc = Z_NULL;
        stream.zfree = Z_NULL;
        stream.opaque = Z_NULL;
    
        int z_status = inflateInit(&stream);
        if(z_status != Z_OK) break;
        
        inflateEnd(&stream);
    }while(false);

    stream 입/출력 버퍼 할당

    stream.avail_in = deflate_size;
    stream.next_in = deflate_out;
    
    stream.avail_out = BUF;
    stream.next_out = inflate_out;

    압축해제 함수 호출
    블럭 read상태(readed,reading), 스트림 상태, 남은 버퍼사이즈, inflate 데이터, inflate 사이즈 출력

    do{
        z_status = inflate(&stream, Z_BLOCK);
        inflate = BUF - stream.avail_out;
        inflate_out[inflate_size] = NULL;
        std::cout << "//////////////////////////" << std::endl;
        std::cout << "Block Readed?: "<< ((stream.data_type & 0x80) ? 1 : 0 ) << std::endl;
        std::cout << "Block Reading: "<< ((stream.data_type & 0x40) ? 1 : 0 ) << std::endl;
        std::cout << "Return: "<< z_status << std::endl;
        std::cout << "avail_in: " << stream.avail_in << std::endl;
        std::cout << "NOW Data: " << (const char*)inflate_out << std::endl;
        std::cout << "NOW Data Len: " << inflate_size << std::endl;
    }while(Z_status != Z_STREAM_END);
    //flush모드를 Z_BLOCK으로 전달하면 inflate함수는 block단위로 데이터를 읽는다.
    //block이 3+(1)개 있으니 3+(1)번에 걸쳐서 읽게 된다.
    //z_stream.data_type 이라는 변수로 상태를 확인할 수 있다.
    //변수 data_type은 8bit(1byte)로 구성되어 있다.
    //data_type에 [0]자리에 1이 들어오게 되면 block를 읽었다는 신호이다.
    //[1]자리에 1이 들어오게 되면 block을 읽는 중이다.
    //[2]~[7]자리는 Huffman algorithm을 사용해서 압축을 할 때
    //8의 배수를 채우지 못한 비트를 따로 보관하게 되는데
    //그 보관한 비트들이 몇 비트인지를 표현한다.

     

    실행시켜보자.

    강의와 일치하는 결과가 나왔다.

    강의가 싱크가 맞지않아서 강의를 듣는데 애를 먹었다.
    영상은 나중에 참조하고 설명을 집중적으로 듣고 이해할만큼 듣고, 영상으로 다시 돌려서 확인하는 방식으로 공부했다.

    지금까지 블럭단위 압축과 해제를 공부해보았다

Designed by Tistory.