본문 바로가기
Study/MFC

[MFC ] CDC 출력함수 정리

by 뿡뿡대마왕 2015. 7. 10.
반응형

출처:http://warmz.tistory.com/860



참고::

http://skmagic.tistory.com/entry/API-BitBlt-PatBltStretchBltTransparentBlt-%EC%A0%95%EB%A6%AC

http://raptors.egloos.com/892079


Blt 관련 함수들은 CDC 클래스의 멤버 함수로써 해당 DC에 비트맵을 그리거나 복사, 초기화하는 기능을 수행한다.

관련 API 참고::

http://msdn.microsoft.com/ko-kr/library/fxhhde73.aspx



1. BitBlt (고속복사)

메모리 DC의 비트맵을 현재 DC(일반적으론 화면 DC)에 고속복사한다. 이 때 두 DC는 반드시 호환되는 DC이거나 한쪽이 흑백이어야 한다. 완전히 다른 Color Format을 가지는 DC끼리는 비트맵을 전송할 수 없다. (흑백은 예외)

정의)
1
2
3
4
5
6
7
8
9
10
BOOL BitBlt(
   int x,       // 비트맵이 출력될 클라이언트 윈도우 기준 좌표
   int y,
   int nWidth,  // 출력될 비트맵의 폭과 높이
   int nHeight,
   CDC* pSrcDC, // 메모리 DC
   int xSrc,    // 메모리 DC의 비트맵을 어느 좌표부터 출력할 건지
   int ySrc,
   DWORD dwRop  // 출력 스타일 래스터 오퍼레이션 코드
);

예제)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void CBitmapView::OnDraw(CDC *pDC)
{
    ...
 
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);
     
    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP1);
 
    // memDC의 Bitmap이 리턴되지만 화면 pDC의 비트맵과 동일한 객체이다. (호환성)
    CBitmap *pOldBitmap = (CBitmap *) memDC.SelectObject(&bitmap);
 
    pDC->BitBlt(0, 0, 350, 400, &memDC, 0, 0, SRCCOPY);  // 전체 출력
 
    // 메모리 릭을 막기 위해선 반드시 화면 pDC의 비트맵을 돌려줘야 한다.
    // 돌려주지 않으면 pOldBitmap은 reference가 없으므로 해제할 수 없다.
    memDC.SelectObject(pOldBitmap);
    memDC.DeleteDC();
    bitmap.DeleteObject();
}
 


래스터 오퍼레이션(ROP) 코드는 아래와 같다. 빨간색이 가장 많이 사용하는 코드이다.

 SRCAND : 논리 AND 연산자를 사용하여 색을 조합한다.
 SRCCOPY : 원래 비트맵을 그대로 출력한다. (가장 많이 사용함)
 SRCPAINT : 논리 OR 연산자를 사용하여 색을 조합한다.
 SRCERASE : 비트맵과 화면의 반전색을 AND 연산한다.
 SRCINVERT : 비트맵과 화면을 XOR 연산한다.
 
 NOTSRCOPY : 비트맵을 반전시킨다.
 NOTSRCERASE : 화면색과 비트맵 색을 OR 연산한 후 반전시킨다.

 BLACKNESS : 무조건 검정색으로 칠한다.
 WHITENESS : 무조건 흰색으로 칠한다.

 DSTINVERT : 화면색을 반전시킨다.
 MERGECOPY : 브러시와 비트맵 색을 AND 연산한다.
 MERGETPAINT : 비트맵을 반전한 후 화면색과 OR 연산한다.

 PATCOPY : 현재 선택된 브러시로 칠한다.
 PATINVERT : 브러시와 화면색을 XOR 연산한다.
 PATPAINT : NOTSRCERASE의 결과를 브러시와 OR 연산한다.





2. StretchBlt (확대/축소)
이 함수는 이미지를 확대하거나 축소하여 출력하는데 이용한다. 매개변수는 BitBlt의 경우와 동일하나 추가적으로 원본 이미지의 넓이와 폭을 지정할 수 있다. 그래서 두 DC간의 면적비에 따라 이미지가 확대되거나 축소된다. 확대/축소 과정은 이미지의 픽셀끼리 1:1로 대응되는 것이 아니기 때문에 추가로 픽셀이 삽입되기도 하고 또는 픽셀이 생략되거나 합쳐지기도 한다.

정의)
1
2
3
4
5
6
7
8
9
10
11
12
BOOL StretchBlt(
   int x,   // 비트맵이 출력될 클라이언트 윈도우 기준 좌표
   int y,
   int nWidth,  // 출력될 비트맵의 폭과 높이
   int nHeight,
   CDC* pSrcDC, // 메모리 DC
   int xSrc,    // 출력할 비트맵을 어디서(기준 좌표)부터
   int ySrc,
   int nSrcWidth,   // 얼마(크기)만큼 얻어올 것인지 지정
   int nSrcHeight,
   DWORD dwRop  // ROP 코드
);


예제) BITMAP 구조체로 CBitmap의 정보를 알 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void CBitmapView::OnDraw(CDC *pDC)
{
    ...
 
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);
     
    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP1);
 
    BITMAP bmpInfo;
    bitmap.GetBitmap(&bmpInfo);
 
    CBitmap *pOldBitmap = (CBitmap *) memDC.SelectObject(&bitmap);
 
    CRect rect;
    GetClientRect(&rect);
 
    pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &memDC,
                bmpInfo.bmWidth, bmpInfo.bmHeight, SRCCOPY);
 
    memDC.SelectObject(pOldBitmap);
    memDC.DeleteDC();
    bitmap.DeleteObject();
}
 

주의) 확대될 때는 원본의 픽셀을 여러번 반복하면 되므로 별 문제가 없다. 하지만, 축소될 때는 불가피하게 원본의 픽셀 중 일부를 생략해야 하는데 이때 어떤 픽셀이 삽입되고 어떤 픽셀이 생략될 것인가를 계산하는 방법을 스트레칭 모드라고 하며 합쳐질 픽셀들의 논리 방법을 지정해야 한다.

1
int SetStretchBltMode(int iStretchMode);

 StretchMode의 종류

 - BLACKONWHITE(STRETCH_ANDSCANS) : AND 논리 연산을 사용한다. 흰색을 생략하고 검정색을 보존한다. 검정색이 우선 보존된다.

 - WHITEONBLACK(STRETCH_ORSCANS) : OR 논리 연산을 사용한다. 검정색을 생략하고 흰색을 보존한다. 흰색이 우선 보존된다.

 - COLORONCOLOR(STRETCH_DELETESCANS) : 생략되는 픽셀을 별도의 논리 연산없이 삭제한다.

 - HALFTONE(STRETCH_HALFTONE) : 복사대상과 복사원의 사각 블록끼리 대입하여 평균 색상을 구한다. 95/98에서 이 모드는 지원되지 않는다.

흑백 비트맵의 경우 BLACKONWHITE나 WHITEONBLACK이 적당하며 컬러 비트맵의 경우 COLORONCOLOR를 설정해야 픽셀이 깨지지 않는다. COLORONCOLOR 는 축소 비율에 따라 생략되는 줄이나 열 전체를 지워(생략해)버린다. HALFTON은 내부적으로 복잡한 연산에 의해 이미지의 어떤 부분이 획인지 자동으로 판단하여 가장 좋은 축소 결과를 만들어 낸다. 블록 단위의 이미지 판별을 하기 때문에 실행 속도가 다소 느리다.

1
2
3
pDC->SetStretchBltMode(COLORONCOLOR);        // set Mode.
pDC->StretchBlt(nX, nY, button.width, button.height, &memDC, 0,0,
            BMPWIDTH, BMPHEIGHT, SRCCOPY);      // Draw






3. PatBlt (패턴방식 초기화)
이 함수는 해당 DC의 비트맵 영역을 패턴형태로 초기화하는데 사용한다. 여기서 말하는 패턴이란 쉽게 말해서 브러시인데 지정한 사각영역을 현재 DC에 선택된 브러시로 채운다. FillRect 함수와 형식만 다를 뿐이지 동작은 같다. 그러나 FillRect는 사각영역을 무조건 브러시로 채우지만 PatBlt는 ROP 코드를 통해 화면 색상과 브러시 생삭의 논리 연산을 지정할 수 있다.

정의)
1
2
3
4
5
6
7
BOOL PatBlt(
   int x,
   int y,
   int nWidth,
   int nHeight,
   DWORDdwRop
);


예제) 화면 DC를 흰색으로 초기화한다.

1
pDC->PatBlt(0, 0, rect.Width(), rect.Height(), WHITENESS);





4. TransparentBlt (투명 비트맵 출력)
비트맵은 예외없이 사각형 모양을 가진다. 타원 모양이나 다각형 모양의 비트맵은 존재하지 않는다. 비트맵 안의 그림은 어떤 모양이든지 가능하지만 비트맵 자체는 꼭 사각형이어야만 하며 출력할 때도 화면상의 사각영역에만 출력된다. 그런데 경우에 따라서 사각형이 아닌 형태로 비트맵을 출력해야 할 경우가 있는데 특히 게임의 경우 캐릭터들이 사각형이 아닌 경우가 많다. 이때는 비트맵의 일부를 투명하게 처리하여 투명색 부분은 출력에서 제외하는 방법을 사용한다.

정의)

1
2
3
4
5
6
7
8
9
10
11
12
BOOL TransparentBlt(
   int xDest,
   int yDest,
   int nDestWidth,
   int nDestHeight,
   CDC* pSrcDC,
   int xSrc,
   int ySrc,
   int nSrcWidth,
   int nSrcHeight,
   UINT clrTransparent      // 투명 영역 컬러(RGB)
);
 
이 함수가 투명 비트맵을 출력하는데 원형 StretchBlt와 거의 유사하되 제일 마지막의 인수가 ROP 모드를 지정하지 않고 투명색으로 사용할 마스크 색상을 지정한다는 점이 다르다. 이 함수를 사용하려면 먼저 출력할 비트맵부터 만들어야 한다. 비트맵을 처음 만들 때부터 투명하게 처리할 부분은 특별한 다른 색(마스크 색상)으로 주어 그림 자체와는 구분되게 처리한다그리고 마스크 색은 출력되지 않도록 하면 원하는 효과를 달성할 수 있다.이때 마스크로 사용할 색상은 이미지 내에는 존재하지 않는 특수한 색상이어야 하는데 주로 분홍생이 많이 사용된다. 


예제)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CDC memDC;
memDC.CreateCompatibleDC(&pDC);
 
CBitmap bmp;
bmp.LoadBitmapA(IDB_ME);
 
CBitmap *pOldBmp = NULL;
pOldBmp = memDC.SelectObject(&bmp);
 
BITMAP bmpInfo;
bmp.GetBitmap(&bmpInfo);
 
// 검정색(RGB(0,0,0))으로 처리된 영역은 출력하지 않는다.
// 그러므로 해당 리소스의 투명 영역은 반드시 검정색으로 처리해놔야 한다.
pDC->TransparentBlt(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC,
            0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, RGB(0,0,0));
 
memDC.SelectObject(pOldBmp);
memDC.DeleteDC();
bmp.DeleteObject();

TransparentBlt는 Msimg32.lib 에서 제공하므로 프로젝트 링커에서 등록해줘야 한다. (MS Visual 6 기준)





5. MaskBlt
이 함수는 BitBlt와 거의 동일한 동작을 하며, (래스터 연산과 함께) 마스크 비트맵(maskBitmap)을 사용하여 srcDC와 pDC의 컬러 테이터를 섞을 수 있다는 점에서 다르다. 마스크 비트맵은 흑백의 비트맵인데 1인 부분(전경(foreground) ROP)과 0인 부분(배경(background) ROP)에 각각 서로 다른 래스터 연산 코드를 줘서 다른 효과를 낼 수 있다. 이를 위해 ROP 코드의 상위 워드의 상위 바이트에는 배경을 위한 ROP가, 상위 워드의 하위 바이트에는 전경을 위한 ROP가 들어간다. 하위 워드의 값은 0이어야 하며 이 값은 무시(ignore)된다. 이러한 래스터 연산 코드를 조합하기 위해서는 MAKEROP4 매크로를 이용하면 된다. (Windows NT 이상만 사용 가능)

정의)

1
2
3
4
5
6
7
8
9
10
11
12
13
BOOL MaskBlt(
   int x,
   int y,
   int nWidth,
   int nHeight,
   CDC* pSrcDC,
   int xSrc,
   int ySrc,
   CBitmap& maskBitmap, // 마스크 비트맵
   int xMask,
   int yMask,
   DWORD dwRop  // ROP 코드
);




6. PlgBlt (이미지 기울이기 / 평행사변형)
parallelogram라는 단어에서 알 수 있듯이 PlgBlt 함수는 pSrcDC에 지정된 rectangle에 있는 컬러 데이터 비트를 현재 DC에 지정된 평행사변형(lpPoint)으로 비트 블럭을 전송하는 역할을 수행한다. 만약, 주어진 maskBitmap이 유효한 흑백 비트맵과 동일하다면, 함수는 이 비트맵을 rectangle로부터 컬러 데이터 비트를 추출하는데 쓰이는 마스크(mask)로 사용한다.

 lpPoint는 평행사변형의 세 꼭지점을 가리키는 좌표(POINT)에 대한 배열의 포인터이다. 이 배열의 0번째 인덱스(A)에는 왼쪽 상단의 꼭지점, 1번째 인덱스(B)에는 오른쪽 상단의 꼭지점, 2번째 인덱스(C)는 왼쪽 하단의 꼭지점을 가리키는 좌표의 값이 들어가게 된다. 평행사변형의 오른쪽 하단 좌표(D)는 B + C - A 의 계산을 통해 알 수 있다.


정의)

1
2
3
4
5
6
7
8
9
10
11
BOOL PlgBlt(
   LPPOINT lpPoint,
   CDC* pSrcDC,     // 가져올 DC
   int xSrc,
   int ySrc,
   int nWidth,
   int nHeight,
   CBitmap& maskBitmap, // 마스크 이미지
   int xMask,
   int yMask
);


반응형

댓글