본문 바로가기
코스웨어/10년 시스템제어

[시스템제어] 6월9일 업무일지_2 20번 이창민

by 알 수 없는 사용자 2010. 6. 11.
728x90
반응형

  <비트맵의 stribe와 width의 차이점 이해>
    - 20행 #define WIDTH4(width) ((width+3)>>2)<<2  -

 1. 비트맵 인포헤더의 총사이즈와 너비*높이의 값 차이
   - 비트맵의 정보를 담고있는 비트맵 헤더파일을 보면 다음과 같은 특이사항을 발견할 수 있다.
    

   비트맵 크기 = 가로 * 세로 * biBitCount /8 이 되어야한다.
   하지만 실제 비트맵 인포헤더파일에의 값을 확인하면 다음과 같은 결과가 나온다.
   biWidth * biHeight * biBitCount/8 = 399* 295 * 24/8 =  353,115
   * 계산한 크기 값 353,115byte와  실제인포헤더의 biSizeImage의 값은 354000Byte보다 885byte가 작다.
     이 885byte가 의미 하는 것은 무엇일까?

 2. 비트맵 파일 저장시 dummy(사용하지 않는) 메모리.
  - 비트맵 파일은 너비의 데이터를 4의 배수(4Byte, 32bit)로 맞춘다.
    ->이렇게 4의배수로 맞추는 이유는 현재 32bit의 컴퓨터를 사용하기 때문이라고 생각되어지나, 믿거나 말거나!
  
즉 상기 인포헤더에서 너비는 399byte지만 실제 저장되어있는 파일은 400byte이다.
 -  비트맵 파일을 헥사 뷰로 열어서 눈으로 확인해보자.







 - 0x36번지에서 실제 이미지 데이터가 시작된다.
  너비가 399이고 비트카운트가 24이므로 0x36번지부터 1,197(399*24/8)개의 데이터가 첫번째 가로줄의 이미지 데이터이다.
  다시말하면, 0x36~0x4e3의 주소가 첫번째 줄의 이미지 데이터이다.

 - 그리고 4e4~4e6까지의 데이트를 주목하자.
   -> 이 3바이트는 0으로 되어있고 이것이 dummy Data이다.

 - 두번째줄의 마지막(0x993~0x995)에도 똑같은 현상이 발생한다.
 매줄 3byte씩 높이 295byte, 3*295=885byte 
  -> 실제와 계산값에서의 차이 885byte와 정확히 일치한다.
 
 - 모든 비트맵파일에서 저런 dummy데이터가 있는 것일까?
  -> 32bit로 맞출려고 dummy데이터가 존재하는 것이다. 
      따라서, 열의 크기가 4byte의 배수로 되어있는 경우에는 이런 더미데이터가 존재하지 않는다.
   -> 다시말해서 width가 399이면 큰 4의 배수, 400이되고 24비트(3바이트)이므로 dummy값의 크기는 3byte가 되는 것이다.

 이렇게 비트맵의 실제 가로크기와 파일에 저장되어있는 파일크기와는 차이가 난다.
 -> 따라서 비트맵 출력시 이런 점을 잊어버리면 원치않는 결과가 발생할 것이다.

 3. 비트맵에서 stribe크기 맞추기.
 - 그럼 width와 stribe의 크기가 다른데 어떻게 해야할까?
 #define WIDTH4(width) ((width+3)>>2)<<2    : width보다 큰 4의배수를 정의
 그리고 2번째 줄을 읽을때의 첫 Data가 399*3번째의 데이터가 아니라, 400*3번째의 데이터를 읽어야 한다.
 코드는 다음과 같다.
 

121         /**************메모리 동적할당 하여 비트맵 복사 ******************************/
122  
123     cpyData = (BYTE*)malloc(binfo->bmiHeader.biSizeImage);   // 메모리 동적할당. 
124     width4=binfo->bmiHeader.biWidth*3;    
125     width4=WIDTH4(width4);                    //4의 배수로 비트맵 크기를 맞추는 작업.
126     for(height=0; height<binfo->bmiHeader.biHeight;height++)
127     {
128       for(width=0; width<binfo->bmiHeader.biWidth;width++)
129       {
130         cpyData[(height*width4)+width*3]=
131           imageData[(height*width4)+width*3];
132  
133         cpyData[(height*width4)+width*3+1]=
134           imageData[(height*width4)+width*3+1];
135         
136         cpyData[(height*width4)+width*3+2]=
137           imageData[(height*width4)+width*3+2];
138       }
139     }

 4. 90도 회전.
  -
141     /*********************비트맵 정보 180도 회전하여 복사*********************************/
142  
143     reData = (BYTE*)malloc(binfo->bmiHeader.biSizeImage);    
144     for(height=0; height<binfo->bmiHeader.biHeight;height++)
145     {
146       for(width=0; width<binfo->bmiHeader.biWidth;width++)
147       {
148         reData[(height*width4)+width*3]=
149           imageData[((binfo->bmiHeader.biHeight-height-1)*width4)
150                      +(binfo->bmiHeader.biWidth-width-1)*3];
151         reData[(height*width4)+width*3+1]=
152           imageData[((binfo->bmiHeader.biHeight-height-1)*width4)
153                      +(binfo->bmiHeader.biWidth-width-1)*3+1];
154         reData[(height*width4)+width*3+2]=
155           imageData[((binfo->bmiHeader.biHeight-height-1)*width4)
156                      +(binfo->bmiHeader.biWidth-width-1)*3+2];
157       }
158     }

728x90