ImgProc: C/C++ Version
/****************************************************************************\
* *
* ImgProc.c *
* *
* This program demonstrates several of the Fastgraph for Windows image *
* processing functions. *
* *
\****************************************************************************/
#include
#include
#include
#include "ImgProc.h"
LRESULT CALLBACK WindowProc(HWND,UINT,WPARAM,LPARAM);
void OpenClick(void);
void SaveAsClick(void);
void DetailsClick(void);
void UndoClick(void);
void RestoreOriginalClick(void);
void ContrastEnhancementClick(void);
void GammaCorrectionClick(void);
void GrayscaleClick(void);
void PhotoInversionClick(void);
void SwitchBuffers(void);
char DefaultExt[4];
BYTE FileHeader[128];
char FileName[256];
char mbString[256];
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdParam, int iCmdShow)
{
static char szAppName[] = "FGimgproc";
HWND hWnd;
MSG msg;
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
RegisterClassEx(&wndclass);
hWnd = CreateWindow(szAppName, // window class name
"Image Processing Demo", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hWnd,iCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
/****************************************************************************\
* *
* WindowProc() *
* *
\****************************************************************************/
HCURSOR hCursor;
HDC hDC;
HMENU hMenu;
HPALETTE hPal;
int hVB, hVBoriginal, hVBundo;
UINT cxClient, cyClient;
int cxBuffer, cyBuffer;
int nColors;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
switch (iMsg)
{
case WM_CREATE:
hDC = GetDC(hWnd);
fg_setdc(hDC);
hPal = fg_defpal();
fg_realize(hPal);
// initialize the virtual buffer environment
fg_vbinit();
fg_vbdepth(24);
// create the main virtual buffer for the working copy of the image
cxBuffer = cyBuffer = 32;
hVB = fg_vballoc(cxBuffer,cyBuffer);
fg_vbopen(hVB);
// create two additional virtual buffers -- one for a copy of the original
// image, and one used for the undo operation
hVBoriginal = fg_vballoc(cxBuffer,cyBuffer);
hVBundo = fg_vballoc(cxBuffer,cyBuffer);
// start with a window full of white pixels
fg_setcolor(-1);
fg_fillpage();
hMenu = GetMenu(hWnd);
return 0;
case WM_COMMAND:
switch (wParam)
{
case IDM_File_Open:
OpenClick();
return 0;
case IDM_File_SaveAs:
SaveAsClick();
return 0;
case IDM_File_Details:
DetailsClick();
return 0;
case IDM_File_Exit:
DestroyWindow(hWnd);
return 0;
case IDM_Edit_Undo:
UndoClick();
return 0;
case IDM_Edit_RestoreOriginal:
RestoreOriginalClick();
return 0;
case IDM_Edit_ContrastEnhancement:
ContrastEnhancementClick();
return 0;
case IDM_Edit_GammaCorrection:
GammaCorrectionClick();
return 0;
case IDM_Edit_Grayscale:
GrayscaleClick();
return 0;
case IDM_Edit_PhotoInversion:
PhotoInversionClick();
return 0;
}
break;
case WM_PAINT:
BeginPaint(hWnd,&ps);
fg_vbscale(0,cxBuffer-1,0,cyBuffer-1,0,cxClient-1,0,cyClient-1);
EndPaint(hWnd,&ps);
return 0;
case WM_SETFOCUS:
fg_realize(hPal);
InvalidateRect(hWnd,NULL,TRUE);
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_DESTROY:
fg_vbclose();
fg_vbfree(hVB);
fg_vbfree(hVBoriginal);
fg_vbfree(hVBundo);
fg_vbfin();
DeleteObject(hPal);
ReleaseDC(hWnd,hDC);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,iMsg,wParam,lParam);
}
/****************************************************************************\
* *
* Event handlers for the items on the File menu. *
* *
\****************************************************************************/
void OpenClick()
{
static OPENFILENAME fn;
static char FilterAll[] =
"All image files (*.bmp,*.jpg,*.pcx)\0*.BMP;*.JPG;*.PCX\0" \
"BMP files (*.bmp)\0*.BMP\0" \
"JPEG files (*.jpg)\0*.JPG\0" \
"PCX files (*.pcx)\0*.PCX\0\0";
// fill in structure fields for Open File dialog box
fn.lStructSize = sizeof(OPENFILENAME);
fn.hwndOwner = GetActiveWindow();
fn.lpstrFilter = FilterAll;
fn.lpstrCustomFilter = NULL;
fn.nFilterIndex = 0;
fn.lpstrFile = FileName;
fn.nMaxFile = sizeof(FileName);
fn.lpstrFileTitle = NULL;
fn.lpstrInitialDir = NULL;
fn.lpstrTitle = NULL;
fn.Flags = OFN_READONLY;
fn.lpstrDefExt = NULL;
*FileName = '\0';
// open the bmp, jpeg, or pcx image file
if (!GetOpenFileName(&fn)) return;
lstrcpy(FileName,fn.lpstrFile);
// check for a bmp file
if (fg_bmphead(FileName,FileHeader) == 0)
{
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
ShowCursor(TRUE);
nColors = fg_bmppal(FileName,NULL);
fg_bmpsize(FileHeader,&cxBuffer,&cyBuffer);
SwitchBuffers();
fg_showbmp(FileName,0);
lstrcpy(DefaultExt,"bmp");
}
// check for a jpeg file
else if (fg_jpeghead(FileName,FileHeader) == 0)
{
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
ShowCursor(TRUE);
nColors = 0;
fg_jpegsize(FileHeader,&cxBuffer,&cyBuffer);
SwitchBuffers();
fg_showjpeg(FileName,0);
lstrcpy(DefaultExt,"pcx");
}
// check for a pcx file
else if (fg_pcxhead(FileName,FileHeader) == 0)
{
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
ShowCursor(TRUE);
nColors = fg_pcxpal(FileName,NULL);
fg_pcxsize(FileHeader,&cxBuffer,&cyBuffer);
SwitchBuffers();
fg_move(0,0);
fg_showpcx(FileName,FG_AT_XY);
lstrcpy(DefaultExt,"pcx");
}
// the file is not a valid bmp, jpeg, or pcx file
else
{
lstrcpy(mbString,FileName);
lstrcat(mbString,"\nis not a recognized image file.");
MessageBox(GetActiveWindow(),mbString,"Error",MB_ICONSTOP|MB_OK);
return;
}
// make a copy of the original image
fg_copypage(hVB,hVBoriginal);
// display the image
fg_vbscale(0,cxBuffer-1,0,cyBuffer-1,0,cxClient-1,0,cyClient-1);
ShowCursor(FALSE);
SetCursor(hCursor);
// enable remaining items on the File menu, and the image processing
// items on the Edit menu
EnableMenuItem(hMenu,IDM_File_SaveAs,MF_ENABLED);
EnableMenuItem(hMenu,IDM_File_Details,MF_ENABLED);
EnableMenuItem(hMenu,IDM_Edit_Undo,MF_GRAYED);
EnableMenuItem(hMenu,IDM_Edit_RestoreOriginal,MF_GRAYED);
EnableMenuItem(hMenu,IDM_Edit_ContrastEnhancement,MF_ENABLED);
EnableMenuItem(hMenu,IDM_Edit_GammaCorrection,MF_ENABLED);
EnableMenuItem(hMenu,IDM_Edit_Grayscale,MF_ENABLED);
EnableMenuItem(hMenu,IDM_Edit_PhotoInversion,MF_ENABLED);
}
//---------------------------------------------------------------------------
void SaveAsClick()
{
static OPENFILENAME fn;
// fill in structure fields for Save File dialog box
fn.lStructSize = sizeof(OPENFILENAME);
fn.hwndOwner = GetActiveWindow();
fn.lpstrCustomFilter = NULL;
fn.nFilterIndex = 0;
fn.lpstrFile = FileName;
fn.nMaxFile = sizeof(FileName);
fn.lpstrFileTitle = NULL;
fn.lpstrInitialDir = NULL;
fn.lpstrTitle = NULL;
fn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT |
OFN_PATHMUSTEXIST;
fn.lpstrDefExt = DefaultExt;
// save image as a bmp file (original image was bmp)
if (lstrcmp(DefaultExt,"bmp") == 0)
{
fn.lpstrFilter = "BMP files (*.bmp)\0*.BMP\0\0";
lstrcpy(strrchr(FileName,'.'),".bmp");
if (!GetSaveFileName(&fn)) return;
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
ShowCursor(TRUE);
fg_makebmp(0,cxBuffer-1,0,cyBuffer-1,24,FileName);
nColors = 0;
ShowCursor(FALSE);
SetCursor(hCursor);
}
// save image as a pcx file (original image was jpeg or pcx)
else if (lstrcmp(DefaultExt,"pcx") == 0)
{
fn.lpstrFilter = "PCX files (*.pcx)\0*.PCX\0\0";
lstrcpy(strrchr(FileName,'.'),".pcx");
if (!GetSaveFileName(&fn)) return;
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
ShowCursor(TRUE);
fg_makepcx(0,cxBuffer-1,0,cyBuffer-1,FileName);
nColors = 0;
ShowCursor(FALSE);
SetCursor(hCursor);
}
}
//---------------------------------------------------------------------------
void DetailsClick()
{
// display the original image resolution and color depth
if (nColors > 0)
wsprintf(mbString,"%s\n%dx%d pixels\n%d colors",
(LPSTR)FileName,cxBuffer,cyBuffer,nColors);
else
wsprintf(mbString,"%s\n%dx%d pixels\n24-bit RGB",
(LPSTR)FileName,cxBuffer,cyBuffer);
MessageBox(GetActiveWindow(),mbString,"Information",MB_ICONINFORMATION|MB_OK);
}
/****************************************************************************\
* *
* Event handlers for the items on the Edit menu. *
* *
\****************************************************************************/
void UndoClick()
{
// undo the previous image processing operation
fg_copypage(hVBundo,hVB);
fg_vbscale(0,cxBuffer-1,0,cyBuffer-1,0,cxClient-1,0,cyClient-1);
EnableMenuItem(hMenu,IDM_Edit_Undo,MF_GRAYED);
EnableMenuItem(hMenu,IDM_Edit_RestoreOriginal,MF_ENABLED);
}
//---------------------------------------------------------------------------
void RestoreOriginalClick()
{
// restore the original image
fg_copypage(hVB,hVBundo);
fg_copypage(hVBoriginal,hVB);
fg_vbscale(0,cxBuffer-1,0,cyBuffer-1,0,cxClient-1,0,cyClient-1);
EnableMenuItem(hMenu,IDM_Edit_Undo,MF_ENABLED);
EnableMenuItem(hMenu,IDM_Edit_RestoreOriginal,MF_GRAYED);
}
//---------------------------------------------------------------------------
void ContrastEnhancementClick()
{
// perform a contrast enhancement transform on the active virtual buffer
fg_copypage(hVB,hVBundo);
fg_move(0,cyBuffer-1);
fg_contvb(63,192,cxBuffer,cyBuffer);
fg_vbscale(0,cxBuffer-1,0,cyBuffer-1,0,cxClient-1,0,cyClient-1);
EnableMenuItem(hMenu,IDM_Edit_Undo,MF_ENABLED);
EnableMenuItem(hMenu,IDM_Edit_RestoreOriginal,MF_ENABLED);
}
//---------------------------------------------------------------------------
void GammaCorrectionClick()
{
// perform a gamma correction transform on the active virtual buffer
fg_copypage(hVB,hVBundo);
fg_move(0,cyBuffer-1);
fg_gammavb(0.45,cxBuffer,cyBuffer);
fg_vbscale(0,cxBuffer-1,0,cyBuffer-1,0,cxClient-1,0,cyClient-1);
EnableMenuItem(hMenu,IDM_Edit_Undo,MF_ENABLED);
EnableMenuItem(hMenu,IDM_Edit_RestoreOriginal,MF_ENABLED);
}
//---------------------------------------------------------------------------
void GrayscaleClick()
{
// perform a grayscale transform on the active virtual buffer
fg_copypage(hVB,hVBundo);
fg_move(0,cyBuffer-1);
fg_grayvb(cxBuffer,cyBuffer);
fg_vbscale(0,cxBuffer-1,0,cyBuffer-1,0,cxClient-1,0,cyClient-1);
EnableMenuItem(hMenu,IDM_Edit_Undo,MF_ENABLED);
EnableMenuItem(hMenu,IDM_Edit_RestoreOriginal,MF_ENABLED);
}
//---------------------------------------------------------------------------
void PhotoInversionClick()
{
// perform a photo-inversion transform on the active virtual buffer
fg_copypage(hVB,hVBundo);
fg_move(0,cyBuffer-1);
fg_photovb(cxBuffer,cyBuffer);
fg_vbscale(0,cxBuffer-1,0,cyBuffer-1,0,cxClient-1,0,cyClient-1);
EnableMenuItem(hMenu,IDM_Edit_Undo,MF_ENABLED);
EnableMenuItem(hMenu,IDM_Edit_RestoreOriginal,MF_ENABLED);
}
/****************************************************************************\
* *
* SwitchBuffers() *
* *
* Close the and release the virtual buffers for the current image, then *
* create and open new virtual buffers for the new image file. *
* *
\****************************************************************************/
void SwitchBuffers(void)
{
fg_vbclose();
fg_vbfree(hVB);
fg_vbfree(hVBoriginal);
fg_vbfree(hVBundo);
hVB = fg_vballoc(cxBuffer,cyBuffer);
fg_vbopen(hVB);
hVBoriginal = fg_vballoc(cxBuffer,cyBuffer);
hVBundo = fg_vballoc(cxBuffer,cyBuffer);
}
|