Results 1 to 17 of 17

Thread: Per-pixel alpha blend function math [Resolved]

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662

    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.

  2. #2
    Ex-Super Mod'rater Electroman's Avatar
    Join Date
    Sep 2000
    Location
    Newcastle, England
    Posts
    4,349
    VB Code:
    1. 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.

  3. #3
    Ex-Super Mod'rater Electroman's Avatar
    Join Date
    Sep 2000
    Location
    Newcastle, England
    Posts
    4,349
    I'll rewrite it to match your variables:
    VB Code:
    1. 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.

  4. #4
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    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!
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  5. #5
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    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
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  6. #6
    Ex-Super Mod'rater Electroman's Avatar
    Join Date
    Sep 2000
    Location
    Newcastle, England
    Posts
    4,349
    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.

  7. #7

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    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++
    Code:
    HDC hdcDest
    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));

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    Originally posted by Electroman
    I'll rewrite it to match your variables:
    VB Code:
    1. 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.

  9. #9
    Ex-Super Mod'rater Electroman's Avatar
    Join Date
    Sep 2000
    Location
    Newcastle, England
    Posts
    4,349
    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.

  10. #10
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    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:
    1. 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.
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    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.

  12. #12
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    yes! i can hardly wait
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  13. #13
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    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?
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  14. #14

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    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.

  15. #15

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    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.

  16. #16
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    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:
    1. Red = Color And 255
    2. Green = (Color And 65280) \ 256
    3. Blue = (Color And 16711680) \ 65535
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  17. #17
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    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!
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width