문제

알파 채널로 BMP 이미지를 표시하려면 사용자 정의 컨트롤을 작성해야합니다. 배경은 다른 색상으로 페인트 될 수 있고 이미지에는 그림자가 있으므로 알파 채널을 진정으로 "페인트"해야합니다.

아무도 그것을하는 방법을 아는 사람이 있습니까?

또한 가능한 경우 알파 채널 정보를 사용하여 마스크를 만들어 마우스가 이미지를 클릭했는지 또는 투명 영역을 클릭했는지 여부를 알 수 있습니다.

어떤 종류의 도움이든 감사 할 것입니다!

감사.

편집 (JDEPEDRO) : 여러분 중 일부가 제안한 것처럼 Alpha Blend를 사용하여 Alpha 채널로 비트 맵을 페인트하려고했습니다. 이것은 리소스에서 32 비트 비트 맵을로드하는 곳에서 구현 한 테스트 일뿐 아니라 Alphablend 기능을 사용하여 페인트를 칠하려고합니다.

void CAlphaDlg::OnPaint()
{
    CClientDC dc(this);
    CDC  dcMem;
    dcMem.CreateCompatibleDC(&dc);

    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP);

    BITMAP BitMap;
    bitmap.GetBitmap(&BitMap);
    int nWidth = BitMap.bmWidth;
    int nHeight = BitMap.bmHeight;
    CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);

    BLENDFUNCTION m_bf;
    m_bf.BlendOp = AC_SRC_OVER;
    m_bf.BlendFlags = 0;
    m_bf.SourceConstantAlpha = 255;
    m_bf.AlphaFormat = AC_SRC_ALPHA;
    AlphaBlend(dc.GetSafeHdc(), 100, 100, nWidth, nHeight, dcMem.GetSafeHdc(), 0, 0,nWidth, nHeight,m_bf); 

    dcMem.SelectObject(pOldBitmap);

    CDialog::OnPaint();
}

이것은 단지 테스트 일 뿐이므로 코드를 대화 상자의 정점에 넣었습니다 (또한 CDC 객체의 Alphablend 함수를 시도했습니다).

비 투피 영역은 올바르게 페인트되고 있지만 비트 맵이 투명 해야하는 곳에서 흰색이됩니다.

도움이 있습니까 ???

이것은 스크린 샷입니다.보기는 쉽지 않지만 파란색 원 주위에는 흰색 사각형이 있습니다.Alt Text http://img385.imageshack.us/img385/7965/alphamh8.png

확인. 알겠어요! 알파 값을 위해 모든 픽셀을 미리 배양해야합니다. 누군가가 최적화 된 방법을 제안 할 수 있습니까?

도움이 되었습니까?

해결책

내가 일반적 으로이 작업을 수행하는 방식은 직접 픽셀을 수정할 수있는 장치 독립 비트 맵입니다. 불행히도 dibsections에 대한 MFC 지원은 없습니다. Win32 함수 createBsection ()을 사용하여 사용해야합니다.

비트 맵을 32 비트 RGBA로로드하여 시작하십시오 (즉, 픽셀 당 4 바이트 : 하나의 빨간색, 1 개의 녹색, 하나는 알파 채널)로로드하십시오. 컨트롤에서 적절한 크기의 딥 션을 만듭니다. 그런 다음 페인트 루틴에서

  • 알파 채널 바이트를 사용하여 비트 맵 데이터를 Dibsection의 비트 맵 데이터에 복사하여 비트 맵 이미지를 배경색과 혼합하십시오.
  • 장치 컨텍스트를 작성하고 dibsection을 선택하십시오.
  • bitblt ()를 사용하여 새 장치 컨텍스트에서 페인트 장치 컨텍스트로 복사하십시오.

알파 채널 값을 보면서 원시 비트 맵 데이터가 주어지면 마스크를 만들 수 있습니다. 여기에서 무엇을 묻는 지 잘 모르겠습니다.

다른 팁

향후 Google 사용자의 경우 여기에 온화한 작업이 있습니다. 이것은 가져 왔습니다 http://www.viksoe.dk/code/alphatut1.htm .

inline void PremultiplyBitmapAlpha(HDC hDC, HBITMAP hBmp)
{
   BITMAP bm = { 0 };
   GetObject(hBmp, sizeof(bm), &bm);
   BITMAPINFO* bmi = (BITMAPINFO*) _alloca(sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
   ::ZeroMemory(bmi, sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
   bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
   BOOL bRes = ::GetDIBits(hDC, hBmp, 0, bm.bmHeight, NULL, bmi, DIB_RGB_COLORS);
   if( !bRes || bmi->bmiHeader.biBitCount != 32 ) return;
   LPBYTE pBitData = (LPBYTE) ::LocalAlloc(LPTR, bm.bmWidth * bm.bmHeight * sizeof(DWORD));
   if( pBitData == NULL ) return;
   LPBYTE pData = pBitData;
   ::GetDIBits(hDC, hBmp, 0, bm.bmHeight, pData, bmi, DIB_RGB_COLORS);
   for( int y = 0; y < bm.bmHeight; y++ ) {
      for( int x = 0; x < bm.bmWidth; x++ ) {
         pData[0] = (BYTE)((DWORD)pData[0] * pData[3] / 255);
         pData[1] = (BYTE)((DWORD)pData[1] * pData[3] / 255);
         pData[2] = (BYTE)((DWORD)pData[2] * pData[3] / 255);
         pData += 4;
      }
   }
   ::SetDIBits(hDC, hBmp, 0, bm.bmHeight, pBitData, bmi, DIB_RGB_COLORS);
   ::LocalFree(pBitData);
}

그러면 당신의 onpaint는 다음과 같습니다.

void MyButton::OnPaint()
{
    CPaintDC dc(this);

    CRect rect(0, 0, 16, 16);

    static bool pmdone = false;
    if (!pmdone) {
        PremultiplyBitmapAlpha(dc, m_Image);
        pmdone = true;
    }

    BLENDFUNCTION bf;
    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 255;
    bf.AlphaFormat = AC_SRC_ALPHA;

    HDC src_dc = m_Image.GetDC();
    ::AlphaBlend(dc, rect.left, rect.top, 16, 16, src_dc, 0, 0, 16, 16, bf);
    m_Image.ReleaseDC();
}

그리고 이미지의 로딩 (제어 제작자) :

if ((HBITMAP)m_Image == NULL) {
    m_Image.LoadFromResource(::AfxGetResourceHandle(), IDB_RESOURCE_OF_32_BPP_BITMAP);
}

당신은해야합니다 알파 블렌드 배경색으로 알파 채널을 꺼내서 컨트롤에 페인트하십시오.

알파 채널은 이미지의 4 번째 바이트 마다만 있어야합니다. 마스크에 직접 사용할 수 있거나 4 번째 바이트를 새 마스크 이미지로 복사 할 수 있습니다.

그림은 매우 쉽습니다 alphablend 기능.

마스크에 관해서는 필요합니다 비트를 얻으십시오 비트 맵에서 관심있는 각 픽셀에 대한 알파 채널 바이트를 검사하십시오.

알파 채널을 사용하여 RGB 채널을 미리 배치하는 최적화 된 방법은 계산 된 곱셈 결과를 포함하는 [256] [256] 배열을 설정하는 것입니다. 첫 번째 차원은 알파 값이고, 두 번째는 r/g/b 값이고, 배열의 값은 당신이 필요한 사전 배수 값입니다.

이 배열이 올바르게 설정되면 다음과 같은 필요한 값을 계산할 수 있습니다.

R = multiplicationLookup[alpha][R];
G = multiplicationLookup[alpha][G];
B = multiplicationLookup[alpha][B];

당신은 올바른 길을 가고 있지만 두 가지를 고쳐야합니다.

첫 번째 aD 둘째, 비트 맵에서 각각의 값에 대한 모든 픽셀의 RGB 값을 "사전 다중"해야합니다. 이것은 alphablend 기능의 요구 사항입니다. 이 MSDN 페이지. 티

그만큼 lpng DIB 데이터의 전형화를 수행하는 작업 코드가 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top