REMOTE.C

/************************************************************************* 
Copyright Microsoft Corp. 1992-1996
Remote Machine WinType sample

FILE : REMOTE.C

PURPOSE : The actual functions on the server side of the RPC
distributed application wintyp that are called from
the client side.

COMMENTS : This sample is made to demonstrate the passing of a
Window Type from the client to the server. The
colordepth in the edge detection funciton is limited
to 256 color because of the simpler algorithm

*************************************************************************/
#include "wintyp.h" // Generated by the MIDL compiler
#include "common.h" // Common definitions for all files
#include <windows.h> // All windows programs must include this file

#define THRESHOLD 75 // Threshold value in findedges function

// Local procedures used only within this file
BYTE **Get2DPointer(BYTE *, LONG, LONG);
void FindEdges(BYTE **, BYTE **, LONG, int, int);
void FlipImage(BYTE **, BYTE **, LONG, int, int);

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function : BOOL ChangeBitmapRemote ()
// Desc. : This function is called from the client side. First it
// allocates space for the data in the image passed from
// the client. Then it will analyze the function call,
// and perform a findedge, or flipimage operation on the
// bitmap passed from the client.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BOOL ChangeBitmapRemote(unsigned short nAction, HBITMAP *hBM)
{
BITMAP sBM; // A structure to load the bitmap data into
BOOL bRetValue; // The value to return from this function
BYTE *pbOldBitmapBits, // Buffer to hold the old values of the bitmap
*pbNewBitmapBits, // Buffer to hold the new values of the bitmap
**pbOldImage, // 2D-pointer to the old image
**pbNewImage; // 2D-pointer to the new image
long nImageSize; // The size of the image in bytes


_tprintf(TEXT("In the remote procedure \'ChangeBitmapRemote\'\n"));
// Obtain information about the BITMAP from the handle to the bitmap
GetObject(*hBM, sizeof(BITMAP), (LPVOID) &sBM);

// Calculate the total number of bytes the image occupies
nImageSize = sBM.bmHeight * sBM.bmWidthBytes;

// Allocate memory for the buffers to store the image data in
if (NULL == (pbOldBitmapBits = (BYTE *) malloc (nImageSize)))
{
_tprintf(TEXT("Memory allocation error"));
return FALSE;
}

if (NULL == (pbNewBitmapBits = (BYTE *) malloc (nImageSize)))
{
_tprintf(TEXT("Memory allocation error"));
return FALSE;
}

// Get the data from the image, and fill into the old image buffer
GetBitmapBits(*hBM, nImageSize, (LPVOID) pbOldBitmapBits);

// Create 2D-array pointers to the image data for easier acces
if(NULL == (pbOldImage = Get2DPointer(pbOldBitmapBits,
sBM.bmHeight, sBM.bmWidthBytes)))
{
return FALSE;
}
if(NULL == (pbNewImage = Get2DPointer(pbNewBitmapBits,
sBM.bmHeight, sBM.bmWidthBytes)))
{
return FALSE;
}


switch(nAction)
{
case FINDEDGE :
FindEdges(pbOldImage,
pbNewImage,
nImageSize,
sBM.bmWidth,
sBM.bmHeight);

// Copy the new image data into the bitmap to return to client
SetBitmapBits(*hBM, nImageSize, (const void *) pbNewBitmapBits);
bRetValue = TRUE;
break;

case FLIPIMAGE:
FlipImage(pbOldImage,
pbNewImage,
nImageSize,
sBM.bmWidthBytes,
sBM.bmHeight);

// Copy the new image data into the bitmap to return to client
SetBitmapBits(*hBM, nImageSize,
(const void *) pbNewBitmapBits);
bRetValue = TRUE;
break;

default :
bRetValue = FALSE;
}

// Deallocate the memory used for the imagebuffers and the 2D-pointers
free(pbOldBitmapBits);
free(pbNewBitmapBits);
free(pbOldImage);
free(pbNewImage);

_tprintf(TEXT("Leaving the remote procedure \'ChangeBitmapRemote\'\n"));

return bRetValue;
}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function : void FindEdges ()
// Desc. : This function finds the edges in a given image by
// using the Sobel edge operators. The image will be
// changed to the edges corresponding to the boundaries
// in it
// Comments : The algorithm used works best on grayscale images, but
// it should produce acceptable results on a 256-color
// image as well
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void FindEdges(BYTE **pbOldImage, // 2D-pointer to existing image
BYTE **pbNewImage, // 2D-pointer to the new image
LONG nImageSize, // The size of the image in bytes
int nWidth, // The width of the image
int nHeight) // The Height of the image
{
int
nIdx1, nIdx2, // Counters in loops
nGx, nGy, // Values found by applying the masks Gx and Gy
nMax = 0; // Max value for the edge




// Go through every pixel in the image, and find the edges
for (nIdx1 = 1; nIdx1 < (nHeight - 1); nIdx1++)
{
for (nIdx2 = 1; nIdx2 < (nWidth - 1); nIdx2++)
{
// Find Gx
nGx =(( (int)pbOldImage[nIdx1+1][nIdx2-1] +
2*(int)pbOldImage[nIdx1+1][nIdx2] +
(int)pbOldImage[nIdx1+1][nIdx2+1] )
-
( (int)pbOldImage[nIdx1-1][nIdx2-1] +
2*(int)pbOldImage[nIdx1-1][nIdx2] +
(int)pbOldImage[nIdx1-1][nIdx2+1] )) / 8;

// Find Gy
nGy =(( (int)pbOldImage[nIdx1-1][nIdx2+1] +
2*(int)pbOldImage[nIdx1][nIdx2+1] +
(int)pbOldImage[nIdx1+1][nIdx2+1] )
-
( (int)pbOldImage[nIdx1-1][nIdx2-1] +
2*(int)pbOldImage[nIdx1][nIdx2-1] +
(int)pbOldImage[nIdx1+1][nIdx2-1] )) / 8;

// Enter value into the new image
pbNewImage[nIdx1][nIdx2] = (BYTE)((abs(nGx) + abs(nGy))/2);
}
}


// Find the max value
for (nIdx1 = 1; nIdx1 < (nHeight-1); nIdx1++)
{
for (nIdx2 = 0; nIdx2 < nWidth; nIdx2++)
{
if (pbNewImage[nIdx1][nIdx2] > nMax)
{
nMax = pbNewImage[nIdx1][nIdx2];
}
}
}

// Normalize every point in the image
for (nIdx1 = 1; nIdx1 < (nHeight-1); nIdx1++)
{
for (nIdx2 = 0; nIdx2 < nWidth; nIdx2++)
{
pbNewImage[nIdx1][nIdx2]=(pbNewImage[nIdx1][nIdx2] * 255)/nMax;
}
}

// Now set every pixel value that is less than a threshold to 0, and
// the rest to 255
for (nIdx1 = 1; nIdx1 < (nHeight-1); nIdx1++)
{
for (nIdx2 = 0; nIdx2 < nWidth; nIdx2++)
{
if(pbNewImage[nIdx1][nIdx2] > THRESHOLD)
{
pbNewImage[nIdx1][nIdx2] = 255;
}
else
{
pbNewImage[nIdx1][nIdx2] = 0;
}
}
}

}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function : void FlipImage ()
// Desc. : This function will flip the image upside down
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void FlipImage(BYTE **pbOldImage, // 2D-pointer to existing image
BYTE **pbNewImage, // 2D-pointer to the new image
LONG nImageSize, // The size of the image in bytes
int nWidth, // The width of the image
int nHeight) // The Height of the image
{
int nIdx1, nIdx2; // Counters in loops

// Copy the old image, line by line, into the new image
for (nIdx1 = 0; nIdx1 < nHeight; nIdx1++)
{
for (nIdx2 = 0; nIdx2 < nWidth; nIdx2++)
{
pbNewImage[nHeight - nIdx1 - 1][nIdx2] =
pbOldImage[nIdx1][nIdx2];
}
}

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function : Get2DPointer(BITMAP *)
// Purpose : This procedure will get a 2D-pointer to the data in the
// bitmap, which is much easier to work with than a single
// pointer.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BYTE **Get2DPointer(BYTE *pbBuffer, LONG nHeight, LONG nWidthBytes)
{
BYTE **pbRetValue; // The return value
int nIdx;

if (NULL == (pbRetValue = (BYTE **) malloc (nHeight * sizeof(BYTE *))))
{
_tprintf(TEXT("Memory allocation error"));
return NULL;
}


for (nIdx = 0; nIdx < nHeight; nIdx++)
pbRetValue[nIdx] = pbBuffer + (nIdx * nWidthBytes);

return pbRetValue;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* Procedure : void ShutDown(void) */
/* Desc. : This procedure send a message to the server that it */
/* can stop listening for remote procedure calls */
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void ShutDown(void)
{
RPC_STATUS nStatus;

/* Tell the server to stop listening for remote procedure calls */
_tprintf(TEXT("Shutting down the server\n"));
nStatus = RpcMgmtStopServerListening(NULL);
EXIT_IF_FAIL(nStatus, "RpcMgmtStopServerListening");
}