Header

  1. View current page

    개발자를 꿈꾼다

Profile_img_60x60_01
5

흑백 메모리 비트맵과 BitBlt

보통 윈도우에서 그리기를 할 때 메모리 DC(CompatibleDC)와 메모리 Bitmap(CompatibleBitmap)를 사용하여 BitBlt 함수로 드로잉 작업을 한다.

여기서는 BitBlt 함수 개념 정리 내용을 바탕으로 흑백 메모리 비트맵과 BitBlt 함수에 대해서 알아본다.

위의 내용에서 눈여겨 봐 둘 점은 BitBlt 함수는

  • 흑백 비트맵을 칼라 비트맵으로 변환할 때, white bit(1)을 배경색으로 변환하고 black bit(0)을 전경색으로 변환한다. 이 때는 대상 DC의 전경색과 배경색이 사용된다.

라는 점이다. 

 

[참고] 아래의 내용은 메모리 비트맵을 메모리 DC를 인자로 사용하여 생성하였을 경우나 다른 방법으로 메모리 비트맵을 흑백으로 생성했을 경우에 해당한다.

 

메모리 비트맵을 생성하여 CPaintDC에 출력
  1. // WTL OnPaint 코드
     CPaintDC dc( m_hWnd ) ;
  2.  CRect rect ;
     dc.GetClipBox( rect ) ;
     CDC dcMem ;
     dcMem.CreateCompatibleDC( dc ) ;
     CBitmap bitmapMem ;
     bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  // 100x100의 흑색으로 칠해진 흑백 비트맵 생성
     dcMem.SelectBitmap( bitmapMem ) ;
     dc.BitBlt( 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY ) ;

test.bmp      Test1.jpg

[메모리 비트맵]         [출력]

  • 전경색인 흑색으로 채워진 비트맵이 생성된다.

  • 흑백 비트맵(dcMem)을 칼라 비트맵(dc)으로 변환하나(흑백 비트맵의 흰색->칼라 비트맵의 배경색, 흑백 비트맵의 검정색->칼라 비트맵의 전경색) CPaintDC도 기본 배경색이 흰색이고 전경색이 흑색이다.

  • 비트맵 바깥쪽의 흰색 바탕은 윈도우에서 배경색으로 칠해주는 색이다. WM_ERASEBKGND 에서 아무것도 해 주지 않으면 컨토롤의 기본 배경색인 회색 계통의 색이 나타난다.

[참고]

  • atlcrack.h를 사용한 OnPaint 함수는 인자로 CDCHandle이 넘어오는데 이 DC는 아무값도 가지고 있지 않다(NULL). 그래서 사용할 수 없다.
  • WTL 7.5(? 8.0)에서 부터 사용할 수 있는 CMemoryDC는 생성자에서 인자로 넘겨받는 CPaintDC를 가지고 CreateCompatibleBitmap의 인자로 넘겨주므로 흑백이 아닌 screen과 같은 칼라 포맷을 가진 비트맵이 생성된다.

 

메모리 비트맵에 글자 찍기
  1. // WTL OnPaint 코드
     CPaintDC dc( m_hWnd ) ; 
     CRect rect ; 
     dc.GetClipBox( rect ) ; 
     CDC dcMem ; 
     dcMem.CreateCompatibleDC( dc ) ; 
     CBitmap bitmapMem ;
     bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  // 100x100의 흑색으로 칠해진 흑백 비트맵 생성
     dcMem.SelectBitmap( bitmapMem ) ;
     dcMem.TextOut( 0, 0, TEXT("MY TEST") ) ;
     dc.BitBlt( 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY ) ;

test2.bmp      test2.jpg

[메모리 비트맵]         [출력]

  • 메모리 비트맵 생성시 초기에 무조건 전경색인 검정색으로 채워진 비트맵이 생성되고 메모리 DC에 적용한 전경색인 배경색은 그 다음의 그리기 연산을 할 때 적용된다.

  • 글자의 배경이 기본 배경색인 흰색, 글자색이 기본 전경색인 흑색으로 출력된다.

 

CPaintDC의 배경색을 Green으로 변경
  1. // WTL OnPaint 코드
     CPaintDC dc( m_hWnd ) ;
     dc.SetBkColor( RGB(0, 255, 0) ) ;
     CRect rect ;
     dc.GetClipBox( rect ) ;
     CDC dcMem ;
     dcMem.CreateCompatibleDC( dc ) ;
     CBitmap bitmapMem ;
     bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  // 100x100의 흑색으로 칠해진 흑백 비트맵 생성
     dcMem.SelectBitmap( bitmapMem ) ;
     dcMem.TextOut( 0, 0, TEXT("MY TEST") ) ;
     dc.BitBlt( 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY ) ;

test2.bmp      test3.jpg

[메모리 비트맵]         [출력]

  • TextOut 출력시 배경색인 흰색이 CPaintDC의 배경색인 초록색으로 출력된다.

  • TextOut 출력시 전경색인 검정색은 CPaintDC의 전경색인 검정색으로 출력된다.

 

CPaintDC의 전경색을 Red로 변경
  1. // WTL OnPaint 코드
     CPaintDC dc( m_hWnd ) ; 
     dc.SetTextColor( RGB(255, 0, 0) ) ;
     CRect rect ;
     dc.GetClipBox( rect ) ;
     CDC dcMem ;
     dcMem.CreateCompatibleDC( dc ) ;
     CBitmap bitmapMem ;
     bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  // 100x100의 흑색으로 칠해진 흑백 비트맵 생성
     dcMem.SelectBitmap( bitmapMem ) ;
     dcMem.TextOut( 0, 0, TEXT("MY TEST") ) ;
     dc.BitBlt( 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY ) ;

test2.bmp      test4.jpg

[메모리 비트맵]         [출력]

  • TextOut 출력시 전경색인 검정색이 CPaintDC의 전경색인 빨강색으로 출력된다.

  • TextOut 출력시 배경색인 흰색은 CPaintDC의 배경색인 흰색으로 출력된다.

 

CPaintDC의 배경색을 Green으로, 전경색을 Red로 변경
  1. // WTL OnPaint 코드
     CPaintDC dc( m_hWnd ) ; 
     dc.SetBkColor( RGB(0, 255, 0) ) ;
     dc.SetTextColor( RGB(255, 0, 0) ) ;
     CRect rect ;
     dc.GetClipBox( rect ) ;
     CDC dcMem ;
     dcMem.CreateCompatibleDC( dc ) ;
     CBitmap bitmapMem ;
     bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  // 100x100의 흑색으로 칠해진 흑백 비트맵 생성
     dcMem.SelectBitmap( bitmapMem ) ;
     dcMem.TextOut( 0, 0, TEXT("MY TEST") ) ;
     dc.BitBlt( 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY ) ;

test2.bmp      test5.jpg

[메모리 비트맵]         [출력]

  • TextOut 출력시 배경색인 흰색은 CPaintDC의 배경색인 초록색으로 출력된다.

  • TextOut 출력시 전경색인 검정색은 CPaintDC의 전경색인 빨강색으로 출력된다.

 

CPaintDC의 배경색은 Green으로, 전경색을 Red로, 메모리 DC의 배경색을 Black으로, 전경색을 White로 반전
  • 원래 메모리 DC의 배경색이 White이고 전경색이 Black이다
  1. CPaintDC dc( m_hWnd ) ; 
    dc.SetBkColor( RGB(0, 255, 0) ) ;
    dc.SetTextColor( RGB(255, 0, 0) ) ;
    CRect rect ; 
    dc.GetClipBox( rect ) ; 
    CDC dcMem ; 
    dcMem.CreateCompatibleDC( dc ) ; 
    dcMem.SetBkColor( RGB( 0, 0, 0 ) ) ;
    dcMem.SetTextColor( RGB( 255, 255, 255 ) ) ;
    CBitmap bitmapMem ;
    bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  // 100x100의 흑색으로 칠해진 흑백 비트맵 생성
    dcMem.SelectBitmap( bitmapMem ) ;
    dcMem.TextOut( 0, 0, TEXT("MY TEST") ) ;
    dc.BitBlt( 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY ) ;

test1(2).bmp      test6.jpg

[메모리 비트맵]         [출력]

  • 메모리 비트맵 생성시 초기에 무조건 전경색인 검정색으로 채워진 비트맵이 생성되고 메모리 DC에 적용한 전경색인 배경색은 그 다음의 그리기 연산을 할 때 적용된다.

  • 그러므로 전체가 검정색인 비트맵에서 글자를 찍을 때 배경색을 변경된 배경색인 검정색으로 글자색을 변경된 전경색인 흰색으로 찍는다.

  • 이 결과 메모리 비트맵에서 검정색 부분은 대상 DC의 전경색인 빨강색으로, 흰색 부분은 대상 DC의 배경색인 초록색으로 출력된다.

 

CPaintDC의 배경색은 Green, 전경색 Red, 메모리 DC의 전경색과 배경색을 같게
  • 메모리 DC의 전경색, 배경색을 모두 White로
  1. dcMem.SetBkColor( RGB( 255, 255, 255 ) ) ;
  2. dcMem.SetTextColor( RGB( 255, 255, 255 ) ) ;

test1(3).bmp      test7.jpg

[메모리 비트맵]         [출력]

 

  • 메모리 DC의 전경색, 배경색을 모두 Black로
  1. dcMem.SetBkColor( RGB( 0, 0, 0 ) ) ;
  2. dcMem.SetTextColor( RGB( 0, 0, 0 ) ) ;

test1(4).bmp      test8.jpg

[메모리 비트맵]         [출력]

 

메모리 DC의 전경색과 배경색을 흰색과 검정색 이외의 색으로, CPaintDC의 배경색은 Green, 전경색은 Red

여기서 메모리 DC의 전경색 및 배경색을 희색과 검정색 이외의 색으로 지정해 준다면 어떻게 될까?

  •  메모리 DC의 배경색을 RGB(255, 255, 0)으로 지정
  1. // WTL OnPaint 코드
    CPaintDC dc( m_hWnd ) ; 
    COLORREF crBackground = RGB( 0, 255, 0 ) ;
    COLORREF crForeground = RGB( 255, 0, 0 ) ;
    dc.SetBkColor( crBackground ) ;
    dc.SetTextColor( crForeground ) ;
    CRect rect ; 
    dc.GetClipBox( rect ) ; 
    CDC dcMem ; 
    dcMem.CreateCompatibleDC( dc ) ; 
    dcMem.SetBkColor( RGB( 255, 255, 0 ) ) ;
    CBitmap bitmapMem ;
    bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  // 100x100의 흑색으로 칠해진 흑백 비트맵 생성
    dcMem.SelectBitmap( bitmapMem ) ;
    dcMem.TextOut( 0, 0, TEXT("MY TEST") ) ;
    dc.BitBlt( 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY ) ;

test1(5).bmp      test9.jpg

[메모리 비트맵]         [출력]

  • 결과는 배경을 흰색으로 지정했을 때와 같다

  • 즉 RGB(255, 255, 0)은 흰색으로 계산된다.

 

  •  메모리 DC의 배경색을 RGB(128, 127, 127)로 지정
  1. // WTL OnPaint 코드
    CPaintDC dc( m_hWnd ) ; 
    COLORREF crBackground = RGB( 0, 255, 0 ) ;
    COLORREF crForeground = RGB( 255, 0, 0 ) ;
    dc.SetBkColor( crBackground ) ;
    dc.SetTextColor( crForeground ) ;
    CRect rect ; 
    dc.GetClipBox( rect ) ; 
    CDC dcMem ; 
    dcMem.CreateCompatibleDC( dc ) ; 
    dcMem.SetBkColor( RGB( 128, 127, 127 ) ) ;
    CBitmap bitmapMem ;
    bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  // 100x100의 흑색으로 칠해진 흑백 비트맵 생성
    dcMem.SelectBitmap( bitmapMem ) ;
    dcMem.TextOut( 0, 0, TEXT("MY TEST") ) ;
    dc.BitBlt( 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY ) ;

test1(6).bmp      test10.jpg

[메모리 비트맵]         [출력]

  • 결과는 배경을 검정색으로 지정했을 때와 같다

  • 즉 RGB(128, 127, 127)은 검정색으로 계산된다

 

결과를 보면 알겠지만 흰색과 검정색 이외의 색도 결과적으로 흰색과 검정색으로 변환된다.

이는 현재 메모리 DC는 흑백 비트맵을 장착하고 있다. 그 말은 흰색과 검정색만 표현할 수 있다는 말이다.

 

그렇다면 흰색과 검정색으로 변환되는 기준은 무엇일까?

SetBkColor에 들어 갈 수 있는 값은 RGB(0, 0, 0)에서 RGB(255, 255, 255)까지의 값이다. 이 사이의 값들 중에서 RGB(0, 0, 0)에 가까운 값은 RGB(0, 0, 0)인 검정색으로 변환되고 RGB(255, 255, 255)에 가까운 값은 RGB(255, 255, 255)인 흰색으로 변환된다.

기준은 RGB 매크로의 인자인 r, g, b 의 최고값인 255, 255, 255를 합하여 검정색과 흰색 두 색으로만 나뉘어지므로 2를 나눈 값이다.

(255 + 255 + 255) / 2 = 382.5

그런데 소수점은 RGB의 값으로 사용할 수 없으므로 r, g, b의 값을 합한 값이 382 이하이면 검정색을 나타내고 383 이상이면 흰색을 나타낸다.

첫 번째 예는 255 + 255 + 0 = 510 이므로 흰색을 나타내고 두 번째 예는 128 + 127 + 127 = 382 이므로 검정색을 나타낸다.

그럼 RGB(129, 127, 127)의 경우는 어떨까? 이 값은 합이 383이므로 흰색을 나타낼 것이다.

  • 메모리 DC의 배경색을 RGB(129, 127, 127)로 지정
  1. // WTL OnPaint 코드
    CPaintDC dc( m_hWnd ) ; 
    COLORREF crBackground = RGB( 0, 255, 0 ) ;
    COLORREF crForeground = RGB( 255, 0, 0 ) ;
    dc.SetBkColor( crBackground ) ;
    dc.SetTextColor( crForeground ) ;
    CRect rect ; 
    dc.GetClipBox( rect ) ; 
    CDC dcMem ; 
    dcMem.CreateCompatibleDC( dc ) ; 
    dcMem.SetBkColor( RGB( 129, 127, 127 ) ) ;
    CBitmap bitmapMem ;
    bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  // 100x100의 흑색으로 칠해진 흑백 비트맵 생성
    dcMem.SelectBitmap( bitmapMem ) ;
    dcMem.TextOut( 0, 0, TEXT("MY TEST") ) ;
    dc.BitBlt( 0, 0, rect.Width(), rect.Height(), dcMem, 0, 0, SRCCOPY ) ;

test1(7).bmp      test11.jpg

[메모리 비트맵]         [출력]

  • 결과는 예상대로 메모리 비트맵의 배경이 흰색으로 나왔다

  • RGB(255, 128, 0)으로 해도 메모리 비트맵의 배경이 흰색이 된다.

  • RGB(254, 128, 0)으로 했을 경우에는 메모리 비트맵의 배경이 검정색이 된다.

 

결론은 지금껏 보아 왔듯이 다음과 같다.

  • 메모리 DC를 인자로 CreateCompatibleBitmap 함수를 호출하면 검정색으로 채워진 흑백 비트맵이 생성된다.
  • 흑백 비트맵은 당연히 검정색과 흰색만 나타낼 수 있다.
  • BitBlt 함수 사용시 dwRop인자의 영향을 받겠지만 메모리 비트맵의 흰색은 대상 DC의 배경색으로, 검정색으로 대상 DC의 전경색으로 나타난다.

 

칼라 메모리 비트맵을 흑백 메모리 비트맵으로 Bit-Blit할 때의 칼라 변환은 칼라 메모리 비트맵과 BitBlt를 참조해라.

 

Tags

History

Last edited on 08/18/2008 10:49 by 개발자를 꿈꾼다

Comments (0)

You must log in to leave a comment. Please sign in.