3.PlayStation 1(one) 2D Format 해부학 - ConverBMP(16Bit)

ConvertBMP(16Bit)


작성자 : kallru(신휘재)
E-Mail : kallru@kornet.net

 

※이 문서는 작성자의 허락없이 재배포 할 수 없음을 알려드립니다. 최소한 작성자에 허락 정도는 맡아주시기 바랍니다.

 

지식은 권한을 보호 받어야 한다.


- 목  차 -
10.16Bit의 특징
11..BYTE와 BIT
12.16Bit를 24Bit로 만드는 And연산의 힘
13.포인터의 힘과 주의점

 

10.16Bit의 특징
16Bit는 먼저 그 특징과 개념을 이해하기가 좀 힘든데, Bit 개념이 확실히 서지 않은 사람이라면 더욱더 난해할 것이고 Bit 개념이 충분하다면 쉬울 것이다. 나 또한 한참 프로그램에 기초를 배우면서 Bit이니 Byte니 하면서 머리 아플 때 16Bit 강의를 듣게 되었었는데 지금 생각해봐도 그때 선생님이 뭐라고 한지 도저히 이해 할 수 없다. 자 그럼 16Bit의 특징을 살펴 보자.
 16Bit는 말 그대로 16개의 Bit로 1픽셀을 표현한다는 것이다. 1픽셀을 표현하는데 16비트를 사용한다는 것인데, 그래픽을 조금 이라도 아는 사람이라면 RGB와 CMYK를 알 것이다. 컴퓨터는 RGB로 이루어저 있다는 것도 알고 있을 것이다. 그렇다면 1픽셀을 16개의 Bit로 표현한다면 16개의 Bit로 RGB를 표현한다는 소리가 되는 것이다. 그런데 문제는 바로 여기서부터 시작되어진다.
 3으로 16을 나누면 1이 남게 된다. 각각의 RGB 마다 5Bit씩 할당해 준다고 생각하면 1Bit가 남는 것이다. 그럼 이 사태를 어떻게 해결해야 될까? 그래서 나온 것이 바로 2가지 해결책이 나오게 된 것이다.
 첫 번째 방법은 5:5:5 모드라고 해서 각각 RGB를 5:5:5씩 주는 것이다. 그럼 좀 전에 이야기 한 대로 1바이트가 남게 된다. 이 1바이트를 사용하지 않는 것이다. 즉 이건 16Bit가 아니라 15Bit가 되는 것이다. 과거에는 이 방식을 많이 사용했다. 이해를 돕기 위해 간단한 그림을 붙이겠다.


[X][R][R][R] [R][R][G][G] [G][G][G][B] [B][B][B][B] -> 실제 사용되는 Bit수는 15Bit, 최상위 1Bit는 사용하지 않는다.


 두 번째 방법은 5:6:5 모드라고 하는 것이다. 사람의 눈이 초록색깔에 민감하데나?? 그런 것을 생각해서 G 에 1Bit를 더 주는 방식이다. 그림을 보고 5:5:5 모드와 비교 해본다면 쉽게 이해 될 것이다.


[R][R][R][R] [R][G][G][G] [G][G][G][B] [B][B][B][B] -> 이것이 실제로 16Bit, 16개의 모든 Bit를 사용한다.

 

이렇게 16Bit를 가지고 RGB를 표현하게 된다. 그렇다면 각각 5Bit 또는 6Bit를 주는데, 이걸 값으로 보면 R이 가질수 있는 값은 0∼31 까지가 된다. 2진수로 1 1111 이니까 0부터 31까지의 값을 가지게 되는 셈이다. 각 RGB마다 이 정도로 값을 가지면 실제로 거의 모든 색상을 다 표현 할 수 있다고 생각된다. 그래서 아직까지도 사용되어진다.
 물론 약간 모자르다 싶어서 그래픽 부분에선 24Bit를 사용한다. 이 "10"번 파트를 잘 이해 하길 바란다. 어려운 부분은 없지만 Bit 라는게 무엇인지, 그리고 RGB와 Bit, 픽셀들을 잘 알고 있다면 지금, 그리고 앞으로도 문제 없다. 그리고 마지막으로 Tim포맷은 15Bit를 사용한다.

 

11.BYTE와 BIT
이번에는 Bit와 Byte의 관계를 설명 하려 한다. 물론 잘 알고 있을 것이지만, 나중에 쉬프트 연산을 하다보면 자꾸 햇갈리는 관계로 여기에 간단하게 기술해두려 한다. 계산을 하다가 햇갈리면 이번 파트를 참고하길 바라며, 또 나도 Byte와 Bit가 하드웨어에서 어떻게 동작하는지, 그런 세세하고 구체적인 것을 모르므로 좀 더 좋은 자료가 있다면 그걸 활용하길 바란다.
 Byte와 Bit관계는 별거 없다. 1Byte는 8Bit라는 것이다. 그럼 16Bit는 몇 Byte일까?? 당연히 2Byte이다. 그렇다면 C/C++에서 2Byte를 할당 받기 위해선 어떤 형으로 선언해야 될까?? short 형이다. 하지만 이런 이미지 계산에서 -‚는 필요 없으므로 unsigned short형을 쓰게 될 것이다. 이것은 WORD형으로 제 정의 되어 있다. 그래서 WORD형을 쓰게 될 것이다. 결국 1픽셀을 표현하기 위해선 2Byte가 필요하게 되는 샘이다.

 

12.16Bit를 24Bit로 만드는 And연산의 힘
갑자기 16Bit를 24Bit로 바꾼다고 하니까 이상 할 것이다. 왜 16Bit를 24Bit로 변환해야 하는 것일까?? 그 이유는 BMP는 16Bit모드를 지원하지 않기 때문이다. 뭐 되긴 되겠지만....어쨌든 BMP는 4,8,24Bit를 지원하므로 8 또는 24로 변환해서 써야 될 것이다. 8Bit는 팔레트를 짜야 된다. 그렇게 되면 더욱 복잡해지지만 16Bit를 그대로 살리질 못한다. 더 복잡하지만 제대로 살리지도 못한다면 사용할 필요가 없지 않겠는가? 그래서 24Bit로 변환하게 된 것이다.
 그럼 한번 16Bit와 24Bit를 생각해보자 16Bit는 RGB 각각 5:6:5를 사용한다. 24Bit는 RGB 각각 1Byte(8Bit)를 다 사용한다. 그렇다면 우리는 5->8 로 바꾸어 주면 된다는 결론이 나온다. 5를 8로 늘리려면 3이 더 필요하다 이 3은 어떻게 처리를 할까?? 그건 간단하다 0 값으로 매꾸면 되는 것이다.

 

[R][R][R][R] [R][G][G][G] [G][G][G][B] [B][B][B][B] -> 이런걸
[R][R][R][R] [R][0][0][0] <- 이렇게 각각의 RGB를 바꾸어 주면 된다.

비는 부분 만큼 0 값으로 채워주면 되는 것이다. (당연 0값으로 채워지는 부분은 오른쪽에서부터 3까지가 된다)


여기서부터 이 글을 읽고 있는 사람은 의문을 가저야 한다. 어떻게 각각의 RGBBit를 컨트롤 해야 하는 것일까??? 여기서 바로 And연산의 진정한 힘!이 나오는 것이다.
 우리는 16Bit에서 RGB가 어떻게 할당되어 있는지 안다. 또 And연산을 알고 있다. 그렇다면 R값을 뽑아내는건 쉽지 않은가?? 우리는 비트마스킹을 해서 R값을, G값을, B값을 가저와야 한다. 아래부터는 예제를 이용해서 이해를 돕겠다.

 

1101 1001 1100 0011 -> 이런 16Bit가 있다.
1111 1000 0000 0000 -> 상위 5Bit는 R값이 된다. 상위 5Bit만 1로 &연산 시킨다.
-----------------------
1101 1000 0000 0000 -> 최종적으로 뽑혀진 R 값이다.

 

 이렇게 하나씩 뽑아내면 된다. 그런데 여기서 또 문제가 있다.^^;
바로 1111 1000 0000 0000 이 값은 0∼31 범위를 넘는다는게 문제다. 1Byte 범위는
0000 0000 이렇게 8Bit 까지만 이기 때문에 이 범위로 맞추어야 한다. 그래서 우리에게 주어지는 것이 바로 쉬프트이다.
 1101 1001 1100 0011 -> 이 녀석중 상위 5Bit인 1101 1 이걸 하위 1Byte로 주어야 한다.
아님 다 뽑아낸 값을 1Byte로 맞추어 주어도 상관없다. 여기선 먼저 맞춘 후에 비트마스킹 하기로 한다.
 1101 1001 1100 0011 -> 이걸 오른쪽으로 7번 쉬프트 시키면 1Byte 범위 안으로 R 값이 들어오게 된다.
0000 0000 1101 1000 -> 하튼 이런식으로...물론 앞에 0 으로 가득 차는게 아니라 밀려진 값 만큼 앞으로 돌아온다. 다시 말해
 1100 0011 1101 1000 이런식으로 변하는 것이다. 여기서 우리는
0000 0000 1111 1111 이렇게 비트 마스킹 하면 0∼31 범위의 R값을 얻을 수가 있다.
G나 B 값도 이런식으로 밀어서 얻어 오면 된다. 주의 해야 될것이 B 값은 왼쪽으로 옮겨줘야 한다는 것이다.
 1 1000 <- 이런 값을 1100 0000 이렇게 만들어 줘야 하므로 왼쪽으로 밀어주어야 한다는 점과 G는 6Bit를 차지 한다는 점을 잊지 말자.

 

13.포인터 힘과 주의점
C언어에는 포인터가 있다. 이 포인터를 이용하면 굉장히 쉽게 여러 가지를 할 수 있는데 포인터가 없었다면 분명 16Bit를 컨트롤 하는데 힘이 들었을 것이다. 포인터를 이용해서 나는 1Byte형으로 되어 있는 이미지데이터를 먼저 2Byte형으로 바꾸어 줄 것이다. 그리고 나서 위에서 설명했던 비트마스킹을 거처서 최종적으로 24Bit로 만든 것을 전강좌에서 24Bit를 설명한 것처럼 할 것이다. 그럼 이제 소스를 보며 이야기 하겠다.

 

 Image16.Size = imgInfo.Width*3*imgInfo.Height;
 Image16.Data = new BYTE[ Image16.Size ];
 ZeroMemory(Image16.Data,Image16.Size);


가장 먼저 이런 부분을 보고 가야 한다.
Imaeg16.Size 부분을 보자 Width*3*Height 이렇게 Size를 구하고 있다. 첫 강좌에서 분명 Width*2가 Tim 이미지의 실제 데이터 길이라고 했었다. 그런데 *3을 하고 있다. 그 이유는 이 Image16에 저장될 것은 Tim24Bit가 아니라 BMP24Bit라는 점을 알고 있자. 그러니 당연히 가로*3*세로가 맞다. 어째서 3을 곱해야 된다고 묻는다면 처음부터 다시 보길 바란다.

 

 Temp1 = (WORD *)imgInfo.Data;

 

 다음으로 이런 부분이 나오는데, 위에서 설명했다시피 Byte형을 2Byte형으로 읽는다고 했다. 포인터를 이용해서 위와 같이 Temp1으로 Data를 WORD형 포인터로 지정할수 있다.
이게 몬 말인가 정리 해보면 imgInfo.Data는 Byte형으로 데이터를 바라보고 있지만 Temp1은 WORD형으로 봐라 이소리이다. 즉 Temp1은 Data를 WORD형으로 취급하게 된다.

 

 BYTE r,g,b;
 for(i=0; i<imgInfo.Size/2; i++)
 {
  b = (Temp1[i] >> 7) & 0xf8;
  g = (Temp1[i] >>2) & 0xf8;
  r = (Temp1[i] <<3) & 0xf8;

  //R,G,B 값 뽑는데 까지 함
  //24 비트로 다시 바꾸어서 넣어주어야 함

  *(Image16.Data + (i*3) + 2) = r;
  *(Image16.Data + (i*3) + 1) = g;
  *(Image16.Data + (i*3) + 0) = b;
 }


이 부분은 바로 비트마스킹을 하는 부분이다. 바로 위에서 Temp1을 이용해서 WORD형으로 바꾸었다. 그렇다면 XRRRR RGGGGG BBBBB 이렇게 Temp1은 취급하게 되는 것이다. 그럼 여기서 우리는 비트마스킹을 해서 가저오면 된다. 먼저 Temp1을 오른쪽을 7번 밀고 0xf8로 비트마스킹 한다. fc로 비트마스킹 했었는데 fc로 하나 f8로 하나 그게 그거 인 것 같다. g,r도 같은 원리로 비트마스킹 해서 각각에 값을 뽑아낸다.
뽑아낸 값을 bgr 순으로 24bit처럼 넣어준다. 비트마스킹 할때 이미 0∼31 범위의 값으로 쉬프팅 시킨후 마스킹 시켜서 뽑아 냈으므로 자연적이게 r,g,b 각각 1Byte로 만들어 저있다.
이걸 다시 Image16.Data에 넣어주면 Image16.Data는 24Bit형으로 만들어지게 되었다.
이걸 다시 역순정렬 후 출력하거나 저장하거나 하면 되는 것이다. 이건 전강좌에서 이미 다 설명했으니 전강좌를 참고하길 바라며, 이것으로 ConvertBMP(16Bit) 강좌는 마치겠다.

 

- 후 기
원래 저번주 주말에 쓰려고 했는데 중간고사와 자격증 시험등으로 인해서 주말에 제대로 쉬지를 못해서 못썼네요. 2틀 뒤에 소풍이여서 또 그때 쓰면 되겠지 하고 생각했는데 갑작스럽게 정보올림피아드 예선에 나가게 되어서 그거 준비하는 것 때문에 소풍도 못가고, 소풍날 학교에서 오후 6시까지.....그렇게 오늘까지 왔네요. 어제 정보올림피아드 예선을 봤구요. 오늘은 옷사러 쇼핑도 갔다가 좀 늦게 집에 들어 왔고....해서 오늘도 못쓸 것 같다..라 생각했는데 오늘 미루면 다음번에 또 미루게 될 것 같아서, 힘들지만 다음을 위해서 쓰게 되었습니다.^^; 음 그 덕에 Tim합체는 조금 미루게 됬군요;;; 어차피 5월 2째주는 노는 날도 많고 하니까...^^; 그럼 다음 강좌는 4,8을 묵어서 하게 될 것 같습니다.

 

Tim을 분석하고 있는 사람, 하려는 사람, Tim에 대한 실질적인 프로그램 레퍼런스!
나, 다음에 사람을 위해서 강좌는 계속 됩니다.

칼루
나만의 강의 2004. 5. 2. 20:34
,
Powerd by Tistory, designed by criuce
rss