2008-11-20 17 views
8

मुझे अल्फा चैनल के साथ बीएमपी छवियों को प्रदर्शित करने के लिए कस्टम नियंत्रण बनाने की आवश्यकता है। पृष्ठभूमि को विभिन्न रंगों में चित्रित किया जा सकता है और छवियों में छाया होती है इसलिए मुझे अल्फा चैनल को वास्तव में "पेंट" करने की आवश्यकता होती है।32-बिट अल्फा चैनल बिटमैप्स कैसे आकर्षित करें?

क्या कोई जानता है कि यह कैसे करें?

मैं यह भी जानना चाहता हूं कि अल्फा चैनल जानकारी का उपयोग करके मास्क बनाना संभव है या नहीं, यह जानने के लिए कि माउस छवि पर या पारदर्शी क्षेत्र पर क्लिक किया गया है या नहीं।

किसी भी प्रकार की सहायता की सराहना की जाएगी!

धन्यवाद।

संपादित (जेडीपेड्रो): जैसा कि आप में से कुछ ने सुझाव दिया है कि मैं अल्फा चैनल के साथ बिटमैप पेंट करने के लिए अल्फा मिश्रण का उपयोग करने का प्रयास कर रहा हूं। यह सिर्फ एक परीक्षण मैं क्रियान्वित किया है, जहां मैं संसाधनों से एक 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(); 
} 

यह सिर्फ एक परीक्षण तो मैं की OnPaint में कोड डाल है संवाद (मैंने सीडीसी ऑब्जेक्ट के अल्फाब्लेंड फ़ंक्शन का भी प्रयास किया)।

गैर-पारदर्शी क्षेत्रों को सही ढंग से चित्रित किया जा रहा है लेकिन मुझे सफेद मिलता है जहां बिटमैप पारदर्शी होना चाहिए।

कोई मदद ???

यह एक screenshot..it को देखने के लिए आसान नहीं है लेकिन वहाँ नीले वृत्त के चारों ओर एक सफेद आयत है: alt text http://img385.imageshack.us/img385/7965/alphamh8.png

ठीक है। मैं समझ गया! मुझे अल्फा मान के लिए प्रत्येक पिक्सेल को पूर्व-गुणा करना होगा। कोई ऐसा करने के लिए अनुकूलित तरीका सुझा सकता है?

उत्तर

5

जिस तरह से मैं आमतौर पर ऐसा करता हूं वह एक DIBSection के माध्यम से होता है - एक डिवाइस स्वतंत्र बिटमैप जिसे आप सीधे पिक्सल संशोधित कर सकते हैं। दुर्भाग्यवश DIBSections के लिए कोई भी एमएफसी समर्थन नहीं है: आपको इसका उपयोग करने के लिए Win32 फ़ंक्शन CreateDIBSection() का उपयोग करना होगा।

32-बिट आरजीबीए (यानी, चार बाइट प्रति पिक्सेल: एक लाल, एक हरा, एक नीला और अल्फा चैनल के लिए) के रूप में बिटमैप लोड करके प्रारंभ करें। नियंत्रण में, एक उपयुक्त आकार का डिब्बेक्शन बनाएं। फिर, रंग दिनचर्या

  • कॉपी में DIBSection के बिटमैप डेटा में बिटमैप डेटा, अल्फ़ा चैनल बाइट का उपयोग कर पृष्ठभूमि रंग के साथ बिटमैप छवि मिश्रण करने के लिए।
  • डिवाइस संदर्भ बनाएं और इसमें DIBSection का चयन करें।
  • नए डिवाइस संदर्भ से पेंट डिवाइस संदर्भ में कॉपी करने के लिए बिटबल्ट() का उपयोग करें।

आप अल्फा चैनल मानों को देखकर कच्चे बिटमैप डेटा को एक मुखौटा बना सकते हैं - मुझे यकीन नहीं है कि आप यहां क्या पूछ रहे हैं।

1

आपको अपने पृष्ठभूमि रंग के साथ alpha blend करने की आवश्यकता है, फिर उसे नियंत्रण में पेंट करने के लिए अल्फा चैनल निकालें।

अल्फा चैनल आपकी छवि के प्रत्येक चौथाई बाइट होना चाहिए। आप सीधे अपने मुखौटा के लिए इसका उपयोग कर सकते हैं, या आप हर 4 वें बाइट को एक नई मास्क छवि में कॉपी कर सकते हैं।

+0

हाय मार्क, की अगर देखते हैं मैं अपने सुझाव को समझें। कल्पना कीजिए कि मैं CSTatic/CWnd से अपना नियंत्रण प्राप्त करता हूं और मैं सदस्य के रूप में एक सीबीआईटीमैप जोड़ता हूं। फिर हर बार जब नियंत्रण पेंट किया जा रहा है (ऑनपेंट विधि में) मुझे पृष्ठभूमि प्राप्त करना है और मेरी छवि के साथ मिश्रण बनाना है? –

+0

(जारी रखें) क्या मैं सही हूँ? क्या मुझे अपने आप से सब कुछ करना है? ऐसा लगता है क्योंकि इसमें उच्च प्रदर्शन लागत हो सकती है ... क्या आप (कोई भी) मुझे ऐसा करने का सबसे अच्छा तरीका (अधिक इष्टतम) बता सकता है? शायद कुछ भयानक लेख या यहां तक ​​कि codenippet? धन्यवाद। –

1

चित्रकारी AlphaBlend function के साथ बहुत आसान है।

के लिए आप मुखौटा के रूप में, आप बिटमैप की get the bits के लिए एक अनुकूलित रास्ता अल्फा के साथ आरजीबी चैनलों पूर्व गुणा करने की आवश्यकता है और प्रत्येक पिक्सेल में आपकी रुचि है के लिए अल्फ़ा चैनल बाइट की जांच करेंगे।

1

चैनल एक [256] [256] सरणी स्थापित करने के लिए गणना की गई गुणात्मक परिणाम है। पहला आयाम अल्फा मान है, दूसरा आर/जी/बी मान है, सरणी में मान पूर्व-गुणा मूल्यों की आवश्यकता है।

इस सरणी सही तरीके से सेट के साथ, आप मूल्य आप इस तरह की जरूरत है की गणना कर सकते हैं:

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

आप सही रास्ते पर हैं, लेकिन दो बातें तय करने के लिए की जरूरत है।

सीबीआईटीमैप :: लोडबिटमैप के बजाय पहले लोड :: लोडइमेज (.. LR_CREATEDIBSECTION ..) का उपयोग करें। दो, आपको प्रत्येक पिक्सेल के आरजीबी मूल्यों को बिटमैप में अपने संबंधित ए मान में "पूर्व-गुणा" करना होगा। यह अल्फाब्लेंड फ़ंक्शन की आवश्यकता है, this MSDN page पर अल्फाफॉर्मेट विवरण देखें। टी

lpng में एक कामकाजी कोड है जो डीआईबी डेटा के प्रील्टिप्लिकेशन करता है।

7

भविष्य के 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); 
} 
+0

यदि मैं एक स्थिर लेबल पर पारदर्शी छवि दिखाना चाहता हूं तो क्या होगा? पायस्टेटिक-> संशोधित स्टाइल (0xF, SS_BITMAP); pStatic-> SetBitmap (बिटमैप); –

संबंधित मुद्दे