سؤال

أنا بحاجة إلى إنشاء عنصر تحكم مخصص لعرض الصور bmp مع قناة ألفا.الخلفية يمكن أن تكون رسمت في ألوان مختلفة و الصور والظلال لذلك أنا بحاجة حقا "الطلاء" قناة ألفا.

لا أحد يعرف كيف نفعل ذلك ؟

أريد أيضا إذا كان من الممكن إنشاء قناع استخدام قناة ألفا المعلومات لمعرفة ما إذا كان الماوس تم انقر على الصورة أو على منطقة شفافة.

أي نوع من المساعدة سوف يكون موضع تقدير!

شكرا

تحرير(JDePedro):كما أن بعض من كنت قد اقترحت كنت أحاول استخدام ألفا مزيج لرسم الصورة النقطية مع قناة ألفا.هذا مجرد اختبار لقد نفذت أين يمكنني تحميل 32-bit bitmap من الموارد و أحاول رسمه باستخدام 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 من مربع الحوار (أنا أيضا حاولت AlphaBlend وظيفة مركز السيطرة على الأمراض كائن).

عدم الشفافية في المناطق التي رسمت بشكل صحيح ولكن يمكنني الحصول الأبيض حيث نقطية ينبغي أن تكون شفافة.

أي مساعدة ؟ ؟ ؟

هذا هو لقطة..ليس من السهل أن نرى ولكن هناك المستطيل الأبيض حول الدائرة الزرقاء:النص البديل http://img385.imageshack.us/img385/7965/alphamh8.png

موافق.حصلت عليه!لدي إلى ما قبل تتضاعف كل بكسل على قيمة ألفا.شخص يمكن أن تشير إلى الطريقة الأمثل للقيام بذلك ؟

هل كانت مفيدة؟

المحلول

طريقة أفعل عادة هذا هو طريق DIBSection - وهو صورة نقطية مستقلة عن الجهاز أنه يمكنك تعديل بكسل مباشرة.للأسف ليس هناك أي MFC دعم DIBSections:لديك لاستخدام الدالة Win32 CreateDIBSection() لاستخدامه.

تبدأ عن طريق تحميل صورة نقطية مثل 32 بت RGBA (وهي أربعة بايت لكل بكسل:واحد أحمر ، أخضر واحد واحد أزرق وواحد قناة ألفا).في السيطرة إنشاء الحجم مناسب DIBSection.ثم في الطلاء الروتين

  • نسخ البيانات النقطية في 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);
}

وتحتاج إلى القيام ألفا مزيج مع لون الخلفية الخاصة بك، ثم إخراج ألفا قناة لرسمه إلى عنصر التحكم.

وقناة ألفا ينبغي أن يكون فقط كل بايت 4th من الصور الخاصة بك. يمكنك استخدام هذا مباشرة عن القناع الخاص بك، أو يمكنك فقط نسخ كل بايت 4TH إلى صورة قناع جديدة.

اللوحة فمن السهل جدا مع AlphaBlend وظيفة.

أما بالنسبة لك قناع, سوف تحتاج إلى الحصول على بت من الصورة النقطية ودراسة قناة ألفا بايت لكل بكسل كنت مهتما في.

والطريقة الأمثل لمرحلة ما قبل مضاعفة القنوات RGB مع قناة ألفا هي إعداد مجموعة [256] [256] تحتوي على نتائج الضرب المحسوبة. البعد الأول هو قيمة ألفا، والثاني هو R / G / B قيمة، القيم في مجموعة هي القيم مضروبة قبل التي تحتاج إليها.

ومع مجموعة هذه المجموعة بشكل صحيح، يمكنك حساب قيمة تحتاج مثل هذه:

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

وأنت على الطريق الصحيح، ولكن بحاجة إلى إصلاح أمرين.

وأول استخدام :: LoadImage (.. LR_CREATEDIBSECTION ..) بدلا من CBitmap :: LoadBitmap. اثنين، لديك ل"قبل ضرب" القيم RGB من كل بكسل في الصورة النقطية إلى كل وقيمتها. هذا هو شرط وظيفة AlphaBlend، انظر AlphaFormat الوصف على هذه الصفحة MSDN . T

lpng يحتوي على رمز العمل أن يفعل premultiplication للبيانات بنك دبي الإسلامي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top