// GDIRotate.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include <math.h>
#include "resource.h"
#include <stdlib.h>
#include <stdio.h>
#include "comdef.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
float g_angle = 0.2f; // The current Rotation angle
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_GDIROTATE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_GDIROTATE);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_GDIROTATE);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCSTR)IDC_GDIROTATE;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
// Initialize the Timer to 100 ms delay between screen updates
SetTimer(hWnd, 10, 100, 0);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
// Helper function for getting the minimum of 4 floats
float min4(float a, float b, float c, float d)
{
if (a < b) {
if (c < a) {
if (d < c)
return d;
else
return c;
} else {
if (d < a)
return d;
else
return a;
}
} else {
if (c < b) {
if (d < c)
return d;
else
return c;
} else {
if (d < b)
return d;
else
return b;
}
}
}
// Helper function for getting the maximum of 4 floats
float max4(float a, float b, float c, float d)
{
if (a > b) {
if (c > a) {
if (d > c)
return d;
else
return c;
} else {
if (d > a)
return d;
else
return a;
}
} else {
if (c > b) {
if (d > c)
return d;
else
return c;
} else {
if (d > b)
return d;
else
return b;
}
}
}
// 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)
// Returns the DI (Device Independent) bits of the Bitmap
// Here I use 32 bit since it's easy to adress in memory and no
// padding of the horizontal lines is required.
pBGR MyGetDibBits(HDC hdcSrc, HBITMAP hBmpSrc, int nx, int ny)
{
BITMAPINFO bi;
BOOL bRes;
pBGR buf;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = nx;
bi.bmiHeader.biHeight = - ny;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = nx * 4 * ny;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
buf = (pBGR) malloc(nx * 4 * ny);
bRes = GetDIBits(hdcSrc, hBmpSrc, 0, ny, buf, &bi, DIB_RGB_COLORS);
if (!bRes) {
free(buf);
buf = 0;
}
return buf;
}
// RotateMemoryDC rotates a memory DC and returns the rotated DC as well as its dimensions
void RotateMemoryDC(HBITMAP hBmpSrc, HDC hdcSrc, int SrcX, int SrcY, float angle, HDC &hdcDst, int &dstX, int &dstY)
{
HBITMAP hBmpDst;
float x1, x2, x3, x4, y1, y2, y3, y4, cA, sA;
float CtX, CtY, orgX, orgY, divisor;
int OfX, OfY;
int stepX, stepY;
int iorgX, iorgY;
RECT rt;
char s[40];
LARGE_INTEGER lStart, lEnd, lFreq;
pBGR src, dst, dstLine;
BITMAPINFO bi;
// Rotate the bitmap around the center
CtX = ((float) SrcX) / 2;
CtY = ((float) SrcY) / 2;
// First, calculate the destination positions for the four courners to get dstX and dstY
cA = (float) cos(angle);
sA = (float) sin(angle);
x1 = CtX + (-CtX) * cA - (-CtY) * sA;
x2 = CtX + (SrcX - CtX) * cA - (-CtY) * sA;
x3 = CtX + (SrcX - CtX) * cA - (SrcY - CtY) * sA;
x4 = CtX + (-CtX) * cA - (SrcY - CtY) * sA;
y1 = CtY + (-CtY) * cA + (-CtX) * sA;
y2 = CtY + (SrcY - CtY) * cA + (-CtX) * sA;
y3 = CtY + (SrcY - CtY) * cA + (SrcX - CtX) * sA;
y4 = CtY + (-CtY) * cA + (SrcX - CtX) * sA;
OfX = ((int) floor(min4(x1, x2, x3, x4)));
OfY = ((int) floor(min4(y1, y2, y3, y4)));
dstX = ((int) ceil(max4(x1, x2, x3, x4))) - OfX;
dstY = ((int) ceil(max4(y1, y2, y3, y4))) - OfY;
// Create the new memory DC
hdcDst = CreateCompatibleDC(hdcSrc);
hBmpDst = CreateCompatibleBitmap(hdcSrc, dstX, dstY);
SelectObject(hdcDst, hBmpDst);
// Fill the new memory DC with the current Window color
rt.left = 0;
rt.top = 0;
rt.right = dstX;
rt.bottom = dstY;
FillRect(hdcDst, &rt, GetSysColorBrush(COLOR_WINDOW));
// Start timing
QueryPerformanceFrequency(&lFreq);
QueryPerformanceCounter(&lStart);
// Get the bitmap bits for the source and destination
src = MyGetDibBits(hdcSrc, hBmpSrc, SrcX, SrcY);
dst = MyGetDibBits(hdcDst, hBmpDst, dstX, dstY);
dstLine = dst;
divisor = cA*cA + sA*sA;
// Step through the destination bitmap
for (stepY = 0; stepY < dstY; stepY++) {
for (stepX = 0; stepX < dstX; stepX++) {
// Calculate the source coordinate
orgX = (cA * (((float) stepX + OfX) + CtX * (cA - 1)) + sA * (((float) stepY + OfY) + CtY * (sA - 1))) / divisor;
orgY = CtY + (CtX - ((float) stepX + OfX)) * sA + cA *(((float) stepY + OfY) - CtY + (CtY - CtX) * sA);
iorgX = (int) orgX;
iorgY = (int) orgY;
if ((iorgX >= 0) && (iorgY >= 0) && (iorgX < SrcX) && (iorgY < SrcY)) {
// Inside the source bitmap -> copy the bits
dstLine[dstX - stepX - 1] = src[iorgX + iorgY * SrcX];
} else {
// Outside the source -> set the color to light grey
dstLine[dstX - stepX - 1].b = 240;
dstLine[dstX - stepX - 1].g = 240;
dstLine[
- 1
- 2
- 3
- 4
前往页