|
Hi fellow coders,
When I'm blending pixels ARGB 127,127,127,127 on pixel RGB 0,0,127 the result is surprisingly RGB 127,127,190 !! where I was waiting for a result of 63,63,127.
AlphaBlend is using the formula :
A1R1G1B1 blended on R2G2B2 = ( R1 + A1*R2 ), ( G1 + A1*G2 ), ( B1 + A1*B2 )
How can I have it working with the formula :
A1R1G1B1 blended on R2G2B2 = ( A1*R1 + (255-A1)*R2 ), ( A1*G1 + (255-A1)*G2 ), ( A1*B1 + (255-A1)*B2 )
I'm using the following code :
CImage MyImage;<br />
CClientDC dc ( MyMFCControl );<br />
_pDoubleBufferBitmap = new CBitmap();<br />
_pDoubleBufferBitmap -> CreateCompatibleBitmap ( &dc, ... );<br />
_pDoubleBufferCDC = new CDC();<br />
_pDoubleBufferCDC -> CreateCompatibleDC(&dc);<br />
_pDoubleBufferCDC -> SelectObject(_pDoubleBufferBitmap);<br />
CPaintDC* pPaintDC = CreateCompatibleDC ( dc );<br />
MyImage.AlphaBlend ( _pPaintDC -> m_hDC, 50,50, 0xFF, AC_SRC_OVER );
Thank you for any help..
Alexis.
|
|
|
|
|
Oh.. ok I got it now.
The MSDN was not clear enough for me about the need of an alpha pre multiplyed ARGB format .
Alexis.
|
|
|
|
|
I translated this into C#. Works like a charm! Infinitely faster than DrawImage and the like in .NET.
I simply didnt know about this function. Thanks for pointing it out!
|
|
|
|
|
Hi.
I have a problem with the AlphaBlend function, that is the rendered bitmap doesn't look like it should.
For example, a bitmap with a pure red opaque region (a = 255, r = 255, g = 0, b = 0) and transparent in rest looks very weird: on a white background it's completly transparent, on a blue background the red region is magenta, etc. It looks like the Alphablend adds with saturation the coresponding channels of the colors.
The bitmap is obtained from a tiff image, edited with Photoshop.
Here is a part of the source code:
//premultiply the pixels of the bitmap
for (int i = 0; i < m_bm.Width(); i++)
{
for(int j = 0; j < m_bm.Height(); j++)
{
GX_RGBA c = m_bm.ReadPixel(i, j);
c.r = (BYTE)((double)c.r * c.a / 255.);
c.g = (BYTE)((double)c.g * c.a / 255.);
c.b = (BYTE)((double)c.b * c.a / 255.);
m_bm.WritePixel(i, j, c);
}
}
//call AlphaBlend
CDC memDC;
memDC.CreateCompatibleDC(NULL);
CBitmap *oldBmp = memDC.SelectObject(CBitmap::FromHandle(hBmp));
if (pBm->Type() == colour32)
{
BLENDFUNCTION bld;
bld.BlendOp = AC_SRC_OVER;
bld.BlendFlags = 0;
bld.SourceConstantAlpha = 255;
bld.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(*dp.pDC, outputOrigin.x, outputOrigin.y, m_bitmap.Width(), m_bitmap.Height(), memDC, 0, 0, m_bitmap.Width(), m_bitmap.Height(), bld);
}
Any insights will be very appreciated, thank you.
/\
|
|
|
|
|
Hey,
Try this if you haven't already figured it out:
bld.AlphaFormat = 0;
I had the same problem and setting bld.AlphaFormat to 0 seemed to fix it.
|
|
|
|
|
When you do the pre-multiply, you must make sure that no color channel is greater than the alpha channel. Oddly, this only affects 64-bit versions of Windows.
|
|
|
|
|
Can i draw with a single call of AlphaBlend image with alpha and transparency or should I call TransparentBlt and then AlphaBlend?
If the first one is true, please show me a sample code
|
|
|
|
|
I've been looking all over the Internet for an explanation of this and this is the only article.
Thank you Woo Seok Seo!
|
|
|
|
|
really?
i have seen several AlphaBlend?
|
|
|
|
|
Oh, well, I didn't find it and it doesn't diminish how awesome this article was!
|
|
|
|
|
Where can I find the same demo but I want that it is normal window???
|
|
|
|
|
You can find code for the alphablend algorithm that will run on Windows 95 here:
http://www.windevnet.com/documents/s=7628/wdj0109b/0109b.htm
|
|
|
|
|
Unfortunately, that algorithm is not nearly as fast as the Windows one, which probably is written in assembly.
I'm actually looking for an alpha-blending algorithm to be used in a moderately intensive graphics application involving lots of animation, an algorithm that's fast and works with all versions of Windows, msimg32.dll is probably the best bet but I'm not completely certain that it could be used with Win95/NT. Would appreciate any info from someone who has tested it with those OS's.
Henry P.
http://www.allersoft.com
|
|
|
|
|
How much slower is it?
On my machine, the code is actually faster. (I must be doing something wrong)
I'm using DoAlphaBlend for XP menu, toolbar effects and for "softening" lines and text in the main view of the program. I took a little shortcut in Christian's algorithm: Since I know the background (destination) is always the same colour (i.e. all bits the same RGB value), why bother creating 2 DIBs? I simply create 1 DIB in the algorithm, and then apply the alphablend between the source DIB bits and a static background colour.
I also ignore any source bit that is the same colour as the background color. This acts like a transparency for background coloured bits in the source.
|
|
|
|
|
Actually, the Windows AlphaBlend function has variable speeds depending on the specific parameters it's given. If you blend two bitmaps that are compatible with each other, it is MUCH faster than blending two bitmaps that are incompatible. For instance, if you're trying to blend a 24-bit bitmap to a 16-bit surface, it's a lot slower than blending a 16-bit bitmap to a 16-bit surface.
This difference is probably insignificant when you're dealing with bitmaps of menu size. However, when you're blending a bitmap, measuring say 800x600 pixels, that's almost half a million pixels that you have to compute the composite color for. That is too slow on most current home computers to be of use in an animation application.
I've found that blending two compatible bitmaps using the Windows AlphaBlend is amazingly fast, whereas blending two incompatible bitmaps (say a 32-bit DIB with a 16-bit surface) is MUCH slower (perhaps by an order of magnitude?).
Incidentally, if you include the msimg32.dll from WinME (and probably 98 as well) - but not the one from Win2000/XP - the AlphaBlend function will work on Win NT4. I haven't tested it on a Win95 machine yet (hard to find one these days) but I think it should work well as well (When you examine the import table for the WinME msimg32.dll, it contains only function calls to "basic" GDI functions that are available on all Windows platforms, so it probably will work on all Windows platform).
|
|
|
|
|
For the testing, I'm using the AlphaBlend on the entire view of an SDI project. (1280 x 1024, minus scrollbar space)
Here's the code I'm using in my OnDraw function.
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CRect rcClient;
GetClientRect(&rcClient);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height());
CBitmap* pOldBmp = memDC.SelectObject(&bmp);
memDC.FillSolidRect(&rcClient, GetSysColor(COLOR_WINDOW));
BLENDFUNCTION bf =
{
AC_SRC_OVER,
0,
170,
0
};
// Output text and lines here.
// Perform the blend
AlphaBlend(pDC->GetSafeHdc(), rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), memDC.GetSafeHdc(), rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), bf);
memDC.SelectObject(pOldBmp);
Am I doing something that is not optimal for the SDK based function? Christian's algorithm, combined with the tweaks I mentioned in a previous article, result in roughly 3x faster drawing code.
|
|
|
|
|
I've created an SDI project, and paste the code you provide into the CMyView::OnDraw function. I changed the color of the memDC to red to make the painting more easily observable. I did not do a formal timing test, but by resizing the view, the repainting occurs much quicker with the Windows AlphaBlend as compared to Christian's AlphaBlendU. The former repainting is almost instanstaneous whereas the latter pauses (the background takes on the original white color for a split second) before the painting is completed.
This test was done on a AMD 1.8GHz with WindowsXP, 512MB RAM. This could be a system-specific finding.
The Windows AlphaBlend function actually allows two different blending modes, by specifying the last parameter (AlphaFormat) of the BLENDFUNCTION struct. For reference:
typedef struct _BLENDFUNCTION
{
BYTE BlendOp;
BYTE BlendFlags;
BYTE SourceConstantAlpha;
BYTE AlphaFormat;
}BLENDFUNCTION, *PBLENDFUNCTION, *LPBLENDFUNCTION;
If AlphaFormat is 0, the source image is assumed to have a constant alpha as specified by SourceConstantAlpha. If AlphaFormat is AC_SRC_ALPHA, the source image is assumed to contain individual alpha values for each pixel (the alpha value being contained in the fourth byte of each pixel in a 32-bit (4 bytes per pixel) bitmap.
The reason I bring this up is because I've found that, at least for several computer systems I've tried on (both AMD, WinXP and Win2000), the blending is SIGNIFICANTLY faster when AlphaFormat is 0 (comparable to a BitBlt of the same bitmap size), whereas when the AlphaFormat is AC_SRC_ALPHA, the speed is slower, comparable to Christian's algorithm.
My speculation is that for the case where AlphaFormat is 0 (i.e., only a single SourceConstantAlpha is used), the Windows function does not need to extract the device-independent bits, and rather operate directly on the device-dependent bitmaps. The Windows function may also take advantage of driver acceleration as well...but this is just speculation.
If anyone discovers other interesting findings, please post them here.
Henry P.
http://www.allersoft.com
|
|
|
|
|
Hi guys
someone have a working version of this algo ?
I tried it, but got nothing
|
|
|
|
|
The msimg32.dll is required for AlphaBlend to work. It's not included, however, for Win95 and NT...This file is substantially different between the two families of Windows operating systems. For the 98/ME line, the file is about 50 KB in size whereas it's only 5 KB for the 2000/XP line. The reason is that the 98/ME file actually CONTAINS the drawing code for the alpha blending, whereas the 2000/XP file is merely a wrapper dll that will call the actual alpha blending function (named gdiAlphaBlend) in gdi32.dll. This can be verified by looking at the import tables for the two files.
Anyway, this means that the 2000/XP msimg32.dll may not be usuable on an NT4 platform, since the NT4 gdi32.dll may not contain the gdiAlphaBlend function. So if you want to use AlphaBlend on NT4 you might actually need the msimg32.dll from the 98/ME line.
Hope this makes sense.
Henry P.
http://www.allersoft.com
|
|
|
|
|
On the other hand, WDJ has code on thier site from an article I wrote that offers alphablending for all Windows versions.
Christian
NO MATTER HOW MUCH BIG IS THE WORD SIZE ,THE DATA MUCT BE TRANSPORTED INTO THE CPU. - Vinod Sharma
|
|
|
|
|
Thanks for the link...I'll attempt a thorough comparison between your algorithm and the Windows function in terms of speed. Just a quick comment, looking at your code it seems that it does not currently support variable source alpha (i.e., alpha values that are different for the individual source pixels), but it could probably be modified quite simply to handle this case.
Henry P.
http://www.allersoft.com
|
|
|
|
|
Yes, you are right. My algorithm seeks simply to copy the windows one, but it would be quite effortless to generate varying alpha based on a mask image or an algorithm.
Christian
NO MATTER HOW MUCH BIG IS THE WORD SIZE ,THE DATA MUCT BE TRANSPORTED INTO THE CPU. - Vinod Sharma
|
|
|
|
|
Anyone knows how fast AlphaBlend is compared to the other GDI functions: BitBlt, StretchBlt, DrawDibDraw, etc...?
Henry P.
http://www.allersoft.com
|
|
|
|
|
can use CDC class draw entity on this hbitmap.
my email:hexisoft@hotmail.com
|
|
|
|
|
Try 1600 repetitions: AlphaBlend hangs the entire wind98 box
(hangs XP partition)
This is serious mon
cts
cts
|
|
|
|
|