|
-
Jul 28th, 2003, 10:34 PM
#1
Thread Starter
Fanatic Member
Per-pixel alpha blend function math [Resolved]
I know this is not vb, but...
I'm writing a function in vc++ for a dll that will be accessed from vb. It takes three hDC's and combines them, overlaying hdc2 over hdc1, using hdc3 as the mask.
I'm working with the DIB of the hdc's so it's hella fast (array of pixel values). Anybody know what the math formula for blending the pixels is?
this is how it might look in algebra.
d = f(o, s, a)
d = destination value
o = "layer 1" value
s = "layer 2" value
a = "alpha" or opacity value
all of the values range from 0 to 255 (this needs to be done for each channel of the pixel)
255 is full opacity and 0 is no opacity
if anybody can tell me what f is?
if you don't understand what i'm asking, let me know. maybe i can phrase it better
Last edited by agent; Jul 29th, 2003 at 11:25 PM.
-
Jul 29th, 2003, 08:07 AM
#2
Ex-Super Mod'rater
VB Code:
FinalPixel = (AlphaValue * (Source + 256 - Destination)) / 256 + Destination - AlphaValue
When your thread has been resolved please edit the original post in the thread (  )
and amend "-[RESOLVED]-" to the end of the title and change the icon to  , Thank you.
When posting Code use the [VBCode]Code Here[/VBCode] tags to be able to use the code highlighting.

-
Jul 29th, 2003, 08:13 AM
#3
Ex-Super Mod'rater
I'll rewrite it to match your variables:
VB Code:
d = (a * (s + 256 - o)) / 256 + o - a
Be aware that your value for a would be best based on the average of the 3 color channels for that pixel on your mask.
Last edited by Electroman; Jul 29th, 2003 at 08:16 AM.
When your thread has been resolved please edit the original post in the thread (  )
and amend "-[RESOLVED]-" to the end of the title and change the icon to  , Thank you.
When posting Code use the [VBCode]Code Here[/VBCode] tags to be able to use the code highlighting.

-
Jul 29th, 2003, 09:03 AM
#4
Frenzied Member
could you please post the dll source?
i would really like to know how to handle dc's in vc++...
im making a dll myself and it sends all the colorvalues as an array to vb and i dont like it that way, so i think it would be better to make a dc...also all the processing should be put into vc++ cus its alot faster than vb!
-
Jul 29th, 2003, 09:07 AM
#5
Frenzied Member
also try this:
d=o*(1-a)+s*a
a should be from 0 to 1
if its from 0 to 255 then a = a/255
-
Jul 29th, 2003, 09:15 AM
#6
Ex-Super Mod'rater
You realise that thats the same?? .
Mind he can't use 0 < a < 1 because he's getting the value for the alpha from a image so it'll be in the 0 - 255 range already so there ain't much point in converting it to 0 - 1.
Also don't simplify the formula I gave by removing the 256's because they are there to prevent negative numbers in the division.
When your thread has been resolved please edit the original post in the thread (  )
and amend "-[RESOLVED]-" to the end of the title and change the icon to  , Thank you.
When posting Code use the [VBCode]Code Here[/VBCode] tags to be able to use the code highlighting.

-
Jul 29th, 2003, 12:12 PM
#7
Thread Starter
Fanatic Member
Originally posted by cyborg
could you please post the dll source?
i would really like to know how to handle dc's in vc++...
im making a dll myself and it sends all the colorvalues as an array to vb and i dont like it that way, so i think it would be better to make a dc...also all the processing should be put into vc++ cus its alot faster than vb!
i'll post the source when i get home, but i'll answer you question right now:
hDCs are handled basically the same in vb as in c++
in vb
Code:
Dim hdcDest As Long
in c++
since the API call are all in windows.h, you don't need to declare them as you do in vb.
an example? let's create a memory hDC and make it 300x300 pixels in vb and c++
vb
Code:
Dim hdcTmp As Long 'hdc
hdcTmp = CreateCompatibleDC(0)
SelectObject hdcTmp, CreateCompatibleBitmap(hdcTmp, 300, 300)
c++
Code:
HDC hdcTmp = CreateCompatibleBitmap(NULL);
SelectObject(hdcTmp, CreateCompatibleBitmap(hdcTmp, 300, 300));
-
Jul 29th, 2003, 12:17 PM
#8
Thread Starter
Fanatic Member
Originally posted by Electroman
I'll rewrite it to match your variables:
VB Code:
d = (a * (s + 256 - o)) / 256 + o - a
Be aware that your value for a would be best based on the average of the 3 color channels for that pixel on your mask.
you sure it should be 256? the values for all the variables range from 0 to 255, inclusive.
-
Jul 29th, 2003, 12:32 PM
#9
Ex-Super Mod'rater
Yea I know, the 256 cancels itself anyway and its only to prevent negative numbers while doing calculations. This is because I assume a,d,s and o will all be bytes and when doing calculations with just bytes VB will use a byte to hold the dat while it is being calculated at each stage. Did you try it??
When your thread has been resolved please edit the original post in the thread (  )
and amend "-[RESOLVED]-" to the end of the title and change the icon to  , Thank you.
When posting Code use the [VBCode]Code Here[/VBCode] tags to be able to use the code highlighting.

-
Jul 29th, 2003, 01:23 PM
#10
Frenzied Member
dont seem to get it to work...
i get the "Bad dll calling convention" error from vb...
i declare the api like this:
VB Code:
Private Declare Function Mandelbrot Lib "mandelbrotfractal.dll" (ByVal Rmin As Double, ByVal Rmax As Double, ByVal Imin As Double, ByVal Imax As Double, ByVal MaxIt As Double, ByVal MaxColors As Double, ByVal maxcol As Integer, ByVal maxrow As Integer, ColorRange As Double) As Long
then i just put this into BitBlt as the hSrcDC parameter and blit it into a picturebox.
-
Jul 29th, 2003, 02:53 PM
#11
Thread Starter
Fanatic Member
make sure the vb declare has the same number of parameters as the c++ function. make sure that the types being passed are compatible.
for exampble, HDC and int in c++ are both the same as Long in vb.
also, make sure that the function uses the __stdcall directive, and make sure the function is properly exported using a def file. when i upload my dll, you can see how I export the SoftBlit function.
-
Jul 29th, 2003, 03:09 PM
#12
Frenzied Member
yes! i can hardly wait
-
Jul 29th, 2003, 03:43 PM
#13
Frenzied Member
got a small problem...when using SetPixelV in c++ i only get colors in black and white...thats color values 0 and 16777216. even thou i set it to 255 i gets totally black! what do i do wrong?
-
Jul 29th, 2003, 07:03 PM
#14
Thread Starter
Fanatic Member
try making an HDC that is compatible with the screen (you'll need to refer to the API documentation for this one, don't have it memorized.
-
Jul 29th, 2003, 08:55 PM
#15
Thread Starter
Fanatic Member
finally... i just got home from work... here's the source code to the dll
jsgfx.cpp
Code:
#include <windows.h>
// The Representation of a 32 bit color table entry
#pragma pack(push)
#pragma pack(1)
typedef struct ssBGR {
unsigned char b;
unsigned char g;
unsigned char r;
unsigned char pad;
} sBGR;
typedef sBGR *pBGR;
#pragma pack(pop)
//prototypes
void __stdcall SoftBlt(HDC hdcDest, int nLeft, int nTop, int nWidth, int nHeight, HDC hdcSrc, HDC hdcSrcMask);
pBGR MyGetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight);
int MySetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight, pBGR buf);
sBGR Pixelate(sBGR dest,sBGR source,BYTE Alpha);
void __stdcall SoftBlt(HDC hdcDest, int nLeft, int nTop, int nWidth, int nHeight, HDC hdcSrc, HDC hdcSrcMask)
{
//STEP 1 - 3
HDC hdcTMPDest = CreateCompatibleDC(hdcDest);
HBITMAP hbTMPDest = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
SelectObject(hdcTMPDest, hbTMPDest);
BitBlt(hdcTMPDest, 0, 0, nWidth, nHeight, hdcDest, nLeft, nTop, SRCCOPY);
pBGR dibDest = MyGetDibBits(hdcTMPDest, (HBITMAP) GetCurrentObject(hdcTMPDest, OBJ_BITMAP), nWidth, nHeight);
pBGR dibSource = MyGetDibBits(hdcSrc, (HBITMAP) GetCurrentObject(hdcSrc, OBJ_BITMAP), nWidth, nHeight);
pBGR dibMask = MyGetDibBits(hdcSrcMask, (HBITMAP) GetCurrentObject(hdcSrcMask, OBJ_BITMAP), nWidth, nHeight);
//STEP 4
for (int y = 0; y < nHeight; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
sBGR bgrDest = dibDest[y * nWidth + x];
sBGR bgrSource = dibSource[y * nWidth + x];
sBGR bgrMask = dibMask[y * nWidth + x];
unsigned char mask = ((bgrMask.b + bgrMask.g + bgrMask.r) / 3);
//Blend function
//bgrDest.r = 255;
//bgrDest.g = 0;
//bgrDest.b = 0;
bgrDest = Pixelate(bgrDest, bgrSource, mask);
//bgrDest.r = 255 - bgrDest.r;
//bgrDest.g = 255 - bgrDest.g;
//bgrDest.b = 255 - bgrDest.b;
dibDest[y * nWidth + x] = bgrDest;
}
}
//STEP 5
HDC hdcTmp = CreateCompatibleDC(hdcDest);
HBITMAP hbTmp = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
SelectObject(hdcTmp, hbTmp);
//STEP 6
MySetDibBits(hdcTmp, hbTmp, nWidth, nHeight, dibDest);
//STEP 7
BitBlt(hdcDest, nLeft, nTop, nWidth, nHeight, hdcTmp, 0, 0, SRCCOPY);
//Step 8
DeleteObject(hbTMPDest);
DeleteObject(hbTmp);
DeleteDC(hdcTMPDest);
DeleteDC(hdcTmp);
free(dibDest);
free(dibSource);
free(dibMask);
}
sBGR Pixelate(sBGR dest,sBGR source,BYTE Alpha)
{
float FinalRed,FinalGreen,FinalBlue;
FinalRed = (Alpha/255.0f*(float)source.r) + ((1.0f-Alpha/255.0f)*(float)dest.r);
FinalGreen= (Alpha/255.0f*(float)source.g) + ((1.0f-Alpha/255.0f)*(float)dest.g);
FinalBlue = (Alpha/255.0f*(float)source.b) + ((1.0f-Alpha/255.0f)*(float)dest.b);
int nFinalRed,nFinalGreen,nFinalBlue;
if(FinalRed>=FinalGreen && FinalRed>=FinalBlue)
{
if(FinalRed>255.0f)
{
nFinalRed=255;
nFinalGreen=(int)(FinalGreen/FinalRed*255.0f);
nFinalBlue =(int)(FinalBlue/FinalRed*255.0f);
}
else
{
nFinalRed =(int)(FinalRed);
nFinalGreen=(int)(FinalGreen);
nFinalBlue =(int)(FinalBlue);
}
}
else if(FinalGreen>=FinalRed && FinalGreen>=FinalBlue)
{
if(FinalGreen>255.0f)
{
nFinalRed =(int)(FinalRed/FinalGreen*255.0f);
nFinalGreen=255;
nFinalBlue =(int)(FinalBlue/FinalGreen*255.0f);
}
else
{
nFinalRed =(int)(FinalRed);
nFinalGreen=(int)(FinalGreen);
nFinalBlue =(int)(FinalBlue);
}
}
else if(FinalBlue>=FinalRed && FinalBlue>=FinalGreen)
{
if(FinalBlue>255.0f)
{
nFinalRed =(int)(FinalRed/FinalBlue*255.0f);
nFinalGreen=(int)(FinalGreen/FinalBlue*255.0f);
nFinalBlue=255;
}
else
{
nFinalRed =(int)(FinalRed);
nFinalGreen=(int)(FinalGreen);
nFinalBlue =(int)(FinalBlue);
}
}
sBGR tempBGR;
tempBGR.r=nFinalRed;
tempBGR.g=nFinalGreen;
tempBGR.b=nFinalBlue;
return tempBGR;
}
pBGR MyGetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight)
{
BITMAPINFO bi;
BOOL bRes;
pBGR buf;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = nWidth;
bi.bmiHeader.biHeight = - nHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
// buf = new sBGR[nWidth * nHeight];
buf = (pBGR) malloc(nWidth * 4 * nHeight);
bRes = GetDIBits(hdc, hBmp, 0, nHeight, buf, &bi, DIB_RGB_COLORS);
if (!bRes) {
// delete [] buf;
free(buf);
buf = 0;
}
return buf;
}
int MySetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight, pBGR buf)
{
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = nWidth ;
bi.bmiHeader.biHeight = - nHeight ;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
return ( SetDIBits(hdc , hBmp ,0, nHeight ,buf,&bi,DIB_RGB_COLORS) );
}
jsgfx.def
Code:
LIBRARY "jsgfx.dll"
EXPORTS
SoftBlt
VB Declare (you'll need to change the path for the Lib keyword as appropriate)
Code:
Private Declare Function SoftBlt Lib "H:\Microsoft Visual Studio\MyProjects\jsgfx\Debug\jsgfx.dll" (ByVal hdcDest As Long, ByVal nLeft As Long, ByVal nTop As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hdcSrc As Long, ByVal hdcSrcMask As Long ) As Long
if you use a control's hdc, the control's AutoRedraw property will need to be set to true, and you'll need to call the update method for the destination control after calling SoftBlit
the function does not currently produce a properly Alpha Blended image. Only SoftBlit is exported.
UPDATE!!!
I fixed the above code. Now it does work as advertised. See also http://www.vbforums.com/showthread.php?postid=1488575 for more information.
Last edited by agent; Jul 29th, 2003 at 11:32 PM.
-
Jul 30th, 2003, 10:00 AM
#16
Frenzied Member
i cant get it to work. look at this code...do you know whats wrong?
Code:
void __stdcall Mandelbrot(HDC hdcDest, double rmin,double rmax,double imin,double imax,double maxit,double maxcolors,int maxcol,int maxrow,double colorrange)
{
long double maxsizesq, deltar, deltai, x, y, xsq, ysq, cr, ci;
long double maxsize=2, color, row, col;
HDC hdcTMPDest = CreateCompatibleDC(hdcDest);
HBITMAP hbTMPDest = CreateCompatibleBitmap(hdcDest, maxcol, maxrow);
SelectObject(hdcTMPDest, hbTMPDest);
BitBlt(hdcTMPDest, 0, 0, maxcol, maxrow, hdcDest, 0, 0, SRCCOPY);
pBGR dibDest = MyGetDibBits(hdcTMPDest, (HBITMAP) GetCurrentObject(hdcTMPDest, OBJ_BITMAP), maxcol, maxrow);
maxsizesq=maxsize*maxsize;
deltar=(rmax-rmin)/(maxcol-1);
deltai=(imax-imin)/(maxrow-1);
for (row=0; row<maxrow+1; row++)
{
for (col=0; col<maxcol+1; col++)
{
x=0;
y=0;
ci=(imin+row*deltai);
cr=(rmin+col*deltar);
color=0;
do
{
color++;
xsq=x*x;
ysq=y*y;
if ((xsq+ysq)<(maxsizesq))
{
y=x*2*y+ci;
x=xsq-ysq+cr;
}
}
while ((color<maxit)&&((xsq+ysq)<(maxsizesq)));
if (color>=maxit)
{
dibDest[int(row * maxcol + col)].r = 0;
dibDest[int(row * maxcol + col)].g = 0;
dibDest[int(row * maxcol + col)].b = 0;
}
else
{
int tempcolor=16777215*(maxcolors/color);
dibDest[int(row * maxcol + col)].r = tempcolor;
dibDest[int(row * maxcol + col)].g = tempcolor;
dibDest[int(row * maxcol + col)].b = tempcolor;
}
}
}
HDC hdcTmp = CreateCompatibleDC(hdcDest);
HBITMAP hbTmp = CreateCompatibleBitmap(hdcDest, maxcol, maxrow);
SelectObject(hdcTmp, hbTmp);
MySetDibBits(hdcTmp, hbTmp, maxcol, maxrow, dibDest);
BitBlt(hdcDest, 0, 0, maxcol, maxrow, hdcTmp, 0, 0, SRCCOPY);
DeleteObject(hbTMPDest);
DeleteObject(hbTmp);
DeleteDC(hdcTMPDest);
DeleteDC(hdcTmp);
free(dibDest);
}
also do you know how to convert this into c++ code?
VB Code:
Red = Color And 255
Green = (Color And 65280) \ 256
Blue = (Color And 16711680) \ 65535
-
Jul 30th, 2003, 02:56 PM
#17
Frenzied Member
for (row=0; row<maxrow+1; row++)
for (col=0; col<maxcol+1; col++)
here's the problem...i want setting pixels outside of the array!
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|