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;
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, COLOR, *LPCOLOR;
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 AlphaBlendPixels(Color p1, Color p2, BYTE alpha = 255)
{
double a1f = double(p1.Alpha) / 255,
a2f = double(p2.Alpha) / 255,
a0f = a1f + a2f * (1.0 - a1f);
BYTE Red = (p1.Red * a1f + p2.Red * a2f * (1.0 - a1f)) / a0f;
BYTE Green = (p1.Green * a1f + p2.Green * a2f * (1.0 - a1f)) / a0f;
BYTE Blue = (p1.Blue * a1f + p2.Blue * a2f * (1.0 - a1f)) / a0f;
BYTE Alpha =alpha;
Color clr = RGBA(Red,Green,Blue, Alpha);
return clr;
}
class Bitmap
{
public:
unsigned int Width =0;
unsigned int Height =0;
Color *Pixels=NULL;
Color *PixelsResult=NULL;
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))
{
int BufferSize = SizeWidth * SizeHeight * sizeof(Color);
if(BufferMemory) Disposed();
BufferMemory = VirtualAlloc(0, BufferSize,MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
Pixels =static_cast<Color *> (BufferMemory);
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);
}
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 )
{
HBRUSH color = CreateSolidBrush(RGB(0,255,0));
SelectObject(HDCDestination,color);
Ellipse(HDCBitmap, 0,0,50,50);
for(unsigned int Y =0; Y<Height; Y++)
{
for(unsigned int X =0; X<Width; X++)
{
Pixels[Y*Width + X].Alpha = AlphaValue;
}
}
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);
int BufferSize = Width * Height * sizeof(Color);
PixelsResult =(Color*) VirtualAlloc(0, BufferSize,MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
for(unsigned int Y =0; Y<Height; Y++)
{
for(unsigned int X =0; X<Width; X++)
{
Color TopPixel;
TopPixel.Alpha =Pixels[Y*Width + X].Alpha;
TopPixel.Red = Pixels[Y*Width + X].Red;
TopPixel.Green = Pixels[Y*Width + X].Green;
TopPixel.Blue = Pixels[Y*Width + X].Blue;
COLORREF RREFColor = ::GetPixel(HDCDestination, PosX+X, PosY+Y);
Color BottomPixel=RGBA(GetRValue(RREFColor),GetGValue(RREFColor),GetBValue(RREFColor),255);
PixelsResult[Y*Width+X] = AlphaBlendPixels(TopPixel, BottomPixel ,AlphaValue );
}
}
StretchDIBits(HDCDestination,PosX,PosY+100, Width, Height,0,0,Width, Height,PixelsResult,&BitInfo,DIB_RGB_COLORS,SRCCOPY);
VirtualFree(PixelsResult, 0,MEM_RELEASE);
DeleteObject(color);
}
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(0,0,0,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;
}
}
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;
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);
Sleep(10);
i++;
//if(i==255) i=255/2;
cout << to_string(i)<< "\t";
}while(!GetAsyncKeyState(VK_ESCAPE));
return 0;
}
now heres the result: