Article ID: 186589
Article Last Modified on 2/22/2007
#define SHIFTS 15 // Extend ints to limit round-off error. #define THRESH (1 << SHIFTS) // Threshold for pixel size value.
/* CopySourceToDest()
*
* Re-map a rectangular area into an area defined by four vertices.
*
* This function does all the real re-mapping work by recursively
* dividing both the source and destination areas until the
* area specified by the destination is a single pixel. At this
* point, it copies the pixel from the source to the destination.
*
* By quartering both the source and the destination areas, the
* relationship between the area in the source and the area in the
* destination is preserved.
*
* NOTES:
* This function would be much faster if it were implemented to
* directly manipulate the surface bits of a DIB section rather than
* using GetPixel() / SetPixel().
*/
void CopySourceToDest(HDC hdcDst, POINT ul, POINT ur, POINT lr,
POINT ll, HDC hdcSrc, LONG x1, LONG y1,
LONG x2, LONG y2)
{
POINT tm,lm,rm,bm,m;
LONG mx,my;
// Does the destination area specify a single pixel?
if ((abs(ul.x - ur.x) < THRESH) &&
(abs(ul.x - lr.x) < THRESH) &&
(abs(ul.x - ll.x) < THRESH) &&
(abs(ul.y - ur.y) < THRESH) &&
(abs(ul.y - lr.y) < THRESH) &&
(abs(ul.y - ll.y) < THRESH))
{ // Yes.
COLORREF cr;
cr = GetPixel(hdcSrc, (x1 >> SHIFTS), (y1 >> SHIFTS)); SetPixel(hdcDst, (ul.x >> SHIFTS), (ul.y >> SHIFTS), cr); } else { // No // Quarter the source and the destination, and then recurse. tm.x = (ul.x + ur.x) >> 1; tm.y = (ul.y + ur.y) >> 1; bm.x = (ll.x + lr.x) >> 1; bm.y = (ll.y + lr.y) >> 1;
lm.x = (ul.x + ll.x) >> 1; lm.y = (ul.y + ll.y) >> 1; rm.x = (ur.x + lr.x) >> 1; rm.y = (ur.y + lr.y) >> 1;
m.x = (tm.x + bm.x) >> 1; m.y = (tm.y + bm.y) >> 1;
mx = (x1 + x2) >> 1; my = (y1 + y2) >> 1;
CopySourceToDest(hdcDst, ul, tm, m, lm, hdcSrc, x1, y1, mx, my); CopySourceToDest(hdcDst, tm, ur, rm, m, hdcSrc, mx, y1, x2, my); CopySourceToDest(hdcDst, m, rm, lr, bm, hdcSrc, mx, my, x2, y2); CopySourceToDest(hdcDst, lm, m, bm, ll, hdcSrc, x1, my, mx, y2); };
};
/* WarpBlt()
*
* Re-map a rectangular area into an area defined by four vertices .
*
*/
void WarpBlt(HDC hdcDst, POINT ul, POINT ur, POINT lr, POINT ll,
HDC hdcSrc, LONG x1, LONG y1, LONG x2, LONG y2)
{
// Shift all values to help reduce round-off error.
ul.x <<= SHIFTS;
ul.y <<= SHIFTS;
ur.x <<= SHIFTS;
ur.y <<= SHIFTS;
lr.x <<= SHIFTS; lr.y <<= SHIFTS; ll.x <<= SHIFTS; ll.y <<= SHIFTS;
x1 <<= SHIFTS; y1 <<= SHIFTS; x2 <<= SHIFTS; y2 <<= SHIFTS;
CopySourceToDest(hdcDst, ul, ur, lr, ll, hdcSrc, x1, y1, x2, y2);
}
/* DemonstrateWarpBlt()
*
* Re-map the image of the entire screen into an area
* defined by four random vertices .
*
*/
void DemonstrateWarpBlt(HWND hWnd)
{
HDC hdcScreen = GetDC(NULL); // Source DC.
HDC hdcWindow = GetDC(hWnd); // Destination DC.
POINT ul,ur,lr,ll; // Vertices for the destination area.
int iXRes, iYRes; // Extents of the screen.
RECT rc; // Extents of the window.
// Get the size of the screen.
iXRes = GetDeviceCaps(hdcScreen, HORZRES);
iYRes = GetDeviceCaps(hdcScreen, VERTRES);
// Get the size of our client area.
GetClientRect(hWnd, &rc);
// Define a random destination area that fits in the client area.
ul.x = rand() % rc.right;
ul.y = rand() % rc.bottom;
ur.x = rand() % rc.right;
ur.y = rand() % rc.bottom;
lr.x = rand() % rc.right;
lr.y = rand() % rc.bottom;
ll.x = rand() % rc.right;
ll.y = rand() % rc.bottom;
// Copy the entire screen into the destination area.
WarpBlt(hdcWindow, ul, ur, lr, ll,
hdcScreen, 0, 0, iXRes, iYRes);
}
Additional query words: kbDSupport kbdsd kbGDI kbBitmap kbDevContext kbDisplay
Keywords: kbcode kbhowto KB186589