티스토리 툴바



2008/10/18 00:48

[Tip] afxsock.h에서의 에러

VS2005에서 플랫폼 SDK를 업데이트 하고 나면 컴파일 잘 되던 프로젝트가 afxsock.h 파일에서 에러를 내면서 컴파일이 안 될 수가 있다.

에러의 내용은 아래와 같다.

  1. 오류 1 error C2065: 'IPPROTO_IPV6' : 선언되지 않은 식별자입니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlsocket.inl 130 
    오류 2 error C2065: 'SOCKADDR_STORAGE' : 선언되지 않은 식별자입니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 381 
    오류 3 error C2146: 구문 오류 : ';'이(가) 'sockAddr' 식별자 앞에 없습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 381 
    오류 4 error C2065: 'sockAddr' : 선언되지 않은 식별자입니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 381 
    오류 5 error C2070: ''unknown-type'': sizeof 피연산자가 잘못되었습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 382 
    오류 6 error C2070: ''unknown-type'': sizeof 피연산자가 잘못되었습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 384 
    오류 7 error C2227: '->sin_port' 왼쪽은 클래스/구조체/공용 구조체/제네릭 형식을 가리켜야 합니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 394 
    오류 8 error C2146: 구문 오류 : ';'이(가) 'sockAddr' 식별자 앞에 없습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 402 
    오류 9 error C2070: ''unknown-type'': sizeof 피연산자가 잘못되었습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 403 
    오류 10 error C2070: ''unknown-type'': sizeof 피연산자가 잘못되었습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 405 
    오류 11 error C2227: '->sin_port' 왼쪽은 클래스/구조체/공용 구조체/제네릭 형식을 가리켜야 합니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 415 
    오류 12 error C2146: 구문 오류 : ';'이(가) 'sockAddr' 식별자 앞에 없습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 423 
    오류 13 error C2070: ''unknown-type'': sizeof 피연산자가 잘못되었습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 424 
    오류 14 error C2070: ''unknown-type'': sizeof 피연산자가 잘못되었습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 426 
    오류 15 error C2227: '->sin_port' 왼쪽은 클래스/구조체/공용 구조체/제네릭 형식을 가리켜야 합니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 436 
    오류 16 error C2146: 구문 오류 : ';'이(가) 'sockAddrSelf' 식별자 앞에 없습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 450 
    오류 17 error C2065: 'sockAddrSelf' : 선언되지 않은 식별자입니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 450 
    오류 18 error C2070: ''unknown-type'': sizeof 피연산자가 잘못되었습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 451 
    오류 19 error C2070: ''unknown-type'': sizeof 피연산자가 잘못되었습니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 453 
    오류 20 error C2228: '.ss_family' 왼쪽에는 클래스/구조체/공용 구조체가 있어야 합니다. C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxsock.h 470 

 

이때는 _WIN32_WINNT 버전을 0x0501 이상으로 설정해 주면 된다.

 

자세한 사항은 Microsoft 고객지원 페이지에서 확인할 수 있다.

이 글은 스프링노트에서 작성되었습니다.

Trackback 0 Comment 0
2008/10/17 23:03

프로그램밍적으로 환경변수 등록하기

C-Runtime Library에 보면 환경 변수를 등록하고 가져오는 함수가 있다.

  1. #include "stdafx.h"
    #include <Windows.h>
    #include <cstdlib>
    int _tmain(int argc, _TCHAR* argv[])
    {
     TCHAR* pEnv = NULL ;
     pEnv = _tgetenv(TEXT("path")) ; // 대소문자 구분없음
     _tprintf(TEXT("%s\r\n\r\n"), pEnv) ;
     
     _tputenv(TEXT("aa=myVal")) ;
     pEnv = _tgetenv(TEXT("AA")) ;
     _tprintf(TEXT("%s\r\n\r\n"), pEnv) ;

     return 0;
    }

이렇게 등록한 환경변수는 프로그램이 실행되는 동안에는 유지되는데 프로그램이 끝나도 환경변수가 유지되도록 하려면 레지스트리를 만지면 된다.

환경 변수들은 레지스트리 경로는 HKEY_CURRENT_USER\Environment 키와 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\Session Manager\Environment 키의 하위 값으로 존재한다.

당연히 HKE_CRRET_UER\nvronmnt 키의 값들은 현재 사용자에 대한 사용자 변수이고 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\Session Manager\Environment 키의 값들은 시스템 변수이다.

 

이 글은 스프링노트에서 작성되었습니다.

Trackback 0 Comment 0
2008/08/18 02:26

BitBlt 개념 정리

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

그래서 이에 대해 개인적으로 정리를 하고자 한다.

BitBlt 함수 정리
  • 메모리 DC는 CreateCompatibleDC를 사용하여 생성할 수 있다.
    • 이렇게 생성한 DC는 더블 버퍼링등에 활용한다.
  • DC의 전경색은 SetTextColor로 변경할 수 있다.
  • DC의 배경색은 SetBkColor로 변경할 수 있다.
  • 메모리 비트맵은 CreateCompatibleBitmap을 사용하여 만들어진다.
  • CreateCompatibleBitmap 함수는 인자로 넘겨지는 DC와 호환되는 비트맵을 생성한다.
    • 인자로 CPaintDC 등이 넘어오면 screen 과 같은 Color Format이 만들어진다.
    • 인자로 CreateCompatibleDC 함수로 생성된 메모리 DC가 넘어오면 흑백 비트맵이 만들어진다.
      • 메모리 DC은 초기에 1-by-1의 흑백 비트맵이 선택된 상태로 생성된다.
      • 이 때 전경색은 흑색(Black)이고 배경색은 흰색(White)이다.
      • 크기를 인자로 주면 그 크기의 메모리 비트맵이 초기 전경색인 흑색으로 채워진(Fill) 상태로 생성된다.
      • CPaintDC 등도 초기 기본 값은 전경색은 흑색이고 배경색은 흰색이다.
  • 메모리 비트맵은 메모리 DC에 선택(SelectObject, SelectBitmap) 한 다음 사용한다.
  • 메모리 비트맵의 이미지를 출력하기 위해선 메모리 DC를 소스 DC인자로 여러 그리기 함수를 호출한다.
  • BitBlt 함수는 다음과 같은 특성을 가진다.
    • 마지막 인자인 dwRop 인자로 여러가지 그리기 모드를 설정할 수 있다.
    • 소스와 대상 DC의 칼라 포맷이 다르다면 이 함수는 소스 칼라 포맷을 대상 칼라 포맷에 맞도록 변환한다. 이때 대상 비트맵(DC가 아닐까)의 전경색과 배경색이 변환에 사용된다.
    • 흑백 비트맵을 칼라 비트맵으로 변환할 때, white bit(1)을 배경색으로 변환하고 black bit(0)을 전경색으로 변환한다. 이 때는 대상 DC의 전경색과 배경색이 사용된다.
    • 칼라 비트맵을 흑백 비트맵으로 변환할 때, 배경색과 일치 하는 픽셀을 white로 그렇지 않은 픽셀을 black로 변환한다. 이 때는 칼라 DC의 전경색과 배경색을 사용한다.

이 글은 스프링노트에서 작성되었습니다.

Trackback 0 Comment 2
2008/08/18 02:16

흑백 메모리 비트맵과 BitBlt

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

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

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

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

라는 점이다.


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

메모리 비트맵을 생성하여 CPaintDC에 출력
// WTL OnPaint 코드
CPaintDC dc( m_hWnd ) ;
CRect rect ;
dc.GetClipBox( rect ) ;
CDC dcMem ;
dcMem.CreateCompatibleDC( dc ) ;
CBitmap bitmapMem ;
// 100x100의 흑색으로 칠해진 흑백 비트맵 생성
bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ; 
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과 같은 칼라 포맷을 가진 비트맵이 생성된다.
메모리 비트맵에 글자 찍기
// WTL OnPaint 코드
CPaintDC dc( m_hWnd ) ;
CRect rect ;
dc.GetClipBox( rect ) ;
CDC dcMem ;
dcMem.CreateCompatibleDC( dc ) ;
CBitmap bitmapMem ;
// 100x100의 흑색으로 칠해진 흑백 비트맵 생성
bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ; 
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으로 변경
// WTL OnPaint 코드
CPaintDC dc( m_hWnd ) ;
dc.SetBkColor( RGB(0, 255, 0) ) ;
CRect rect ;
dc.GetClipBox( rect ) ;
CDC dcMem ;
dcMem.CreateCompatibleDC( dc ) ;
CBitmap bitmapMem ;
// 100x100의 흑색으로 칠해진 흑백 비트맵 생성
bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ; 
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로 변경
// WTL OnPaint 코드
CPaintDC dc( m_hWnd ) ;
dc.SetTextColor( RGB(255, 0, 0) ) ;
CRect rect ;
dc.GetClipBox( rect ) ;
CDC dcMem ;
dcMem.CreateCompatibleDC( dc ) ;
CBitmap bitmapMem ;
// 100x100의 흑색으로 칠해진 흑백 비트맵 생성
 bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  
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로 변경
// 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 ;
// 100x100의 흑색으로 칠해진 흑백 비트맵 생성
bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ;  
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이다
// 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 ) ;
dcMem.SetBkColor( RGB( 0, 0, 0 ) ) ;
dcMem.SetTextColor( RGB( 255, 255, 255 ) ) ;
CBitmap bitmapMem ;
// 100x100의 흑색으로 칠해진 흑백 비트맵 생성
bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ; 
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로
dcMem.SetBkColor( RGB( 255, 255, 255 ) ) ;
dcMem.SetTextColor( RGB( 255, 255, 255 ) ) ;

test1(3).bmp      test7.jpg

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


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

test1(4).bmp      test8.jpg

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


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

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

  •  메모리 DC의 배경색을 RGB(255, 255, 0)으로 지정
// 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 ;
// 100x100의 흑색으로 칠해진 흑백 비트맵 생성
bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ; 
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)로 지정
// 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 ;
// 100x100의 흑색으로 칠해진 흑백 비트맵 생성
bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ; 
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)로 지정
// 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 ;
// 100x100의 흑색으로 칠해진 흑백 비트맵 생성
bitmapMem.CreateCompatibleBitmap( dcMem, 100, 100 ) ; 
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를 참조해라.


이 글은 스프링노트에서 작성되었습니다.

Trackback 0 Comment 0
2008/08/18 02:14

칼라 메모리 비트맵과 BitBlt

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

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

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

  • 칼라 비트맵을 흑백 비트맵으로 변환할 때, 배경색과 일치 하는 픽셀을 white로 그렇지 않은 픽셀을 black로 변환한다. 이 때는 칼라 DC의 전경색과 배경색을 사용한다.

라는 점이다.


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

칼라 메모리 비트맵을 생성하여 CPaintDC에 출력
// 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 dcMemColor ;
// dcMemColor의 배경색과 전경색은 초기 생성시
// dc의 배경색 및 전경색과 상관없이 배경:RGB(0, 0, 0), 전경:RGB(255, 255, 255)이다.
dcMemColor.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemColor ;
// 비메모리 DC 전달, 검정색으로 채워진 칼라비트맵 생성
// CPaintDC인 dc와 같은 칼라 포맷을 가진 칼라 비트맵 생성
bitmapMemColor.CreateCompatibleBitmap( dc, 100, 100 ) ;
CBitmapHandle bitmapOldColor = dcMemColor.SelectBitmap( bitmapMemColor ) ;
// CPaintDC와 같은 칼라 포맷을 가진 칼라 메모리 비트맵을 사용하므로 칼라가 그대로 적용된다.
dc.BitBlt( 0, 0, 100, 100, dcMemColor, 0, 0, SRCCOPY ) ;
dcMemColor.SelectBitmap( bitmapOldColor ) ;

color.bmp         color1.jpg

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

  • 칼라 메모리 비트맵이라도 처음에는 검정색(기본 전경색)으로 채워진 메모리 비트맵이 생성된다.

  • 칼라 메모리 비트맵을 칼라 비트맵(CPaintDC에 기본으로 장착된)에 나타내므로 색상 변환이 없다.

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


칼라 메모리 비트맵을 생성하여 글자 출력
// 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 dcMemColor ;
// dcMemColor의 배경색과 전경색은 초기 생성시
// dc의 배경색 및 전경색과 상관없이 배경:RGB(0, 0, 0), 전경:RGB(255, 255, 255)이다.
dcMemColor.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemColor ;
// 비메모리 DC 전달, 검정색으로 채워진 칼라비트맵 생성
// CPaintDC인 dc와 같은 칼라 포맷을 가진 칼라 비트맵 생성
bitmapMemColor.CreateCompatibleBitmap( dc, 100, 100 ) ;
CBitmapHandle bitmapOldColor = dcMemColor.SelectBitmap( bitmapMemColor ) ;
dcMemColor.TextOut( 0, 0, TEXT("MY TEST") ) ;
// CPaintDC와 같은 칼라 포맷을 가진 칼라 메모리 비트맵을 사용하므로 칼라가 그대로 적용된다.
dc.BitBlt( 0, 0, 100, 100, dcMemColor, 0, 0, SRCCOPY ) ;
dcMemColor.SelectBitmap( bitmapOldColor ) ;

color(1).bmp         color2.jpg

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

  • 칼라 메모리 비트맵이라도 초기 전경색은 검정색인 RGB(0, 0, 0), 배경색은 흰색인 RGB(255, 255, 255)의 값을 가진다.

  • 칼라 메모리 비트맵을 칼라 비트맵(CPaintDC에 기본으로 장착된)에 나타내므로 색상 변환이 없다.(참조: 흑백 메모리 비트맵과 BitBlt)


칼라 메모리 비트맵의 전경색을 흰색으로 배경색을 검정색으로 치환
// 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 dcMemColor ;
// dcMemColor의 배경색과 전경색은 초기 생성시
// dc의 배경색 및 전경색과 상관없이 배경:RGB(0, 0, 0), 전경:RGB(255, 255, 255)이다.
dcMemColor.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemColor ;
// 비메모리 DC 전달, 검정색으로 채워진 칼라비트맵 생성
// CPaintDC인 dc와 같은 칼라 포맷을 가진 칼라 비트맵 생성
bitmapMemColor.CreateCompatibleBitmap( dc, 100, 100 ) ;
CBitmapHandle bitmapOldColor = dcMemColor.SelectBitmap( bitmapMemColor ) ;

dcMemColor.SetBkColor( RGB( 0, 0, 0 ) ) ;

dcMemColor.SetTextColor( RGB( 255, 255, 255 ) ) ;
dcMemColor.TextOut( 0, 0, TEXT("MY TEST") ) ;
// CPaintDC와 같은 칼라 포맷을 가진 칼라 메모리 비트맵을 사용하므로 칼라가 그대로 적용된다.
dc.BitBlt( 0, 0, 100, 100, dcMemColor, 0, 0, SRCCOPY ) ;
dcMemColor.SelectBitmap( bitmapOldColor ) ;

 

color(2).bmp         color3.jpg

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

  • 기본 검정색으로 채워진 칼라 비트맵이 생성되고 변경된 배경색과 전경색은 변경 후 호출하는 gdi 함수에 의해 사용된다.

  • 칼라 메모리 비트맵을 칼라 비트맵(CPaintDC에 기본으로 장착된)에 나타내므로 색상 변환이 없다.(참조: 흑백 메모리 비트맵과 BitBlt)


칼라 메모리 비트맵의 배경색을 Blue, 전경색을 RGB(255, 0, 255)로 변경
// 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 dcMemColor ;
// dcMemColor의 배경색과 전경색은 초기 생성시
// dc의 배경색 및 전경색과 상관없이 배경:RGB(0, 0, 0), 전경:RGB(255, 255, 255)이다.
dcMemColor.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemColor ;
// 비메모리 DC 전달, 검정색으로 채워진 칼라비트맵 생성
// CPaintDC인 dc와 같은 칼라 포맷을 가진 칼라 비트맵 생성
bitmapMemColor.CreateCompatibleBitmap( dc, 100, 100 ) ;
CBitmapHandle bitmapOldColor = dcMemColor.SelectBitmap( bitmapMemColor ) ;

dcMemColor.SetBkColor( RGB( 0, 0, 255 ) ) ;

dcMemColor.SetTextColor( RGB( 0, 0, 255 ) ) ;
dcMemColor.TextOut( 0, 0, TEXT("MY TEST") ) ;
// CPaintDC와 같은 칼라 포맷을 가진 칼라 메모리 비트맵을 사용하므로 칼라가 그대로 적용된다.
dc.BitBlt( 0, 0, 100, 100, dcMemColor, 0, 0, SRCCOPY ) ;
dcMemColor.SelectBitmap( bitmapOldColor ) ;

color(4).bmp         color5.jpg

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

  • 변경된 배경색, 전경색들이 메모리 비트맵에도 출력에도 그대로 나타난다.

  • 흑백 비트맵을 출력할 때와 같은 칼라 변환은 일어나지 않는다.


칼라 메모리 비트맵의 배경색을 Blue, 전경색을 RGB(255, 0, 255)로 변경하여 텍스트 출력
// 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 dcMemColor ;
// dcMemColor의 배경색과 전경색은 초기 생성시
// dc의 배경색 및 전경색과 상관없이 배경:RGB(0, 0, 0), 전경:RGB(255, 255, 255)이다.
dcMemColor.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemColor ;
// 비메모리 DC 전달, 검정색으로 채워진 칼라비트맵 생성
// CPaintDC인 dc와 같은 칼라 포맷을 가진 칼라 비트맵 생성
bitmapMemColor.CreateCompatibleBitmap( dc, 100, 100 ) ;
CBitmapHandle bitmapOldColor = dcMemColor.SelectBitmap( bitmapMemColor ) ;
dcMemColor.SetBkColor( RGB( 0, 0, 255 ) ) ;
dcMemColor.SetTextColor( RGB( 0, 0, 255 ) ) ;
dcMemColor.TextOut( 0, 0, TEXT("MY TEST") ) ;
// CPaintDC와 같은 칼라 포맷을 가진 칼라 메모리 비트맵을 사용하므로 칼라가 그대로 적용된다.
dc.BitBlt( 0, 0, 100, 100, dcMemColor, 0, 0, SRCCOPY ) ;
dc.TextOut( 0, 15, TEXT("PaintDC") ) ;
dcMemColor.SelectBitmap( bitmapOldColor ) ;

color(5).bmp         color6.jpg

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

  • 칼라 메모리 비트맵의 색상도 변경없이 출력되고 Paint DC 에서 출력한 내용도 Paint DC에서 설정한 전경색, 배경색 대로 출력된다.


칼라 비트맵을 흑백 비트맵으로 출력
// 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 dcMemColor ;
// dcMemColor의 배경색과 전경색은 초기 생성시
// dc의 배경색 및 전경색과 상관없이 배경:RGB(0, 0, 0), 전경:RGB(255, 255, 255)이다.
dcMemColor.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemColor ;
// 비메모리 DC 전달, 검정색으로 채워진 칼라비트맵 생성
// CPaintDC인 dc와 같은 칼라 포맷을 가진 칼라 비트맵 생성
bitmapMemColor.CreateCompatibleBitmap( dc, 100, 100 ) ;
CBitmapHandle bitmapOldColor = dcMemColor.SelectBitmap( bitmapMemColor ) ;
dcMemColor.SetBkColor( RGB( 0, 0, 255 ) ) ;
dcMemColor.SetTextColor( RGB( 0, 0, 255 ) ) ;
dcMemColor.TextOut( 0, 0, TEXT("MY TEST") ) ;

CDC dcMemMono ;
dcMemMono.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemMono ;
// 모노 칼라(흑백) 비트맵 생성
bitmapMemMono.CreateCompatibleBitmap( dcMemMono, 100, 100 ) ;
CBitmapHandle bitmapOldMono = dcMemMono.SelectBitmap( bitmapMemMono ) ;
// 칼라 비트맵을 흑백 비트맵으로 변환할 때,
// 배경색과 일치 하는 픽셀을 white로 그렇지 않은 픽셀을 black로 변환한다.
// 이 때는 칼라 DC의 전경색과 배경색을 사용한다
dcMemMono.BitBlt( 0, 0, 100, 100, dcMemColor, 0, 0, SRCCOPY ) ;


// 칼라 비트맵을 bit-blit한 흑백 비트맵을 CPaintDC에 출력

dc.BitBlt( 0, 0, 100, 100, dcMemMono, 0, 0, SRCCOPY ) ;
dc.TextOut( 0, 15, TEXT("PaintDC") ) ;

dcMemColor.SelectBitmap( bitmapOldColor ) ;
dcMemMono.SelectBitmap( bitmapOldMono ) ;

color(6).bmp         mono.bmp         color8.jpg

[칼라 메모리비트맵]      [흑백 메모리비트맵]      [출력]

  • 처음에 언급한 "칼라 비트맵을 흑백 비트맵으로 변환할 때, 배경색과 일치 하는 픽셀을 white로 그렇지 않은 픽셀을 black로 변환한다. 이 때는 칼라 DC의 전경색과 배경색을 사용한다."라는 내용의 결과를 볼 수 있다.

  • 처음에 칼라 비트맵은 설정한 대로 잘 나타난다.

  • 두 번째 칼라 비트맵을 흑백 비트맵으로 출력할 때 칼라 DC의 배경색과 일치하는 파랑색은 흑백 비트맵에서 흰색으로 그렇지 않은 색들은 검정색으로 나타난다.

  • 흑백 메모리 비트맵을 다시 칼라 DC인 Paint DC로 출력할 때는 흑백 메모리 비트맵과 BitBlt에서 설명한 "흑백 비트맵을 칼라 비트맵으로 변환할 때, white bit(1)을 배경색으로 변환하고 black bit(0)을 전경색으로 변환한다. 이 때는 대상 DC의 전경색과 배경색이 사용된다"는 원칙에 따라서 흰색 부분은 Paint DC의 배경색인 RGB( 0, 255, 0 )로 나타나고 검은 부분은 Paint DC의 전경색인 RGB( 255, 0, 0 )로 나타난다.


칼라 비트맵을 흑백 비트맵으로 출력, 흑백 비트맵의 전경색을 White, 배경색을 Black로 변경
// 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 dcMemColor ;
// dcMemColor의 배경색과 전경색은 초기 생성시
// dc의 배경색 및 전경색과 상관없이 배경:RGB(0, 0, 0), 전경:RGB(255, 255, 255)이다.
dcMemColor.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemColor ;
// 비메모리 DC 전달, 검정색으로 채워진 칼라비트맵 생성
// CPaintDC인 dc와 같은 칼라 포맷을 가진 칼라 비트맵 생성
bitmapMemColor.CreateCompatibleBitmap( dc, 100, 100 ) ;
CBitmapHandle bitmapOldColor = dcMemColor.SelectBitmap( bitmapMemColor ) ;
dcMemColor.SetBkColor( RGB( 0, 0, 255 ) ) ;
dcMemColor.SetTextColor( RGB( 0, 0, 255 ) ) ;
dcMemColor.TextOut( 0, 0, TEXT("MY TEST") ) ;

CDC dcMemMono ;
dcMemMono.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemMono ;
// 모노 칼라(흑백) 비트맵 생성
bitmapMemMono.CreateCompatibleBitmap( dcMemMono, 100, 100 ) ;
CBitmapHandle bitmapOldMono = dcMemMono.SelectBitmap( bitmapMemMono ) ;
// 흑백 비트맵의 배경색을 검정색으로, 전경색을 흰색으로 바꾼다.
dcMemMono.SetBkColor( RGB( 0, 0, 0 ) ) ;
dcMemMono.SetTextColor( RGB( 255, 255, 255 ) ) ;
// 칼라 비트맵을 흑백 비트맵으로 변환할 때,
// 배경색과 일치 하는 픽셀을 white로 그렇지 않은 픽셀을 black로 변환한다.
// 이 때는 칼라 DC의 전경색과 배경색을 사용한다
dcMemMono.BitBlt( 0, 0, 100, 100, dcMemColor, 0, 0, SRCCOPY ) ;

// 칼라 비트맵을 bit-blit한 흑백 비트맵을 CPaintDC에 출력

dc.BitBlt( 0, 0, 100, 100, dcMemMono, 0, 0, SRCCOPY ) ;
dc.TextOut( 0, 15, TEXT("PaintDC") ) ;

dcMemColor.SelectBitmap( bitmapOldColor ) ;
dcMemMono.SelectBitmap( bitmapOldMono ) ;

color(7).bmp         mono(1).bmp         color9.jpg

[칼라 메모리비트맵]      [흑백 메모리비트맵]      [출력]

  • 흑백 메모리 비트맵의 전경색과 배경색을 바꿔 줬으나 바꾸지 않았을 때와 같은 결과이다.

  • 이것은 칼라 비트맵에서 흑백 비트맵으로 bit-blit 할 때 흑백 비트맵의 전경색과 배경색이 아무런 영향을 끼치지 않는다는 것을 나타낸다.

  • 결국 칼라 비트맵을 흑백 비트맵으로 변환 할 때나 흑백 비트맵을 칼라 비트맵으로 전환할 때 흑백 비트맵의 전경색과 배경색이 무슨 색이냐하는 것은 칼라 변환 자체에는 영향을 끼치지 않는다. 흑백 비트맵의 어떤 부분인 흰 부분인가 검은 부분인가 하는 문제와 칼라 비트맵의 전경색과 배경색이 무엇인가 하는 것만이 칼라 변환에 영향을 끼친다.


 흑백 메모리 DC의 전경색과 배경색을 바꾸고 텍스트 출력
// 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 dcMemColor ;
// dcMemColor의 배경색과 전경색은 초기 생성시
// dc의 배경색 및 전경색과 상관없이 배경:RGB(0, 0, 0), 전경:RGB(255, 255, 255)이다.
dcMemColor.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemColor ;
// 비메모리 DC 전달, 검정색으로 채워진 칼라비트맵 생성
// CPaintDC인 dc와 같은 칼라 포맷을 가진 칼라 비트맵 생성
bitmapMemColor.CreateCompatibleBitmap( dc, 100, 100 ) ;
CBitmapHandle bitmapOldColor = dcMemColor.SelectBitmap( bitmapMemColor ) ;
dcMemColor.SetBkColor( RGB( 0, 0, 255 ) ) ;
dcMemColor.SetTextColor( RGB( 0, 0, 255 ) ) ;
dcMemColor.TextOut( 0, 0, TEXT("MY TEST") ) ;

CDC dcMemMono ;
dcMemMono.CreateCompatibleDC( dc ) ;
CBitmap bitmapMemMono ;
// 모노 칼라(흑백) 비트맵 생성
bitmapMemMono.CreateCompatibleBitmap( dcMemMono, 100, 100 ) ;
CBitmapHandle bitmapOldMono = dcMemMono.SelectBitmap( bitmapMemMono ) ;
// 흑백 비트맵의 배경색을 검정색으로, 전경색을 흰색으로 바꾼다.
dcMemMono.SetBkColor( RGB( 0, 0, 0 ) ) ;
dcMemMono.SetTextColor( RGB( 255, 255, 255 ) ) ;
// 칼라 비트맵을 흑백 비트맵으로 변환할 때,
// 배경색과 일치 하는 픽셀을 white로 그렇지 않은 픽셀을 black로 변환한다.
// 이 때는 칼라 DC의 전경색과 배경색을 사용한다
dcMemMono.BitBlt( 0, 0, 100, 100, dcMemColor, 0, 0, SRCCOPY ) ;
dcMemMono.BitBlt( 0, 30, TEXT("Mono") ) ;

// 칼라 비트맵을 bit-blit한 흑백 비트맵을 CPaintDC에 출력

dc.BitBlt( 0, 0, 100, 100, dcMemMono, 0, 0, SRCCOPY ) ;
dc.TextOut( 0, 15, TEXT("PaintDC") ) ;

dcMemColor.SelectBitmap( bitmapOldColor ) ;
dcMemMono.SelectBitmap( bitmapOldMono ) ;

color(8).bmp         mono(2).bmp         color10.jpg

[칼라 메모리비트맵]      [흑백 메모리비트맵]      [출력]

  • 위에서 살펴본 봐야 같이 흑백 비트맵의 흰 부분인가 검은 부분이가 하는 문제와 칼라 비트맵의 전경색과 배경색 만이 영향을 끼친다.


이상의 내용을 정리하면 다음과 같다.

  • 칼라 비트맵을 흑백 비트맵으로 변환할 때, 배경색과 일치 하는 픽셀을 white로 그렇지 않은 픽셀을 black로 변환한다. 이 때는 칼라 DC의 전경색과 배경색을 사용한다.
  • 흑백 비트맵을 칼라 비트맵으로 변환할 때, white bit(1)을 배경색으로 변환하고 black bit(0)을 전경색으로 변환한다. 이 때는 대상 DC의 전경색과 배경색이 사용된다.
  • 결국 칼라 비트맵을 흑백 비트맵으로 변환 할 때나 흑백 비트맵을 칼라 비트맵으로 전환할 때 흑백 비트맵의 전경색과 배경색이 무슨 색이냐하는 것은 칼라 변환 자체에는 영향을 끼치지 않는다. 흑백 비트맵의 어떤 부분인 흰 부분인가 검은 부분인가 하는 문제와 칼라 비트맵의 전경색과 배경색이 무엇인가 하는 것만이 칼라 변환에 영향을 끼친다.

[참조] 흑백 비트맵과 BitBlt

이 글은 스프링노트에서 작성되었습니다.

Trackback 0 Comment 0
2008/08/18 02:13

BitBlt

BOOL BitBlt (HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop)
  • 인자

    • hdcDest

      • 목적지의 DC 핸들
    • nXDest

      • 목적지의 좌상을 기준으로 한 x 좌표(논리 단위)
    • nYDest

      • 목적지의 좌상을 기준으로 한 y 좌표(논리 단위)
    • nWidth

      • 소스와 목적지의 너비(논리 단위)
    • nHeight

      • 소스와 목적지의 높이(논리 단위)
    • hdcSrc

      • 소스의 DC 핸들
    • nXSrc

      • 소스의 좌상을 기준으로 한 x 좌표(논리 단위)
    • nYSrc

      • 소스의 좌상을 기준으로 한 y 좌표(논리 단위)
    • dwRop

      • 래스트 연산 코드
      • 최종 칼라를 얻기 위해 소스 영역의 칼라가 목적지 영역의 칼라와 어떻게 결합할 것인지를 결정하는 코드
      1. BLACKNESS

        • 0x00000042
        • 물리 팔레트의 인덱스 0에 해당하는 색(디폴트는 검정색)으로 목적지의 사각 영역을 채운다.
      2. CAPTUREBLT
      3. 0x40000000
      4. 사용자 창 위에 놓인 창들이 생성되는 이미지에 포함된다. 기본적으로 이미지에는 사용자 창만 포함된다. 이것은 인쇄 장치 컨텍스트에는 대개 사용할 수 없다.
      5. DSTINVERT

        • 0x0050009
        • 목적지 영역의 색을 반전한다.
      6. MERGECOPY

        • 0x00C000CA
        • 소스 영역의 색이 Boolean AND 연산자를 사용하여 대상 장치 컨텍스트의 선택된 브러시 색과 병합된다.
      7. MERGEPAINT

        • 0x00BB0226
        • 반전된 소스 영역의 색이 Boolean OR 연산자를 사용하여 대상 영역의 색과 병합된다.
      8. NOMIRRORBITMAP
      9. 0x80000000
      10. 비트맵이 미러링되지 않는다.
      11. NOTSRCCOPY

        • 0x00330008
        • 반전된 소스 영역이 대상에 복사된다.
      12. NOTSRCERASE

        • 0x001100A6
        • 소스 및 대상 색이 Boolean OR 연산자를 사용하여 결합된 다음 생성된 색이 반전된다.
      13. PATCOPY

        • 0x00F00021
        • 대상 장치 컨텍스트에서 현재 선택된 브러시가 대상 비트맵에 복사된다.
      14. PATINVERT
        • 0x005A0049
        • 대상 장치 컨텍스트에서 현재 선택된 브러시 색이 Boolean XOR 연산자를 사용하여 대상 색과 결합된다.
      15. PATPAINT
      16. 0x00FB0A09
      17. 대상 장치 컨텍스트에서 현재 선택된 브러시 색이 Boolean OR 연산자에 의해 반전된 소스 영역의 색과 결합된다. 이 연산의 결과는 Boolean OR 연산자를 사용하여 대상 영역의 색과 결합된다.
      18. SRCAND

        • 0x008800C6
        • 소스 및 대상 영역의 색이 Boolean AND 연산자를 사용하여 결합된다.
      19. SRCCOPY

        • 0x00CC0020
        • 소스 영역이 직접 대상 영역에 복사된다.
      20. SRCERASE

        • 0x00440328
        • 대상 영역의 반전된 색이 Boolean AND 연산자를 사용하여 소스 영역의 색과 결합된다.
      21. SRCINVERT

        • 0x00660046
        • 소스 및 대상 영역의 색이 Boolean XOR 연산자를 사용하여 결합된다.
      22. SRCPAINT

        • 0x00EE0086
        • 소스 및 대상 영역의 색이 Boolean OR 연산자를 사용하여 결합된다.
      23. WHITENESS

        • 0x00FF0062
        • 물리 팔레트의 인덱스 1에 해당하는 색 (디폴트는 흰색)을 사용하여 대상 영역을 채운다.

       

  • 반환값

    • 성공하면 0 이외의 값
    • 실패하면 0
  • 설명

    • 소스 디바이스 컨텍스트로부터 대상 디바이스 컨텍스트에 지정된 영역의 픽셀의 칼라 데이터의 비트 블록 전송을 수행한다.
    • 오직 대상 DC에 클리핑을 한다.
    • 소스 DC에 깍기나 회전 등의 변환이 있다면 이 함수는 에러를 리턴한다. 소스 DC에 다른 변환이 있다면 (그리고 매치되는 변환이 대상 DC에 없다면) 대상 DC의 영역은 필요에 따라서 늘어나거나 압축되거나 회전되거나 한다.
    • 소스와 대상 DC의 칼라 포맷이 다르다면 이 함수는 소스 칼라 포맷을 대상 칼라 포맷에 맞도록 변환한다. 이때 대상 비트맵(DC가 아닐까)의 전경색과 배경색이 변환에 사용된다.
    • 흑백 비트맵을 칼라 비트맵으로 변환할 때, white bit(1)을 배경색으로 변환하고 black bit(0)을 전경색으로 변환한다. 이 때는 대상 DC의 전경색과 배경색이 사용된다.
    • 칼라 비트맵을 흑백 비트맵으로 변환할 때, 배경색과 일치 하는 픽셀을 white로 그렇지 않은 픽셀을 black로 변환한다. 이 때는 칼라 DC의 전경색과 배경색을 사용한다.
    • Enhanced Metafile 이 기록되고 있을 때 소스 DC가 Enhanced-Metafile DC라면 에러가 발생한다.
    • 모든 디바이스가 이 함수를 지원하지는 않는다. 보다 많은 정보는 MaskBlt, PlgBltStretchBlt 를 사용할 때처럼 GetDeviceCaps 함수의 RC_BITBLT raster capability 요소로 확인할 수 있다.
    • 이 함수는 소스와 대상 디바이스 컨텍스트가 다른 디바이스를(호환되지 않는) 나타낸다면 에러를 리턴한다. 다른 디바이스들의 DC 간 데이터 전송을 위해서는 메모리 비트맵을 GetDIBits 를 호출하여 DIB로 변환해야한다. DIB를 두번째 디바이스에 디스플레이하기 위해서는 SetDIBitsStretchDIBits를 호출해야 한다.
    • blit 이 발생할 때 칼라 매니지먼트는 실행되지 않는다.

이 글은 스프링노트에서 작성되었습니다.

Trackback 0 Comment 0
2008/08/18 02:13

CreateCompatibleBitmap

HBITMAP CreateCompatibleBitmap (HDC hdc, int nWidth, int nHeight)
  •  인자

    • hdc

      • DC의 핸들.
      • 이 DC와 호환하는 비트맵을 작성한다.
    • nWidth

      • 작성하는 비트맵의 가로 사이즈(픽셀 단위)
    • nHeight

      • 작성하는 비트맵의 세로 사이즈(픽셀 단위)
  • 반환값

    • 성공하면 호환되는(DDB) 비트맵의 핸들
    • 실패하면 NULL
  • 설명

    • 인자로 주어진 DC에 호환하는 비트맵을 생성하여 반환한다.
    • 생성되는 비트맵의 칼라 포맷(색형식)은 hdc 인자의 칼라 포맷과 같다. 생성된 비트맵은 hdc와 호환되는 어떤 메모리 DC에서도 선택되어 질 수 있다.
    • 메모리 DC는 칼라와 흑백 비트맵 둘다 취할 수 있기 때문에 인자로 지정된 DC가 메모리 DC일 때 생성되어 리턴되는 비트맵의 포맷은 다르다.
    • 하지만 메모리 DC가 아닌 DC(비메모리 DC - nonmenory device context)에 의해 생성되는 호환 비트맵은 항상 주어진 인자 DC와 같은 칼라 포맷을 가지고 같은 칼라 팔레트를 사용한다.

      • 메모리 DC가 생성되었을 때 메모리 DC는 처음에 1x1 흑백 비트맵을 선택하고 있다(배경색이 White(255, 255, 255)이고 전경색이 Black(0, 0, 0)). 만약 이 메모리 DC가 CreateCompatibleBitmap 함수에 사용되어 진다면 생성되는 비트맵은 흑백 비트맵이다. 칼라 비트맵을 생성하기 위해서는 이 메모리 DC를 생성할 때 사용된 hDC를 사용해야한다.
      1. HDC memDC = ::CreateCompatibleDC ( hDC ) ;
      2. HBITMAP memBM = ::CreateCompatibleBitmap ( hDC, nWidth, nHeight ) ;
      3. SelectObject ( memDC, memBM ) ;
    • 만약 어플리케이션이 nWidth나 nHeight를 0으로 지정한다면 이 함수는 1x1(1-by-1) 픽셀의 흑백 비트맵의 핸들을 리턴한다.
    • CreateDIBSection 함수로 생성된 DIB section이 hdc인자의 DC에 선택되어져 있다면 이 함수는 DIB section을 생성한다.
    • 비트맵이 더 이상 필요하지 않다면 DeleteObject를 호출하여 비트맵을 지워야 한다.
    • Windows 95/98/Me에서는 16MB을 넘는 사이즈의 비트맵은 생성할 수 없다.

이 글은 스프링노트에서 작성되었습니다.

Trackback 0 Comment 0
2008/08/18 02:12

CreateCompatibleDC

HDC CreateCompatibleDC (HDC hDC)
  •  인자

    • hDC

      • 기존의 디바이스 컨텍스트(DC)의 핸들
      • 이 DC에 관련하는 디바이스와 호환성 있는 메모리 디바이스 컨텍스트 생성
      • NULL을 지정하면 어플리케이션의 현재의 스크린과 호환성 있는 메모리 디바이스 컨텍스트 생성
  • 반환값

    • 성공하면 작성한 메모리 DC의 핸들
    • 실패하면 NULL
  •  설명

    • 이 함수는 인자로 주어진 디바이스에 호환되는 메모리 디바이스 컨텍스트를 생성하여 반환한다.
    • 메모리 DC가 생성되면 이 메모리 DC의 표면(surface)은 1x1 픽셀의 흑백이다(1x1 픽셀의 흑백 비트맵이 선택된 상태가 되어 있다).

      • 처음 생성시 배경색(BkColor)이 White(255, 255, 255)이고 전경색(TextColor)이 Black(0, 0, 0)이다.
      • 처음 표면은 전경색(검정색)으로 채워진다.
      • 표면의 배경색 및 전경색은 SetBkColorSetTextColor로 변경가능하다.
      • CPaintDC 등도 처음 생성하면 배경색은 White이고 전경색은 Black이다.
    • 어플리케이션은 드로잉 작업을 위해 메모리 DC를 사용하기 전에 올바른 사이즈의 비트맵을 DC에 선택(select)해야 한다. DC에 비트맵을 선택하기 위해서 필요한 사이즈와 칼라를 지정하여 CreateCompatibleBitmap 함수를 사용해라.
    • 메모리 DC가 생성되면 모든 속성들은 기본 값이 설정된다. 메모리 DC는 일반 DC처럼 사용될 수 있다. 특정 속성을 다른 값으로 지정할 수도 있고 현재 속성들로부터 값을 얻을 수도 있고 펜, 브러쉬, 영역 등을 선택할 수도 있다.
    • CreateCompatibleDC 함수는 오직 래스터(raster) 연산을 지원하는 디바이스와 사용될 수 있다. 어플리케이션은 디바이스가 GetDeviceCaps 함수를 호출함으로써 래스터 연산을 지원하는지 여부를 확인할 수 있다.
      메모리 DC가 더 이상 필요하지 않을 땐 DeleteDC 함수를 호출해야 한다.
    • Windows 2000 이후부터는 스레드에서 hDC인자를 NULL로 CreateCompatibleDC를 호출하면 그 스레드에 종속적인 HDC를 생성하여 넘겨준다. 스레드가 종료되면 넘겨받은 HDC는 더 이상 유효하지 않다. 그래서 어떤 스레드에서 HDC를 생성하고 다른 스레드로 넘겨주고 스레드가 종료된다면 다른 스레드에서 넘겨받은 HDC를 사용할 수 없다.
    •  인자로 넘겨지는 DC가 Image Color Management(ICM)에 대해 가능하다면, 리턴값으로 받는 DC도 ICM-enabled 이다. 소스와 목적지 칼라 공간은 DC에서 열거된다.

 

이 글은 스프링노트에서 작성되었습니다.

Trackback 0 Comment 0
2008/06/02 21:31

촛불 문화제 강경진압 1

있어서는 안되는 일들이 일어나고 있네요.
Trackback 0 Comment 0
2008/03/31 12:04

HEAP CORRUPTION DETECTED

프로그램을 짜다 보면 HEAP CORRUPTION DETECTED 에러를 만날 수 있다.
이것은 할당한 데로 해제 하지 못했을 경우에 나타나는 에러로 나 같은 경우에는 할당한 이상으로 해제를 한 경우에 나타났다.
COM 작성시 문자열을 다루는데 경우에 주의해야 할 점 중의 하나로
CComBSTR의 인스턴스의 Length()를 사용하여 문자열의 길이를 얻고 이를 Muiti-Bytes로 변환하는 과정에서 에러가 생긴 것이다.
CComBSTR.Length()는 Unicode로 각 문자(영문,한글)을 하나로 취급하여 길이를 반환하는데
이를 받아서 문자열의 길이만큼 char 메모리를 할당한 후 CComBSTR의 문자열을 카피 해 주는 경우 한글이 있을 경우 한글은 Multi-Bytes에서는 2bytes를 차지하므로 CComBSTR.Length()로 받은 길이보다 더 많은 버퍼를 사용하게 된다. 그리고 이를 해제할 경우 HEAP CORRUPTION DETECTED가 발생하였다.

m_FName.Empty();
m_FName.AppendBSTR(name);
int len = m_FName.Length();
USES_CONVERSION ;
TCHAR* buf ;
buf = (TCHAR*)malloc(len+1);  // MBCS 으로 컴파일시 char로 할당됨.
ZeroMemory(buf, len+1) ;
wsprintf(buf, "%s", W2T(name));
int nLen = _tcslen(buf) ;  // 위의 m_FName.Length() 와 다른 값이 나옮
free(buf);
Trackback 0 Comment 1