#include "StdAfx.h"
#include 
#include 
#include 
// important constants
const float PI = 3.14159f; //5358979;
const float Trans=(3.14159535 / 180);//Convert to radians becase te computer can not read degrees
const float Pd2=(3.14159535 / 2);//Same

// generate monocrome mask...
void _stdcall MakeMask(HDC srcHDC, long cWidth, long cHeight, HDC destHDC, long srcX, long srcY, unsigned long transColor, long MtColor,long MoColor) {
	
		for (long y=0;y<=cHeight;y++)
		{ //begin loop
			
			for (long x=0;x<=cWidth;x++)	
			{  // for each pixel..
				
				if (GetPixel(srcHDC,x,y)==transColor) //we have a transparent pixel
					SetPixelV(destHDC,x,y,MtColor);

				else //non-transparent pixel
					SetPixelV(destHDC,x,y,MoColor);


			} //end loop 1
		} // end loop 2
}

// 2D distance Calculation
float _stdcall Distance2D (int x1, int y1, int x2, int y2)
{
	int dx = (x1 - x2), dy = (y1 - y2);
	return (float)sqrt(dx * dx + dy * dy);
}
//End Function



// 3D distance calculation...
float _stdcall Distance3D (int x1, int y1, int z1, int x2, int y2, int z2)
{
	int dx = (x1 - x2), dz = (z1 - z2), dy = (y1 - y2);
	return (float)sqrt(dx * dx + dy * dy + dz * dz);
}
// End Function




// rotation (fast)
void _stdcall RotateAA (HDC HdestDC, HDC HsrcDC, long int srcW, long int srcH, long int destW, long int destH, long int theta) {

// HsrcDC is the source HDC (in c++ this isn't a long, its an HDC)
// HdestDC is the destination HDC (same thing goes here too)

// srcW is the width, in pixels of the source image
// srcH is the height, in pixels of the source image

// destW is the width, in pixels, of the destination DC
// destH is the height, in pixels, of the destination DC
// theta is the angle of rotation

	long int c1x=(srcW / 2);
	long int c1y=(srcH / 2);
	long int c2x=(destW / 2);
	long int c2y=(destH / 2);
	long int n=0;

	float p1x = 0;
	float p1y = 0;
	float p2x = 0;
	float p2y = 0;

    float a=0;
	float r=0;
	double thet2 = (theta * Trans);
	float ApT2=0;
    
	// the following are colors (note for when porting to C++, these should be declared as ColorRef)
    COLORREF c0=0;
	COLORREF c1=0;
	COLORREF c2=0;
	COLORREF c3=0;

	// start actual code, done declaring vars
	//==========================================================

	//If c2x < c2y Then n = c2y Else n = c2x
	if (c2x < c2y)
		n = c2y;
	else
		n = c2x;

	n = ((n - 1) * 2) / 2;

		//For p2x = 0 To n
		for (p2x=0;p2x<=n;p2x++)
		{ // begin loop...
			//For p2y = 0 To n
			for (p2y=0;p2y<=n;p2y++)
			{  // begin inner loop
			  
				//If p2x = 0 Then a = Pd2 Else a = Atn(p2y / p2x)
				if (p2x==0)
					a = Pd2;
				else
					a = atan(p2y / p2x);

				//r = Sqr(p2x * p2x + p2y * p2y)
				r = sqrt(p2x * p2x + p2y * p2y);

				//  ApT = (a + thet2)
                // p1x = r * Cos(ApT) 'used to be (a + theta) written twice
                // p1y = r * Sin(ApT)
				ApT2 = (a + thet2);
					p1x = r * cos(ApT2);
					p1y = r * sin(ApT2);

			//retrieve pixel color
            c0 = GetPixel(HsrcDC, (c1x + p1x), (c1y + p1y));
            c1 = GetPixel(HsrcDC, (c1x - p1x), (c1y - p1y));
            c2 = GetPixel(HsrcDC, (c1x + p1y), (c1y - p1x));
            c3 = GetPixel(HsrcDC, (c1x - p1y), (c1y + p1x));

		 // set pixel color if needed
         if (c0!=-1)
			 SetPixelV(HdestDC, c2x + p2x, c2y + p2y, c0);
		 if (c1!=-1)
			 SetPixelV(HdestDC, c2x - p2x, c2y - p2y, c1);
		 if (c2!=-1)
			 SetPixelV(HdestDC, c2x + p2y, c2y - p2x, c2);
         if (c3!=-1)
			 SetPixelV(HdestDC, c2x - p2y, c2y + p2x, c3);


			} // end nested for loop

		} // end outer for loop...

}

void __stdcall GEpixelate (HDC hSrcDC, long srcWidth, long srcHeight, long CellSize, HDC hDestDC) {
//        ((srcWidth + (CellDiam \ 2)) \ CellDiam) * CellDiam
long maxX=((srcWidth + (CellSize / 2)) / CellSize) * CellSize;
long maxY=((srcHeight + (CellSize / 2)) / CellSize) * CellSize;
long CpX=0;

//This following statement should be called
//before executing this function:
// DeleteObject(SelectObject(hDestDC,CreatePen(5,1,0)));

	for (long x = 0; x <= maxX; x += CellSize)
	{ //begin loop
		CpX = (x + CellSize + 1);
		for (long y = 0; y <= maxY; y += CellSize)
		{ //begin inner loop
			DeleteObject(SelectObject(hDestDC,CreateSolidBrush(GetPixel(hSrcDC,x,y))));
			//Rectangle hdcDest, Xc, Yc, CpX, Yc + CellDiam + 1
			Rectangle(hDestDC,x,y,CpX,(y + CellSize + 1));
		} // end inner loop
	} // end outer loop

}


void __stdcall GERotateSprite (HANDLE hDIB, HANDLE hDIBd, char* bSrcBytes, long SRCbyteCount, HDC hDestDC, char* bDestBytes, long DESTbyteCount, long Angle) {

//	long int SH=(*SRCbi24BitInfo).bmiHeader.biHeight;
//	long int SW=(*SRCbi24BitInfo).bmiHeader.biWidth;
	
//	long int DH=(*DESTbi24BitInfo).bmiHeader.biHeight;
//	long int DW=(*DESTbi24BitInfo).bmiHeader.biWidth;
	
// This lets us use the bitmapinfo from the DIB handle
	
	BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
	BITMAPINFO &bmInfoD = *(LPBITMAPINFO)hDIBd ;

	char* SBO = bSrcBytes;  //original values of pointers (to reference back to the beggining of the array)
	char* DBO = bDestBytes;

	long int c1x = bmInfo.bmiHeader.biWidth / 2;
	long int c1y=  bmInfo.bmiHeader.biHeight / 2;
	long int c2x=  bmInfoD.bmiHeader.biWidth / 2;
	long int c2y=  bmInfoD.bmiHeader.biHeight / 2;
	long int n=((c1x - 1) * 2) / 2L;


	float p1x=0;
	float p1y=0;
	float p2x=0;
	float p2y=0;

    float a=0;
	float r=0;
	float theta = (Angle * Trans);
	float ApT2=0;
	
	long int PCoord=0L;
	long int PCoord2=0L;

	//For p2x = 0 To n
	for (p2x=0;p2x<=n;p2x++)
	{ // begin loop...
			//For p2y = 0 To n
			for (p2y=0;p2y<=n;p2y++)
		{  // begin inner loop


				//If p2x = 0 Then a = Pd2 Else a = Atn(p2y / p2x)
				if (p2x==0)
					a = Pd2;
				else
					a = atan(p2y / p2x);

				//r = Sqr(p2x * p2x + p2y * p2y)
				r = sqrt(p2x * p2x + p2y * p2y);

				//  ApT = (a + theta)
                // p1x = r * Cos(ApT) 'used to be (a + theta) written twice
                // p1y = r * Sin(ApT)
				ApT2 = (a + theta);
					p1x = r * cos(ApT2);
					p1y = r * sin(ApT2);
					

//  'BOTTOM-RIGHT
		
		PCoord = ((( bmInfo.bmiHeader.biHeight - (c1y + p1y)) * bmInfo.bmiHeader.biHeight + (c1x + p1x)) * 3) - 2;
				if(((PCoord + 1) < SRCbyteCount) && (PCoord > 0))
				{
					  //move to pixel position in array, start at blue byte
					  bDestBytes += (long)(((bmInfoD.bmiHeader.biHeight - (c2y + p2y + 1)) * bmInfoD.bmiHeader.biHeight + (c2x + p2x)) * 3) + 1;
					  bSrcBytes += PCoord;
					  //Use memcpy to copy one pointer to another
					  //set blue byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1);			//blue
					  
					  //move to green byte
					  bDestBytes++;
					  bSrcBytes++;
					  //set green byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1);		    //green

					  //move to red byte
					  bDestBytes++;
					  bSrcBytes++;
					  //set red byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1); 	    //red
				}

				//reset pointers to the beggining of the array
				bDestBytes = DBO;
				bSrcBytes = SBO;
//TOP-LEFT
		PCoord = (((bmInfo.bmiHeader.biHeight - (c1y - p1y)) * bmInfo.bmiHeader.biHeight + (c1x - p1x)) * 3) - 2;
				if(((PCoord + 1) < SRCbyteCount) && (PCoord > 0))
				{
					bDestBytes += (long)(((bmInfoD.bmiHeader.biHeight - (c2y - p2y)) * bmInfoD.bmiHeader.biHeight + (c2x - p2x)) * 3) - 2;
					bSrcBytes += PCoord;
					//set blue byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1);			//blue
					  
					  //move to green byte
					  bDestBytes++;
					  bSrcBytes++;
					  //set green byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1);		    //green

					  //move to red byte
					  bDestBytes++;
					  bSrcBytes++;
					  //set red byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1); 	    //red
				}

				//reset pointers to the beggining of the array
				bDestBytes = DBO;
				bSrcBytes = SBO;

//TOP-RIGHT
		PCoord = (((bmInfo.bmiHeader.biHeight - (c1y - p1x)) * bmInfo.bmiHeader.biHeight + (c1x + p1y)) * 3) - 2;
				if(((PCoord + 1) < SRCbyteCount) && (PCoord > 0))
				{
					bDestBytes += (long)(((bmInfoD.bmiHeader.biHeight - (c2y - p2x)) * bmInfoD.bmiHeader.biHeight + (c2x + p2y)) * 3) + 1;
					bSrcBytes += PCoord;
					//set blue byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1);			//blue
					  
					  //move to green byte
					  bDestBytes++;
					  bSrcBytes++;
					  //set green byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1);		    //green

					  //move to red byte
					  bDestBytes++;
					  bSrcBytes++;
					  //set red byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1); 	    //red
				}

				//reset pointers to the beggining of the array
				bDestBytes = DBO;
				bSrcBytes = SBO;

//BOTTOM-LEFT
		PCoord = (((bmInfo.bmiHeader.biHeight - (c1y + p1x)) * bmInfo.bmiHeader.biHeight + (c1x - p1y)) * 3) - 2;
				if(((PCoord + 1) < SRCbyteCount) && (PCoord > 0))
				{
					bDestBytes += (long)(((bmInfoD.bmiHeader.biHeight - (c2y + p2x + 1)) * bmInfoD.bmiHeader.biHeight + (c2x - p2y)) * 3) - 2;
					bSrcBytes += PCoord;
					//set blue byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1);			//blue
					  
					  //move to green byte
					  bDestBytes++;
					  bSrcBytes++;
					  //set green byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1);		    //green

					  //move to red byte
					  bDestBytes++;
					  bSrcBytes++;
					  //set red byte
					  memcpy(bDestBytes,bSrcBytes,strlen(bSrcBytes)+1); 	    //red
				}

		} //end inner loop

	} //end outer loop

//LPVOID lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
SetDIBitsToDevice(hDestDC, 0, 0, bmInfo.bmiHeader.biWidth, bmInfo.bmiHeader.biHeight, 0, 0, 0, bmInfo.bmiHeader.biHeight, bDestBytes, (LPBITMAPINFO)hDIB, 0);
}

//Function to rotate any sprite using the DIB, will rotate by bytes(not sure if thats right)
//Function DIB_rotate Converted by Josh Nixon and Created by Tim Miron
void _stdcall DIB_rotate(BITMAPINFO SRCbi24BitInfo, unsigned char bSrcBytes[], long SRCbyteCount,
           HDC hDestDC, BITMAPINFO DESTbi24BitInfo, unsigned char bDestBytes[],
           long DESTbyteCount, long angle) 
		   
//Begin functions code
{

//_______________________________________________________________________________________________
//Things that should be done by the owner program:
//EG.
//BITMAPINFO bitmap;
// gets passed to this function as SRCbi24BitInfo

//iDC = CreateCompatibleDC(0);
//iBitmap = CreateDIBSection(iDC, bitmap, DIB_RGB_COLORS, ByVal 0&, ByVal 0&, ByVal 0&);
//SelectObject iDC, iBitmap;
//________________________________________________________________________________________________

//IDC and iBitmap are not needed by this function
// because it bypasses that layer of the GDI and
// only deals with the bitarray, HOWEVER - IMPORTANT:
// that last step of creating the diBitmap object
// and selecting it into the source DC is VERY important!
// or else it wont work: NOTE: use DeleteObject and
// deleteDC to delete the source & destination diBitmap
// objects aswell as the DC...


//retrieve source bits
//GetDIBits iDC, iBitmap, 0, bitmap.bmiHeader.biHeight, bBytes(1), bitmap, DIB_RGB_COLORS
//bBytes() is passed to us as BsrcBYTES()
//_________________________________________________________________________________________

//do the same thing for the destination buffer
//note for C++ porting: same variable declaration as
//the first rotation sub, but plus the definition of bbytes!
    long c1x = 0.0, c1y = 0.0;
    long c2x = 0.0, c2y = 0.0;
    short a = 0.0; 
    long p1x = 0.0,p1y = 0.0;
    long p2x = 0.0, p2y = 0.0;
    long n = 0.0, double R = 0.0;
    
	short theta = 0.0; // this is angle * trans
    short ApT2 = 0.0; //A + theta (value=0 at declaration)

    long PCoord = 0.0, PCoord2 = 0.0;
	
// MUCH OF THE BELOW VARIABLE SETUP
//CAN BE THE EXACT SAME AS IN THE EARLIER
//C++ VERSION OF THIS FUNCTION...
//IMPORTANT NOTICE, THE COLORS ARE NOT COLORREFS ANYMORE!
//DOWN TO THE SETUP OF N
    theta=angle * Trans;

    theta = (angle * Trans);
    
    // Correct != is the same as <>
    
    //these can also be calculated when declared
    //(center of destination)
    
	c1x = (SRCbi24BitInfo.bmiHeader.biWidth / 2);
    c1y = (SRCbi24BitInfo.bmiHeader.biHeight / 2);
    c2x = (DESTbi24BitInfo.bmiHeader.biWidth / 2);
    c2y = (DESTbi24BitInfo.bmiHeader.biHeight / 2);
    
    n = (c1x - 1);// / 2
    // n = (c1x - 1) / 2
    //#####
    
    //n is used to determine when the for loops
    //including the nested loop should end...
    //THE END OF THE SETUP OF VARIABLES

    for (p2x = 0; p2x <= n; p2x++){//Begin outter loop
	for (p2y = 0; p2y <= n; p2y++){//Begin nested loop
        if (p2x = 0) 
		 a = Pd2;
		
		else 
		{
		     //TO BE optimzed by Tim on a later date

			 a = atan(p2y / p2x); //in c++ this = atan;
           //r = Sqr(1 * p2x * p2x + 1 * p2y * p2y)
             R = sqrt((p2x * p2x) + (p2y * p2y));
            
            //minor optimization (avoid doing the same calculation twice)
            // NOTE: this value can NOT be set when its declared
            // because the value of A changes in every cycle of this loop
            
			    ApT2 = (a + theta);
                p1x = R * cos(ApT2); //used to be (a + theta) written twice
                p1y = R * sin(ApT2);
            //retrieve pixel color
            //c0& = GetPixel(HsrcDC, c1x + p1x, c1y + p1y)
            
    //BOTTOM-RIGHT
   PCoord = (((SRCbi24BitInfo.bmiHeader.biHeight - (c1y + p1y)) * SRCbi24BitInfo.bmiHeader.biHeight + (c1x + p1x)) * 3) - 2;
    if (  (PCoord + 1) < SRCbyteCount  && (PCoord > 0))
	{
       
       //by eliminating these in-between
       //variables C0[r][g][b]
       //we eliminate 3 copy operators
       //per pixel, AND 9 variable declarations,
       //AND we avoid processing any pixels outside
       //of the rotation's 'edges'..
       //(however, that may cause some problems
       //and actually make thigns take longer
       //if the program has to use a bigger
       //sprite just to make sure there's enough
       //padding to fill the edges properly, so I
       //am questioning whether to keep this or not?)
       
       PCoord2 = (((DESTbi24BitInfo.bmiHeader.biHeight - (c2y + p2y + 1)) * DESTbi24BitInfo.bmiHeader.biHeight + (c2x + p2x)) * 3) + 1;
       bDestBytes[PCoord2] = bSrcBytes[PCoord];     //blue
       bDestBytes[PCoord2 + 1] = bSrcBytes[PCoord + 1]; //green
       bDestBytes[PCoord2 + 2] = bSrcBytes[PCoord + 2]; //red
    }//end if 
         
      
    //Top Left
    PCoord = (((SRCbi24BitInfo.bmiHeader.biHeight - (c1y - p1y)) * SRCbi24BitInfo.bmiHeader.biHeight + (c1x - p1x)) * 3) - 2;
    if ( (PCoord + 1) < SRCbyteCount && (PCoord > 0) )
	{
        //TOP-LEFT
         PCoord2 = (((DESTbi24BitInfo.bmiHeader.biHeight - (c2y - p2y)) * DESTbi24BitInfo.bmiHeader.biHeight + (c2x - p2x)) * 3) - 2;
         bDestBytes[PCoord2] = bSrcBytes[PCoord];            //blue
         bDestBytes[PCoord2 + 1] = bSrcBytes[PCoord + 1];    //green
         bDestBytes[PCoord2 + 2] = bSrcBytes[PCoord + 2];    //red
    }//end if 
         
         
    //top-right
    PCoord = (((SRCbi24BitInfo.bmiHeader.biHeight - (c1y - p1x)) * SRCbi24BitInfo.bmiHeader.biHeight + (c1x + p1y)) * 3) - 2;
    if ( (PCoord + 1) < SRCbyteCount && (PCoord > 0))
	{
         //TOP RIGHT
         PCoord2 = (((DESTbi24BitInfo.bmiHeader.biHeight - (c2y - p2x)) * DESTbi24BitInfo.bmiHeader.biHeight + (c2x + p2y)) * 3) + 1;
         bDestBytes[PCoord2] = bSrcBytes[PCoord];     //blue
         bDestBytes[PCoord2 + 1] = bSrcBytes[PCoord + 1]; //green
         bDestBytes[PCoord2 + 2] = bSrcBytes[PCoord + 2]; //red
    }//end if 
    
    //bottom-left!
    PCoord = (((SRCbi24BitInfo.bmiHeader.biHeight - (c1y + p1x)) * SRCbi24BitInfo.bmiHeader.biHeight + (c1x - p1y)) * 3) - 2;
    if ( (PCoord + 1) < SRCbyteCount && (PCoord > 0))
	{
        //BOTTOM-LEFT
         PCoord2 = (((DESTbi24BitInfo.bmiHeader.biHeight - (c2y + p2x + 1)) * DESTbi24BitInfo.bmiHeader.biHeight + (c2x - p2y)) * 3) - 2;
         bDestBytes[PCoord2] = bSrcBytes[PCoord];    //blue
         bDestBytes[PCoord2 + 1] = bSrcBytes[PCoord + 1]; //green
         bDestBytes[PCoord2 + 2] = bSrcBytes[PCoord + 2]; //red
    }//end if 

	}//end nested loop
    }//end outer loop
    //changed index number of bits from 1 to 0
SetDIBitsToDevice(hDestDC, 0, 0, SRCbi24BitInfo.bmiHeader.biWidth, SRCbi24BitInfo.bmiHeader.biHeight, 0, 0, 0, SRCbi24BitInfo.bmiHeader.biHeight, bDestBytes[1], SRCbi24BitInfo, DIB_RGB_COLORS);
	}
}//End the function

    Source: geocities.com/nit3shift