C++: how calculate alphablend?

Joaquim Miguel Jesus 1 Reputation point
2022-04-11T21:55:08.633+00:00

We have 2 array pointers pixels.
How combine, using math, the 2 pixels for get the alphablend? And the same for stretch?

C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,544 questions
{count} votes

7 answers

Sort by: Most helpful
  1. Joaquim Miguel Jesus 1 Reputation point
    2022-04-22T10:54:43.437+00:00

    on main():
    //just for show and draw something:
    void SimpleConstantAlphaBlend(HDC hDC)
    {
    const int size = 100;

      for (int i=0; i<3; i++)  
      {  
        RECT  rect = { i*(size+10) + 20, 20+size/3,  
                   i*(size+10) + 20 + size, 20+size/3 + size };  
      
        COLORREF Color[]={ RGB(0xFF,0,0), RGB(0,0xFF,0), RGB(0,0,0xFF) };  
      
        HBRUSH hBrush = CreateSolidBrush(Color[i]);  
        FillRect(hDC, & rect, hBrush);  // three original solid rectangles  
        DeleteObject(hBrush);  
      
        BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255/2, 0 }; // alpha 0.5  
        blend.SourceConstantAlpha=120;  
      
        AlphaBlend(hDC, 360+((3-i)%3)*size/3, 20+i*size/3, size, size,  
                   hDC, i*(size+10)+20, 20+size/3, size, size, blend);  
      }  
    }  
      
      
    int main()  
    {  
      
      
        HWND HWNDConsoleWindow = GetConsoleWindow();  
        HDC HDCConsoleWindow = GetDC(HWNDConsoleWindow);  
        Bitmap Bit(100,100);  
        BYTE i=0;  
        HBRUSH clr = CreateSolidBrush(RGB(255,255,255));  
         RECT rect ={0,0,50,50};  
      
            FillRect(Bit.HDCBitmap,&rect,clr);  
            GetDIBits(Bit.HDCBitmap,Bit.HBitmap,0,Bit.Height,Bit.Pixels,&Bit.BitInfo,DIB_RGB_COLORS);  
        do  
        {  
      
            SimpleConstantAlphaBlend(HDCConsoleWindow);//draw some rectangles and half of them are AlphaBlend  
            //Bit is an image with a circle and the backcolor alpha value is 0 for transparent  
      
            Bit.Draw(HDCConsoleWindow, 100,100,i);  
            i++;  
        }while(!GetAsyncKeyState(VK_ESCAPE));  
        DeleteObject(clr);  
        return 0;  
    }  
    

    result:
    195473-image.png

    i see the white fill rectangle... but no a little of red and green rectangles :(
    i'm confused why the function don't do the job :(
    it's slow with GetPixel() and SetPixel(), but i'm testing the function

    0 comments No comments

  2. Joaquim Miguel Jesus 1 Reputation point
    2022-04-22T11:03:42.61+00:00

    better and test the entire code... just run the code:
    #include <iostream>
    #include <windows.h>
    #include <cmath>
    #include <stdlib.h>
    #include <vector>
    #include <string>
    #include <algorithm>

    #define M_PI           3.14159265358979323846  /* pi */
    
    using  namespace std;
    typedef std::vector<std::vector<unsigned int>>  Vect2D ;
    
    
    struct Color
    {
        BYTE Blue=0;
        BYTE Green=0;
        BYTE Red=0;
        BYTE Alpha=0;
    
        Color()
        {
            ;
        }
        Color(COLORREF clr)
        {
            Blue=GetBValue (clr);
            Green=GetGValue (clr);
            Red=GetRValue (clr);
            Alpha=0;
        }
    
        void RGBA(BYTE R, BYTE G, BYTE B, BYTE A)
        {
            Blue=B;
            Green=G;
            Red=R;
            Alpha=A;
        }
        operator COLORREF()
        {
            return RGB(Red,Green, Blue);
        }
    }*LPColor, Pixel, *LPPixel;
    
    Color RGBA(BYTE R, BYTE G, BYTE B, BYTE A)
    {
        Color clr;
        clr.RGBA(R,G,B,A);
        return clr;
    }
    
    struct Position2D
    {
        Position2D()
        {
            //Nothing;
        }
    
        Position2D(float X, float Y)
        {
            PosX = X;
            PosY = Y;
        }
        float PosX = 0;
        float PosY = 0;
    };
    
    struct Position3D
    {
        float PosX = 0;
        float PosY = 0;
        float PosZ = 0;
    
        Position3D()
        {
            //Nothing;
        }
    
        Position3D(float X, float Y, float Z)
        {
            PosX = X;
            PosY = Y;
            PosZ = Z;
        }
    
        operator Position2D()
        {
            return {PosX, PosY};
        }
    
    };
    
    std::vector<Position3D> GetLinePoints(Position3D Origin, Position3D Destination)
    {
        //Getting the Line Points Count:
        int LineCountPoints = sqrt(abs(Destination.PosX - Origin.PosX) * abs(Destination.PosX - Origin.PosX)
                                      + abs(Destination.PosY - Origin.PosY) * abs(Destination.PosY - Origin.PosY)
                                      + abs(Destination.PosZ - Origin.PosZ) * abs(Destination.PosZ - Origin.PosZ));
    
        //Get the increment for X, Y and Z:
        Position3D Increment;
        Increment.PosX = (Destination.PosX - Origin.PosX) / LineCountPoints;
        Increment.PosY = (Destination.PosY - Origin.PosY) / LineCountPoints;
        Increment.PosZ = (Destination.PosZ - Origin.PosZ) / LineCountPoints;
    
        Position3D NextPoint=Origin;
    
        std::vector<Position3D> GetPoints;
        GetPoints.push_back(Origin);
        for(int LinePoint =0 ; LinePoint<LineCountPoints; LinePoint++)
        {
            //Get the next point:
            NextPoint.PosX += Increment.PosX;
            NextPoint.PosY += Increment.PosY;
            NextPoint.PosZ += Increment.PosZ;
    
            //Round the values:
            Position3D Pos3D;
            Pos3D.PosX = ceil(NextPoint.PosX);
            Pos3D.PosY = ceil(NextPoint.PosY);
            Pos3D.PosZ = ceil(NextPoint.PosZ);
            /*if(Pos3D.PosX <Origin.PosX && Pos3D.PosX > Destination.PosX) break;
            if(Pos3D.PosY <Origin.PosY && Pos3D.PosY > Destination.PosY) break;
            if(Pos3D.PosZ <Origin.PosZ && Pos3D.PosZ > Destination.PosZ) break;*/
            //Add the 3D position on vector:
            GetPoints.push_back(Pos3D);
        }
        return GetPoints;
    }
    
    Color MathAlphBlend(Color color, Color background, BYTE AlphaValue)
    {
        BYTE oneminusalpha = 1 - AlphaValue;
    
        BYTE newR = ((color.Red * AlphaValue) + (oneminusalpha * background.Red));
        BYTE newG = ((color.Green * AlphaValue) + (oneminusalpha * background.Green));
        BYTE newB = ((color.Blue * AlphaValue) + (oneminusalpha * background.Blue));
        return RGBA(newR, newG, newB,AlphaValue);
    }
    
    class Bitmap
    {
        public:
            unsigned int Width =0;
            unsigned int Height =0;
            Color *Pixels=NULL;
            Color *PixelsResult=NULL;
            Color clrBackColor;
            HBITMAP HBitmap=NULL;
            HBITMAP OldHBitmap =NULL;
            HDC HDCBitmap;
            BITMAPINFO BitInfo;
            void *BufferMemory=NULL;
    
            Bitmap(unsigned int SizeWidth, unsigned int SizeHeight, Color BackColor=RGBA(0,0,0,0))
            {
                New(SizeWidth,SizeHeight,BackColor);
            }
            void Disposed()
            {
                Pixels=NULL;
                VirtualFree(BufferMemory, 0,MEM_RELEASE);
                SelectObject(HDCBitmap, OldHBitmap);
                DeleteDC(HDCBitmap);
                DeleteObject(HBitmap);
            }
    
            void New(unsigned int SizeWidth, unsigned int SizeHeight, Color BackColor=RGBA(0,0,0,0))
            {
                clrBackColor=BackColor;
                int BufferSize = SizeWidth * SizeHeight * sizeof(Color);
    
                if(BufferMemory) Disposed();
                BufferMemory = VirtualAlloc(0, BufferSize,MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
                Pixels =static_cast<Color *> (BufferMemory);
                PixelsResult=VirtualAlloc(0, BufferSize,MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    
                Width = SizeWidth;
                Height = SizeHeight;
                ZeroMemory(&BitInfo, sizeof(BITMAPINFO));
                BitInfo.bmiHeader.biSize = sizeof(BitInfo.bmiHeader);
                BitInfo.bmiHeader.biWidth = Width;
                BitInfo.bmiHeader.biHeight = -Height;
                BitInfo.bmiHeader.biPlanes = 1;
                BitInfo.bmiHeader.biBitCount = 32;
                BitInfo.bmiHeader.biCompression = BI_RGB;
                //BitInfo.bmiHeader.biSizeImage =  BitInfo.bmiHeader.biWidth  * (-BitInfo.bmiHeader.biHeight)* sizeof(RGBQUAD);
                HBitmap = CreateBitmap(Width, Height,1,32,Pixels);
                HDCBitmap = CreateCompatibleDC(NULL);
                OldHBitmap= (HBITMAP)SelectObject(HDCBitmap, HBitmap);
                Clear(BackColor);
    
    
                ///.........
                HBRUSH color = CreateSolidBrush(RGB(0,255,0));
                SelectObject(HDCBitmap,color);
                Ellipse(HDCBitmap, 0,0,50,50);
                SetDIBits(HDCBitmap,HBitmap,0,Height,Pixels,&BitInfo,DIB_RGB_COLORS);
            }
    
            void Clear(Color BackColor)
            {
                if(!BufferMemory) return;
                for(unsigned int PosY=0; PosY<Height; PosY++)
                {
                    for(unsigned int PosX=0; PosX<Width; PosX++)
                    {
                        Pixels[PosY*Width + PosX].Red =BackColor.Red;
                        Pixels[PosY*Width + PosX].Green =BackColor.Green;
                        Pixels[PosY*Width + PosX].Blue =BackColor.Blue;
                        Pixels[PosY*Width + PosX].Alpha = BackColor.Alpha;
                    }
                }
                SetDIBits(HDCBitmap,HBitmap,0,Height,Pixels,&BitInfo,DIB_RGB_COLORS);
            }
    
            void Draw(HDC HDCDestination, int PosX, int PosY, BYTE AlphaValue=0 )
            {
    
    
    
                for(unsigned int Y =0; Y<Height; Y++)
                {
                    for(unsigned int X =0; X<Width; X++)
                    {
                        if(Pixels[Y*Width+ X]==clrBackColor) continue;
                           Color Result =MathAlphBlend(Pixels[Y*Width+ X],::GetPixel(HDCDestination,PosX,PosY),AlphaValue);
                           ::SetPixel(HDCDestination, X+PosX, Y+PosY+100,RGB(Result.Red, Result.Green, Result.Blue));
                    }
                }
                /*BLENDFUNCTION bf;
                bf.AlphaFormat = AC_SRC_ALPHA;//use Alpha pixels... TransparentBlt()
                bf.BlendFlags = 0;
                bf.BlendOp = AC_SRC_OVER;
                bf.SourceConstantAlpha = AlphaValue;// use the AlphaBlend for all pixels
                AlphaBlend(HDCDestination, PosX, PosY, Width*2, Height*2,HDCBitmap, 0,0,Width, Height, bf);*/
    
            }
    
            void SetPixel(unsigned int PosX, unsigned int PosY, COLORREF Color)
            {
                if(BufferMemory)
                {
                    if(PosX>=Width|| PosX<0) PosX = Width-1;
                    if(PosY>=Height || PosY<0) PosY = Height-1;
                    Pixels[PosY*Width + PosX].Red =GetRValue(Color);
                    Pixels[PosY*Width + PosX].Green =GetGValue(Color);
                    Pixels[PosY*Width + PosX].Blue =GetBValue(Color);
                }
                SetDIBits(HDCBitmap,HBitmap,0,Height,Pixels,&BitInfo,DIB_RGB_COLORS);
            }
    
            Color GetPixel(unsigned int PosX, unsigned int PosY)
            {
                if(BufferMemory)
                {
                    if(PosX>=Width|| PosX<0) PosX = Width-1;
                    if(PosY>=Height || PosY<0) PosY = Height-1;
                    return Pixels[PosY*Width + PosX];
                }
            }
    
            void DrawLine3D(Position3D Origin, Position3D Destination, Color LineColor=RGBA(255,255,255,255))
            {
                if(!BufferMemory) return;
                std::vector<Position3D> GetLineDots = GetLinePoints(Origin, Destination);
                for(unsigned int x=0; x<GetLineDots.size()-1; x++)
                {
                    unsigned int PosX = GetLineDots[x].PosX;
                    unsigned int PosY = GetLineDots[x].PosY;
                    if(PosX>=Width|| PosX<0) PosX = Width-1;
                    if(PosY>=Height || PosY<0) PosY = Height-1;
                    Pixels[PosY*Width + PosX].Red =LineColor.Red;
                    Pixels[PosY*Width + PosX].Green =LineColor.Green;
                    Pixels[PosY*Width + PosX].Blue =LineColor.Blue;
                    Pixels[PosY*Width + PosX].Alpha =LineColor.Alpha;
    
                }
                SetDIBits(HDCBitmap,HBitmap,0,Height,Pixels,&BitInfo,DIB_RGB_COLORS);
            }
    };
    
    Position3D RotationPoints(Position3D Position, Position3D RotationPosition, Position3D Angle)
    {
        //Convert Angles in Radians:
        Angle.PosX *= M_PI / 180 ;
        Angle.PosY *= M_PI / 180 ;
        Angle.PosZ *= M_PI / 180 ;
    
        Position3D RotatedPoint;
    
        //for add the Rotation Point
        //we must sub the Rotation point with rotation center:
        Position.PosX -= RotationPosition.PosX;
        Position.PosY -= RotationPosition.PosY;
        Position.PosZ -= RotationPosition.PosZ;
    
    
        //First we rotate the Z:
        RotatedPoint.PosX = Position.PosX * cos(Angle.PosZ)-Position.PosY*sin(Angle.PosZ);
        RotatedPoint.PosY = Position.PosX * sin(Angle.PosZ)+Position.PosY*cos(Angle.PosZ);
        RotatedPoint.PosZ = Position.PosZ;
    
        //Second we rotate the Y:
        RotatedPoint.PosX = RotatedPoint.PosX * cos(Angle.PosY)+RotatedPoint.PosZ*sin(Angle.PosY);
        RotatedPoint.PosY = RotatedPoint.PosY;
        RotatedPoint.PosZ = -RotatedPoint.PosX * sin(Angle.PosY)+RotatedPoint.PosZ*cos(Angle.PosY);
    
        //Third we rotate the X:
        RotatedPoint.PosX = RotatedPoint.PosX;
        RotatedPoint.PosY = RotatedPoint.PosY * cos(Angle.PosX)-RotatedPoint.PosZ*sin(Angle.PosX);
        RotatedPoint.PosZ = RotatedPoint.PosY * sin(Angle.PosX)+RotatedPoint.PosZ*cos(Angle.PosX);
    
        //after rotate the point
        //we add the rotation center:
        RotatedPoint.PosX += RotationPosition.PosX;
        RotatedPoint.PosY += RotationPosition.PosY;
        RotatedPoint.PosZ += RotationPosition.PosZ;
    
        return RotatedPoint;
    }
    
    
    void DrawLine3D(std::vector<std::vector<unsigned int>> &Pixels, Position3D Origin, Position3D Destination, COLORREF Color)
    {
        std::vector<Position3D> GetLineDots = GetLinePoints(Origin, Destination);
        for(unsigned int x=0; x<GetLineDots.size()-1; x++)
        {
            unsigned int X = GetLineDots[x].PosX;
            unsigned int Y = GetLineDots[x].PosY;
    
           Pixels[Y][X] =(unsigned int) Color;
        }
    }
    
    //just for show and draw something:
    void SimpleConstantAlphaBlend(HDC hDC)
    {
      const int size = 100;
    
      for (int i=0; i<3; i++)
      {
        RECT  rect = { i*(size+10) + 20, 20+size/3,
                   i*(size+10) + 20 + size, 20+size/3 + size };
    
        COLORREF Color[]={ RGB(0xFF,0,0), RGB(0,0xFF,0), RGB(0,0,0xFF) };
    
        HBRUSH hBrush = CreateSolidBrush(Color[i]);
        FillRect(hDC, & rect, hBrush);  // three original solid rectangles
        DeleteObject(hBrush);
    
        BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255/2, 0 }; // alpha 0.5
        blend.SourceConstantAlpha=120;
    
        AlphaBlend(hDC, 360+((3-i)%3)*size/3, 20+i*size/3, size, size,
                   hDC, i*(size+10)+20, 20+size/3, size, size, blend);
      }
    }
    
    
    int main()
    {
    
    
        HWND HWNDConsoleWindow = GetConsoleWindow();
        HDC HDCConsoleWindow = GetDC(HWNDConsoleWindow);
        Bitmap Bit(100,100);
        BYTE i=0;
        HBRUSH clr = CreateSolidBrush(RGB(255,255,255));
         RECT rect ={0,0,50,50};
    
            FillRect(Bit.HDCBitmap,&rect,clr);
            GetDIBits(Bit.HDCBitmap,Bit.HBitmap,0,Bit.Height,Bit.Pixels,&Bit.BitInfo,DIB_RGB_COLORS);
        do
        {
    
            SimpleConstantAlphaBlend(HDCConsoleWindow);//draw some rectangles and half of them are AlphaBlend
            //Bit is an image with a circle and the backcolor alpha value is 0 for transparent
    
            Bit.Draw(HDCConsoleWindow, 100,100,i);
            i++;
        }while(!GetAsyncKeyState(VK_ESCAPE));
        DeleteObject(clr);
        return 0;
    }
    
    0 comments No comments