Windows/MFC

비트맵 배경 제거 (TransparentBitmap)

aucd29 2013. 10. 2. 18:17
void MSJDrawTransparentBitmap(CDC* pDC, CBitmap* pBitmap, int xStart,
                             int yStart, COLORREF cTransparentColor)

{
    CBitmap bmAndBack, bmAndObject, bmAndMem, bmSave;
    CDC dcMem, dcBack, dcObject, dcvc_b, dcSave;

    dcvc_b.CreateCompatibleDC(pDC);
    dcvc_b.SelectObject(pBitmap); //비트맵 선택하기

    BITMAP bm;
    pBitmap->GetObject(sizeof(BITMAP), (LPSTR)&bm);

    CPoint ptSize;
    ptSize.x = bm.bmWidth;         // 비트맵의 폭
    ptSize.y = bm.bmHeight;        // 비트맵의 높이
    dcvc_b.DPtoLP(&ptSize, 1);     // 논리 포인트로부터 장치 포인트로 변환

    // 임시 데이터를 보관하기 위해 몇몇 DC를 생성
    dcBack.CreateCompatibleDC(pDC);
    dcObject.CreateCompatibleDC(pDC);
    dcMem.CreateCompatibleDC(pDC);
    dcSave.CreateCompatibleDC(pDC);

    // 각 DC를 위해 비트맵을 생성. DC는 GDI의 숫자만큼 필요하다.
    //    functions.// 모노크롬 DC

    bmAndBack.CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);

    // 모노크롬 DC
    bmAndObject.CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
    bmAndMem.CreateCompatibleBitmap(pDC, ptSize.x, ptSize.y);
    bmSave.CreateCompatibleBitmap(pDC, ptSize.x, ptSize.y);

    // 각 DC는 픽셀 데이터를 저장하기 위해 비트맵 객체를 선택해야 한다.
    CBitmap* pbmBackOld = dcBack.SelectObject(&bmAndBack);
    CBitmap* pbmObjectOld = dcObject.SelectObject(&bmAndObject);
    CBitmap* pbmMemOld = dcMem.SelectObject(&bmAndMem);
    CBitmap* pbmSaveOld = dcSave.SelectObject(&bmSave);

    // 적당한 맵핑 모드를 설정한다.
    dcvc_b.SetMapMode(pDC->GetMapMode());

    // 이리로 보내진 비트맵을 저장한다.
    dcSave.BitBlt(0, 0, ptSize.x, ptSize.y, &dcvc_b, 0, 0, SRCCOPY);

    // 투영되는 비트맵에 포함되는 색으로 소스 DC의 배경색을 설정한다.
    COLORREF cColor = dcvc_b.SetBkColor(cTransparentColor);

    // 소스 비트맵에서 모노크롬 비트맵까지 BitBlt를 수행해서
    // 비트맵용 오브젝트 마스크를 생성한다.
    dcObject.BitBlt(0, 0, ptSize.x, ptSize.y, &dcvc_b, 0, 0, SRCCOPY);

    // 원래 색으로 되돌리는 소스 DC의 배경색을 설정한다.
    dcvc_b.SetBkColor(cColor);

    // 객체 마스크를 반전시킨다.
    dcBack.BitBlt(0, 0, ptSize.x, ptSize.y, &dcObject, 0, 0, NOTSRCCOPY);

    // 목적지에 메인 DC의 배경을 복사한다.
    dcMem.BitBlt(0, 0, ptSize.x, ptSize.y, pDC, xStart, yStart, SRCCOPY);

    // 비트맵이 놓여지는 위치를 마스크한다.
    dcMem.BitBlt(0, 0, ptSize.x, ptSize.y, &dcObject, 0, 0, SRCAND);

    // 비트맵의 투명 색상 픽셀을 마스크한다.
    dcvc_b.BitBlt(0, 0, ptSize.x, ptSize.y, &dcBack, 0, 0, SRCAND);    

    // 목적지 DC상에서 배경색과 비트맵을 XOR 연산한다.
    dcMem.BitBlt(0, 0, ptSize.x, ptSize.y, &dcvc_b, 0, 0, SRCPAINT);

    // 스크린에 목적지를 복사한다.
    pDC->BitBlt(xStart, yStart, ptSize.x, ptSize.y, &dcMem, 0, 0, SRCCOPY);

    // 보내진 비트맵으로 원래 비트맵을 대체한다.
    dcvc_b.BitBlt(0, 0, ptSize.x, ptSize.y, &dcSave, 0, 0, SRCCOPY);

    // 메모리 비트맵을 리셋시킨다.
    dcBack.SelectObject(pbmBackOld);
    dcObject.SelectObject(pbmObjectOld);
    dcMem.SelectObject(pbmMemOld);
    dcSave.SelectObject(pbmSaveOld);

    // 메모리 DC와 비트맵 객체들은 자동으로 삭제된다.
}